1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-04-20 01:16:36 +00:00

Load and run PLFORTH and DRAWL in PLVM

This commit is contained in:
David Schmenk
2024-08-23 13:46:12 -07:00
parent 88981cfd4f
commit 4ee3a2140b
4 changed files with 522 additions and 189 deletions
+84 -152
View File
@@ -31,6 +31,7 @@ byte *lastsym = symtbl;
byte *perr;
uword keybdbuf = 0x0200;
uword heap = 0x0300;
uword cmdsys;
typedef struct {
uword modofst;
uword defaddr;
@@ -373,7 +374,7 @@ uword lookup_sym(byte *dci)
if (trace) printf("\nSymbol %s not found in symbol table\n", str);
return 0;
}
int add_sym(byte *dci, uword addr)
uword add_sym(byte *dci, uword addr)
{
while (*dci & 0x80)
*lastsym++ = *dci++;
@@ -382,7 +383,7 @@ int add_sym(byte *dci, uword addr)
lastsym += 2;
if (lastsym >= &symtbl[SYMTBL_SIZE])
pfail("Symbol table overflow");
return 0;
return addr;
}
/*
* DEF routines - Create entryoint for 6502 that calls out to PLVM or native code
@@ -405,28 +406,28 @@ byte *add_def(byte type, uword haddr, byte *lastdef)
switch (type)
{
case VM_NATV_DEF:
*lastdef++ = VM_NATV_ENTRY & 0xFF;
*lastdef++ = VM_NATV_ENTRY >> 8;
*lastdef++ = (byte)VM_NATV_ENTRY;
*lastdef++ = (byte)(VM_NATV_ENTRY >> 8);
break;
case VM_EXT_DEF:
*lastdef++ = VM_EXT_ENTRY & 0xFF;
*lastdef++ = VM_EXT_ENTRY >> 8;
*lastdef++ = (byte)VM_EXT_ENTRY;
*lastdef++ = (byte)(VM_EXT_ENTRY >> 8);
break;
case VM_DEF:
*lastdef++ = VM_INDIRECT_ENTRY & 0xFF;
*lastdef++ = VM_INDIRECT_ENTRY >> 8;
*lastdef++ = (byte)VM_INDIRECT_ENTRY;
*lastdef++ = (byte)(VM_INDIRECT_ENTRY >> 8);
break;
case VM_INLINE_DEF: // Never happen
*lastdef++ = VM_INLINE_ENTRY & 0xFF;
*lastdef++ = VM_INLINE_ENTRY >> 8;
*lastdef++ = (byte)VM_INLINE_ENTRY;
*lastdef++ = (byte)(VM_INLINE_ENTRY >> 8);
default:
pfail("Add unknown DEF type");
}
//
// Follow with memory handle
//
*lastdef++ = haddr;
*lastdef++ = haddr >> 8;
*lastdef++ = (byte)haddr;
*lastdef++ = (byte)(haddr >> 8);
return lastdef;
}
void xlat_def(uword addr, uword ofst, defxlat_t *defxtbl)
@@ -450,11 +451,11 @@ uword add_natv( VM_Callout natvfn)
add_def(VM_NATV_DEF, handle, mem_6502 + defaddr);
return defaddr;
}
void export_natv(char *symstr, VM_Callout natvfn)
uword export_natv(char *symstr, VM_Callout natvfn)
{
byte dci[16];
stodci(symstr, dci);
add_sym(dci, add_natv(natvfn));
return add_sym(dci, add_natv(natvfn));
}
/*
* Relocation routines.
@@ -761,8 +762,7 @@ int load_mod(M6502 *mpu, byte *mod)
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;
PULL_ESTK(init);
return init;
}
return 0;
@@ -772,6 +772,7 @@ int load_mod(M6502 *mpu, byte *mod)
*/
void sysexecmod(M6502 *mpu)
{
fprintf(stderr, "SYSEXECMOD unimplemented!\n");
}
void syslookuptbl(M6502 *mpu)
{
@@ -780,95 +781,21 @@ void syslookuptbl(M6502 *mpu)
PULL_ESTK(sym);
addr = lookup_sym(mem_6502 + sym);
PUSH_ESTK(addr);
if (trace) printf("LOOKUPSYM\n");
}
void sysputc(M6502 *mpu)
void syscall6502(M6502 *mpu)
{
char c;
//
// Pop char and putchar it
//
PULL_ESTK(c);
putchar(c);
}
void sysputs(M6502 *mpu)
{
uword strptr;
int i;
char ch;
uword params;
byte cmd, status;
//
// Pop string pointer off stack, copy into C string, and puts it
//
PULL_ESTK(strptr);
for (i = 1; i <= mem_6502[strptr]; i++)
PULL_ESTK(params);
PULL_ESTK(cmd);
status = 0;
switch (cmd)
{
ch = mem_6502[strptr + i] & 0x7F;
switch (ch)
{
case '\r':
case '\n':
putchar('\n');
break;
default:
putchar(ch);
}
}
}
void sysputln(M6502 *mpu)
{
putchar('\n');
}
void sysputi(M6502 *mpu)
{
word print;
//
// Pop int off stack, copy into C string, and print it
//
PULL_ESTK(print);
printf("%d", print);
}
void sysputb(M6502 *mpu)
{
word prbyte;
//
// Pop byte off stack, copy into C string, and print it
//
PULL_ESTK(prbyte);
printf("%02X", prbyte & 0xFF);
}
void sysputh(M6502 *mpu)
{
word prhex;
//
// Pop int off stack, copy into C string, and print it
//
PULL_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);
fprintf(stderr, "SYSCALL6502 unimplemented!\n");
PUSH_ESTK(status);
}
void systoupper(M6502 *mpu)
{
@@ -876,30 +803,33 @@ void systoupper(M6502 *mpu)
PULL_ESTK(c);
c = toupper(c);
PUSH_ESTK(c);
if (trace) printf("TOUPPER\n");
}
void sysstrcpy(M6502 *mpu)
{
uword src, dst;
PULL_ESTK(dst);
PULL_ESTK(src);
memcpy(mem_6502 + dst, mem_6502 + src, mem_6502[src]);
PULL_ESTK(dst);
memcpy(mem_6502 + dst, mem_6502 + src, mem_6502[src] + 1);
PUSH_ESTK(dst);
if (trace) printf("STRCPY\n");
}
void sysstrcat(M6502 *mpu)
{
uword src, dst;
PULL_ESTK(dst);
PULL_ESTK(src);
PULL_ESTK(dst);
memcpy(mem_6502 + dst + mem_6502[dst] + 1, mem_6502 + src + 1, mem_6502[src] - 1);
mem_6502[dst] += mem_6502[src];
PUSH_ESTK(dst);
if (trace) printf("STRCAT\n");
}
void sysmemset(M6502 *mpu)
{
uword dst, val, size;
PULL_ESTK(dst);
PULL_ESTK(val);
PULL_ESTK(size);
PULL_ESTK(val);
PULL_ESTK(dst);
while (size > 1)
{
mem_6502[dst++] = (byte)val;
@@ -908,32 +838,36 @@ void sysmemset(M6502 *mpu)
}
if (size)
mem_6502[dst] = (byte)val;
if (trace) printf("MEMSET\n");
}
void sysmemcpy(M6502 *mpu)
{
uword dst, src, size;
PULL_ESTK(dst);
PULL_ESTK(src);
PULL_ESTK(size);
PULL_ESTK(src);
PULL_ESTK(dst);
memcpy(mem_6502 + dst, mem_6502 + src, size);
if (trace) printf("MEMCPY\n");
}
void sysheapmark(M6502 *mpu)
{
PUSH_ESTK(heap);
if (trace) printf("HEAPMARK\n");
}
void sysheapallocalign(M6502 *mpu)
{
uword size, pow2, align, addr, freeaddr;
PULL_ESTK(size);
PULL_ESTK(pow2);
PULL_ESTK(freeaddr);
PULL_ESTK(pow2);
PULL_ESTK(size);
align = (1 << pow2) - 1;
mem_6502[freeaddr] = (byte)heap;
mem_6502[freeaddr + 1] = (byte)(heap >> 8);
addr = (heap + align) & ~align;
heap += size;
PUSH_ESTK(addr);
if (trace) printf("HEAPALLOCALIGN\n");
}
void sysheapalloc(M6502 *mpu)
{
@@ -942,55 +876,65 @@ void sysheapalloc(M6502 *mpu)
PULL_ESTK(size);
addr = alloc_heap(size);
PUSH_ESTK(addr);
if (trace) printf("HEAPALLOC\n");
}
void sysheaprelease(M6502 *mpu)
{
uword avail, vm_fp = UWORD_PTR(&mem_6502[FP]);
PULL_ESTK(heap);
avail = vm_fp - heap;
PUSH_ESTK(avail);
if (trace) printf("HEAPRELEASE\n");
}
void sysheapavail(M6502 *mpu)
{
uword avail = avail_heap();
PUSH_ESTK(avail);
if (trace) printf("HEAPAVAIL\n");
}
void sysisugt(M6502 *mpu)
{
uword a, b;
word result;
PULL_ESTK(a);
PULL_ESTK(b);
PULL_ESTK(a);
result = a > b ? -1 : 0;
PUSH_ESTK(result);
if (trace) printf("ISUGT\n");
}
void sysisult(M6502 *mpu)
{
uword a, b;
word result;
PULL_ESTK(a);
PULL_ESTK(b);
PULL_ESTK(a);
result = a < b ? -1 : 0;
PUSH_ESTK(result);
if (trace) printf("ISULT\n");
}
void sysisuge(M6502 *mpu)
{
uword a, b;
word result;
PULL_ESTK(a);
PULL_ESTK(b);
PULL_ESTK(a);
result = a >= b ? -1 : 0;
PUSH_ESTK(result);
if (trace) printf("ISUGE\n");
}
void sysisule(M6502 *mpu)
{
uword a, b;
word result;
PULL_ESTK(a);
PULL_ESTK(b);
PULL_ESTK(a);
result = a <= b ? -1 : 0;
PUSH_ESTK(result);
if (trace) printf("ISULE\n");
}
void syssext(M6502 *mpu)
{
@@ -1000,15 +944,6 @@ void syssext(M6502 *mpu)
a = a & 0x0080 ? (a | 0xFF00) : (a & 0x00FF);
PUSH_ESTK(a);
}
void sysdivmod(M6502 *mpu)
{
word prhex;
//
// Pop int off stack, copy into C string, and print it
//
PULL_ESTK(prhex);
printf("%04X", prhex);
}
/*
* CMDSYS exports
*/
@@ -1016,8 +951,9 @@ void export_cmdsys(void)
{
byte dci[16];
uword defaddr;
uword cmdsys = alloc_heap(23);
uword machid = alloc_heap(1);
cmdsys = alloc_heap(23);
stodci("CMDSYS", dci); add_sym(dci, cmdsys);
mem_6502[SYSPATH_STR] = strlen(strcat(getcwd((char *)mem_6502 + SYSPATH_BUF, 128), "/sys/"));
mem_6502[cmdsys + 0] = 0x11; // Version 2.11
mem_6502[cmdsys + 1] = 0x02;
@@ -1028,18 +964,6 @@ void export_cmdsys(void)
defaddr = add_natv(sysexecmod); // sysexecmod
mem_6502[cmdsys + 6] = (byte)defaddr;
mem_6502[cmdsys + 7] = (byte)(defaddr >> 8);
defaddr = add_natv(sysopen); // sysopen
mem_6502[cmdsys + 8] = (byte)defaddr;
mem_6502[cmdsys + 9] = (byte)(defaddr >> 8);
defaddr = add_natv(sysclose); // sysclose
mem_6502[cmdsys + 10] = (byte)defaddr;
mem_6502[cmdsys + 11] = (byte)(defaddr >> 8);
defaddr = add_natv(sysread); // sysread
mem_6502[cmdsys + 12] = (byte)defaddr;
mem_6502[cmdsys + 13] = (byte)(defaddr >> 8);
defaddr = add_natv(syswrite); // syswrite
mem_6502[cmdsys + 14] = (byte)defaddr;
mem_6502[cmdsys + 15] = (byte)(defaddr >> 8);
perr = mem_6502 + cmdsys + 16; *perr = 0;
mem_6502[cmdsys + 17] = 0; // jitcount
mem_6502[cmdsys + 18] = 0; // jitsize
@@ -1048,18 +972,6 @@ void export_cmdsys(void)
defaddr = add_natv(syslookuptbl); // syslookuptbl
mem_6502[cmdsys + 21] = (byte)defaddr;
mem_6502[cmdsys + 22] = (byte)(defaddr >> 8);
mem_6502[machid] = 0xF2; // Apple ///
stodci("CMDSYS", dci); add_sym(dci, cmdsys);
stodci("MACHID", dci); add_sym(dci, machid);
export_natv("PUTC", sysputc);
export_natv("PUTS", sysputs);
export_natv("PUTLN", sysputln);
export_natv("PUTI", sysputi);
export_natv("PUTB", sysputb);
export_natv("PUTH", sysputh);
export_natv("GETC", sysgetc);
export_natv("GETS", sysgets);
stodci("SYSCALL", dci); add_sym(dci, VM_SYSCALL);
export_natv("CALL", syscall6502);
export_natv("TOUPPER", systoupper);
export_natv("STRCPY", sysstrcpy);
@@ -1085,6 +997,22 @@ void export_cmdsys(void)
mem_6502[heap++] = (byte)(VM_INLINE_ENTRY >> 8);
mem_6502[heap++] = 0x36; // DIVMOD
mem_6502[heap++] = 0x5C; // RET
//
// Hack SYSCALL into system (required for PLFORTH)
//
stodci("SYSCALL", dci); add_sym(dci, heap);
mem_6502[heap++] = 0xA5; // LDA ZP,X
mem_6502[heap++] = ESTKL;
mem_6502[heap++] = 0xA5; // LDY ZP,X
mem_6502[heap++] = ESTKH;
mem_6502[heap++] = 0x20; // JSR
mem_6502[heap++] = (byte)VM_SYSCALL;
mem_6502[heap++] = (byte)(VM_SYSCALL >> 8);
//
// Fake MACHID
//
mem_6502[machid] = 0x08; // Apple 1 (NA in ProDOS Tech Ref)
stodci("MACHID", dci); add_sym(dci, machid);
}
int main(int argc, char **argv)
{
@@ -1099,7 +1027,6 @@ 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
//
@@ -1146,14 +1073,19 @@ int main(int argc, char **argv)
//
// 64K - 256 RAM
//
mem_6502[FPL] = 0x00; // Frame pointer = $FF00
mem_6502[FPH] = 0xFF;
mem_6502[PPL] = 0x00; // Pool pointer = $FF00
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;
mem_6502[0x01FE] = 0xFF; // Address of $FF (RTN) instruction
mem_6502[0x01FD] = 0xFE;
mpu->registers->s = 0xFC;
mpu->registers->x = ESTK_SIZE;
//
// Load module from command line - PLVM version
//
export_cmdsys();
export_sysio();
stodci(modfile, dci);
if (trace) dump_sym();
load_mod(mpu, dci);
+26 -16
View File
@@ -41,14 +41,16 @@ int vm_irq(M6502 *mpu, uword address, byte data)
uword addr, handle;
fflush(stdout);
if (mem_6502[mpu->registers->s + 0x101] & flagB)
if (mem_6502[mpu->registers->s + 0x0101] & flagB)
{
//
// Handle BRK instructions
//
PLP; // restore status reg
addr = mem_6502[++mpu->registers->s + 0x100];
addr |= mem_6502[++mpu->registers->s + 0x100] << 8;
addr = mem_6502[++mpu->registers->s + 0x0100];
if (!mpu->registers->s) pfail("SP underflow");
addr |= mem_6502[++mpu->registers->s + 0x0100] << 8;
if (!mpu->registers->s) pfail("SP underflow");
//switch (mem_6502[addr]) // BRK type
//{
// default:
@@ -67,8 +69,10 @@ int vm_indef(M6502 *mpu, uword address, byte data)
{
uword addr;
addr = mem_6502[++mpu->registers->s + 0x100];
addr |= mem_6502[++mpu->registers->s + 0x100] << 8;
addr = mem_6502[++mpu->registers->s + 0x0100];
if (!mpu->registers->s) pfail("SP underflow");
addr |= mem_6502[++mpu->registers->s + 0x0100] << 8;
if (!mpu->registers->s) pfail("SP underflow");
vm_interp(mpu, &mem_6502[addr + 1]);
RTS;
}
@@ -76,8 +80,10 @@ int vm_iidef(M6502 *mpu, uword address, byte data)
{
uword addr;
addr = mem_6502[++mpu->registers->s + 0x100];
addr |= mem_6502[++mpu->registers->s + 0x100] << 8;
addr = mem_6502[++mpu->registers->s + 0x0100];
if (!mpu->registers->s) pfail("SP underflow");
addr |= mem_6502[++mpu->registers->s + 0x0100] << 8;
if (!mpu->registers->s) pfail("SP underflow");
vm_interp(mpu, mem_6502 + UWORD_PTR(&mem_6502[addr + 1]));
RTS;
}
@@ -88,8 +94,10 @@ int vm_exdef(M6502 *mpu, uword address, byte data)
{
uword addr;
addr = mem_6502[++mpu->registers->s + 0x100];
addr |= mem_6502[++mpu->registers->s + 0x100] << 8;
addr = mem_6502[++mpu->registers->s + 0x0100];
if (!mpu->registers->s) pfail("SP underflow");
addr |= mem_6502[++mpu->registers->s + 0x0100] << 8;
if (!mpu->registers->s) pfail("SP underflow");
vm_interp(mpu, vm_def[UWORD_PTR(&mem_6502[addr + 1])]);
RTS;
}
@@ -100,8 +108,10 @@ int vm_natvdef(M6502 *mpu, uword address, byte data)
{
uword addr;
addr = mem_6502[++mpu->registers->s + 0x100];
addr |= mem_6502[++mpu->registers->s + 0x100] << 8;
addr = mem_6502[++mpu->registers->s + 0x0100];
if (!mpu->registers->s) pfail("SP underflow");
addr |= mem_6502[++mpu->registers->s + 0x0100] << 8;
if (!mpu->registers->s) pfail("SP underflow");
vm_natv[mem_6502[addr + 1]](mpu);
RTS;
}
@@ -394,8 +404,8 @@ 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[mpu->registers->s-- + 0x100] = 0xFF; // Address of $FF (RTN) instruction
mem_6502[mpu->registers->s-- + 0x100] = 0xFE;
mem_6502[0x0100 + mpu->registers->s--] = 0xFF; // Address of $FF (RTN) instruction
mem_6502[0x0100 + mpu->registers->s--] = 0xFE;
//mpu->flags |= M6502_SingleStep;
if (trace)
printf("CALL: $%04X\r\n", mpu->registers->pc);
@@ -406,8 +416,8 @@ void vm_interp(M6502 *mpu, code *vm_ip)
break;
case 0x56: // ICALL : IP = TOS ; indirect call
mpu->registers->pc = UPOP;
mem_6502[mpu->registers->s-- + 0x100] = 0xFF; // Address of $FF (RTN) instruction
mem_6502[mpu->registers->s-- + 0x100] = 0xFE;
mem_6502[0x0100 + mpu->registers->s--] = 0xFF; // Address of $FF (RTN) instruction
mem_6502[0x0100 + mpu->registers->s--] = 0xFE;
if (trace)
printf("ICAL: $%04X\r\n", mpu->registers->pc);
externalize();
@@ -431,7 +441,7 @@ void vm_interp(M6502 *mpu, code *vm_ip)
mem_6502[vm_fp + parmcnt * 2 + 0] = val;
mem_6502[vm_fp + parmcnt * 2 + 1] = val >> 8;
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));
printf("< $%04X: $%04X > ", vm_fp + parmcnt * 2 + 0, mem_6502[vm_fp + parmcnt * 2 + 0] | (mem_6502[vm_fp + parmcnt * 2 + 1] << 8));
}
if (trace)
printf("\n");
+28 -11
View File
@@ -22,10 +22,10 @@ typedef uint16_t address;
/*
* 6502 H/W stack
*/
#define PHA (mem_6502[mpu->registers->s-- + 0x100]=mpu->registers->a)
#define PLA (mpu->registers->a=mem_6502[++mpu->registers->s + 0x100])
#define PHP (mem_6502[mpu->registers->s-- + 0x100]=mpu->registers->p)
#define PLP (mpu->registers->p=mem_6502[++mpu->registers->s + 0x100])
#define PHA (mem_6502[0x0100 + mpu->registers->s--]=mpu->registers->a)
#define PLA (mpu->registers->a=mem_6502[++mpu->registers->s + 0x0100])
#define PHP (mem_6502[0x0100 + mpu->registers->s--]=mpu->registers->p)
#define PLP (mpu->registers->p=mem_6502[++mpu->registers->s + 0x0100])
#define RTI \
{ \
uword pc; \
@@ -38,7 +38,9 @@ typedef uint16_t address;
{ \
uword pc; \
pc = mem_6502[++mpu->registers->s + 0x100]; \
if (!mpu->registers->s) pfail("SP underflow"); \
pc |= mem_6502[++mpu->registers->s + 0x100]<<8; \
if (!mpu->registers->s) pfail("SP underflow"); \
return pc + 1; \
}
/*
@@ -47,13 +49,13 @@ typedef uint16_t address;
#define PUSH_ESTK(v) \
{ \
--mpu->registers->x; \
mem_6502[ESTKL + mpu->registers->x] = (byte)(v); \
mem_6502[ESTKH + mpu->registers->x] = (byte)(v)>>8; \
mem_6502[ESTKL+mpu->registers->x] = (byte)(v); \
mem_6502[ESTKH+mpu->registers->x] = (byte)((v)>>8); \
}
#define PULL_ESTK(v) \
{ \
(v) = mem_6502[ESTKL + mpu->registers->x] \
| mem_6502[ESTKH + mpu->registers->x]<<8; \
(v) = mem_6502[ESTKL+mpu->registers->x] \
| mem_6502[ESTKH+mpu->registers->x]<<8; \
++mpu->registers->x; \
}
/*
@@ -96,15 +98,20 @@ typedef uint16_t address;
#define code_alloc(size) malloc(size)
#define TRACE 1
#define SINGLE_STEP 2
/*
* Fatal error
*/
extern void pfail(const char *msg);
/*
* VM callouts
*/
void M6502_exec(M6502 *mpu);
extern void M6502_exec(M6502 *mpu);
typedef void (*VM_Callout)(M6502 *mpu);
extern int trace;
extern byte mem_6502[];
extern byte mem_PLVM[];
extern byte *perr;
extern uword cmdsys;
extern int vm_addxdef(code * defaddr);
extern int vm_addnatv(VM_Callout);
extern int vm_irq(M6502 *mpu, uword address, byte data);
@@ -113,11 +120,21 @@ extern int vm_iidef(M6502 *mpu, uword address, byte data);
extern int vm_exdef(M6502 *mpu, uword address, byte data);
extern int vm_natvdef(M6502 *mpu, uword address, byte data);
extern void vm_interp(M6502 *mpu, code *vm_ip);
/*
* Heap routines
*/
uword alloc_heap(uword size);
/*
* Symbol export routines
*/
extern int stodci(char *str, byte *dci);
extern uword add_sym(byte *dci, uword addr);
extern uword add_natv( VM_Callout natvfn);
extern uword export_natv(char *symstr, VM_Callout natvfn);
/*
* System I/O routines
*/
extern void sysio_init(void);
extern void syscall6502(M6502 *mpu);
extern void export_sysio(void);
extern void sysopen(M6502 *mpu);
extern void sysclose(M6502 *mpu);
extern void sysread(M6502 *mpu);
+384 -10
View File
@@ -5,36 +5,410 @@
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/filio.h>
#include <termios.h>
#include "plvm.h"
void syscall6502(M6502 *mpu)
{
uword params;
byte cmd, status;
int keyqueue = 0;
PULL_ESTK(params);
PULL_ESTK(cmd);
status = 0;
switch (cmd)
/*
* Console I/O
*/
void sysputc(M6502 *mpu)
{
char c;
//
// Pop char and putchar it
//
PULL_ESTK(c);
putchar(c);
}
void sysputs(M6502 *mpu)
{
uword strptr;
int i;
char ch;
//
// Pop string pointer off stack, copy into C string, and puts it
//
PULL_ESTK(strptr);
for (i = 1; i <= mem_6502[strptr]; i++)
{
ch = mem_6502[strptr + i] & 0x7F;
switch (ch)
{
case '\r':
case '\n':
putchar('\n');
break;
default:
putchar(ch);
}
}
PUSH_ESTK(status);
}
void sysputln(M6502 *mpu)
{
putchar('\n');
}
void sysputi(M6502 *mpu)
{
word print;
//
// Pop int off stack, copy into C string, and print it
//
PULL_ESTK(print);
printf("%d", print);
}
void sysputb(M6502 *mpu)
{
uword prbyte;
//
// Pop byte off stack, copy into C string, and print it
//
PULL_ESTK(prbyte);
printf("%02X", prbyte & 0xFF);
}
void sysputh(M6502 *mpu)
{
uword prhex;
//
// Pop int off stack, copy into C string, and print it
//
PULL_ESTK(prhex);
printf("%04X", prhex);
}
void syskeypressed(M6502 *mpu)
{
int n;
if (ioctl(STDIN_FILENO, FIONREAD, &n) == 0 && n > 0)
keyqueue = getchar() | 0x80;
PUSH_ESTK(keyqueue);
}
void sysgetc(M6502 *mpu)
{
char c;
//
// Push getchar()
//
if (keyqueue)
{
c = keyqueue & 0x7F;
keyqueue = 0;
}
else
c = getchar();
PUSH_ESTK(c);
}
void sysgets(M6502 *mpu)
{
uword strptr;
int len;
char instr[256];
//
// Push gets(), limiting it to 128 chars
//
PULL_ESTK(instr[0]);
putchar(instr[0] & 0x7F);
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 sysecho(M6502 *mpu)
{
fprintf(stderr, "CONIO:ECHO unimplemented!\n");
}
void syshome(M6502 *mpu)
{
fprintf(stderr, "CONIO:HOME unimplemented!\n");
}
void sysgotoxy(M6502 *mpu)
{
fprintf(stderr, "CONIO:GOTOXY unimplemented!\n");
}
void sysviewport(M6502 *mpu)
{
fprintf(stderr, "CONIO:VIEWPORT unimplemented!\n");
}
void systexttype(M6502 *mpu)
{
fprintf(stderr, "CONIO:TEXTYPE unimplemented!\n");
}
void systextmode(M6502 *mpu)
{
fprintf(stderr, "CONIO:TEXTMODE unimplemented!\n");
}
void sysgrmode(M6502 *mpu)
{
fprintf(stderr, "CONIO:GRMODE unimplemented!\n");
}
void sysgrcolor(M6502 *mpu)
{
fprintf(stderr, "CONIO:GRCOLOR unimplemented!\n");
}
void sysgrplot(M6502 *mpu)
{
fprintf(stderr, "CONIO:GRPLOT unimplemented!\n");
}
void systone(M6502 *mpu)
{
fprintf(stderr, "CONIO:TONE unimplemented!\n");
}
void sysrnd(M6502 *mpu)
{
fprintf(stderr, "CONIO:RND unimplemented!\n");
}
/*
* File I/O
*/
void sysgetpfx(M6502 *mpu)
{
fprintf(stderr, "FILEIO:GETPFX unimplemented!\n");
}
void syssetpfx(M6502 *mpu)
{
fprintf(stderr, "FILEIO:SETPFX unimplemented!\n");
}
void sysgetfileinfo(M6502 *mpu)
{
fprintf(stderr, "FILEIO:GETFILEINFO unimplemented!\n");
}
void syssetfileinfo(M6502 *mpu)
{
fprintf(stderr, "FILEIO:SETFILEINFO unimplemented!\n");
}
void sysgeteof(M6502 *mpu)
{
fprintf(stderr, "FILEIO:GETEOF unimplemented!\n");
}
void sysseteof(M6502 *mpu)
{
fprintf(stderr, "FILEIO:SETEOF unimplemented!\n");
}
void sysiobufs(M6502 *mpu)
{
uword dummy;
PULL_ESTK(dummy);
PUSH_ESTK(0);
if (trace) printf("IOBUFS\n");
}
void sysopen(M6502 *mpu)
{
uword filestr;
char filename[128];
int fd;
//
// Pop filename string pointer off stack, make C string and open it
//
PULL_ESTK(filestr);
memcpy(filename, mem_6502 + filestr + 1, mem_6502[filestr]);
filename[mem_6502[filestr]] = '\0';
if (trace) printf("FILEIO:OPEN(%s)\n", filename);
fd = open(filename, O_RDWR);
if (fd > 255) fprintf(stderr, "FILEIO:OPEN fd out of range!\n");
if (fd < 0) *perr = errno;
PUSH_ESTK(fd);
}
void sysclose(M6502 *mpu)
{
int fd, result;
PULL_ESTK(fd);
result = close(fd);
if (result < 0) *perr = errno;
PUSH_ESTK(result);
}
void sysread(M6502 *mpu)
{
int fd, len;
uword buf;
PULL_ESTK(len);
PULL_ESTK(buf);
PULL_ESTK(fd);
len = read(fd, mem_6502 + buf, len);
if (len < 0) *perr = errno;
PUSH_ESTK(len);
}
void syswrite(M6502 *mpu)
{
fprintf(stderr, "FILEIO:WRITE unimplemented!\n");
}
void sysio_init(void)
void syscreate(M6502 *mpu)
{
fprintf(stderr, "FILEIO:CREATE unimplemented!\n");
}
void sysdestroy(M6502 *mpu)
{
fprintf(stderr, "FILEIO:DESTROY unimplemented!\n");
}
void sysrename(M6502 *mpu)
{
fprintf(stderr, "FILEIO:RENAME unimplemented!\n");
}
void sysnewline(M6502 *mpu)
{
fprintf(stderr, "FILEIO:NEWLINE unimplemented!\n");
}
void sysonline(M6502 *mpu)
{
fprintf(stderr, "FILEIO:ONLINE unimplemented!\n");
}
void sysunimpl(M6502 *mpu)
{
fprintf(stderr, "FILEIO:??? unimplemented!\n");
}
/*
* Create PLVM versions of fileio and conio modules.
*/
void export_sysio(void)
{
byte dci[16];
uword defaddr;
uword fileio = alloc_heap(36);
uword conio = alloc_heap(24);
//
// CMDSYS IO functions
//
export_natv("PUTC", sysputc);
export_natv("PUTS", sysputs);
export_natv("PUTLN", sysputln);
export_natv("PUTI", sysputi);
export_natv("PUTB", sysputb);
export_natv("PUTH", sysputh);
export_natv("GETS", sysgets);
//
// Exported CONIO function table.
//
//word conio[]
//word = @a2keypressed
//word = @getc
//word = @a12echo
//word = @a2home
//word = @a2gotoxy
//word = @a2viewport
//word = @a2texttype
//word = @a2textmode
//word = @a2grmode
//word = @a2grcolor
//word = @a2grplot
//word = @a2tone
//word = @a2rnd
stodci("CONIO", dci); add_sym(dci, conio);
defaddr = add_natv(syskeypressed);
mem_6502[conio + 0] = (byte)defaddr;
mem_6502[conio + 1] = (byte)(defaddr >> 8);
defaddr = export_natv("GETC", sysgetc);
mem_6502[conio + 2] = (byte)defaddr;
mem_6502[conio + 3] = (byte)(defaddr >> 8);
defaddr = add_natv(sysecho);
mem_6502[conio + 4] = (byte)defaddr;
mem_6502[conio + 5] = (byte)(defaddr >> 8);
defaddr = add_natv(syshome);
mem_6502[conio + 6] = (byte)defaddr;
mem_6502[conio + 7] = (byte)(defaddr >> 8);
defaddr = add_natv(sysgotoxy);
mem_6502[conio + 8] = (byte)defaddr;
mem_6502[conio + 9] = (byte)(defaddr >> 8);
defaddr = add_natv(sysviewport);
mem_6502[conio + 10] = (byte)defaddr;
mem_6502[conio + 11] = (byte)(defaddr >> 8);
defaddr = add_natv(systexttype);
mem_6502[conio + 12] = (byte)defaddr;
mem_6502[conio + 13] = (byte)(defaddr >> 8);
defaddr = add_natv(systextmode);
mem_6502[conio + 14] = (byte)defaddr;
mem_6502[conio + 15] = (byte)(defaddr >> 8);
defaddr = add_natv(sysgrmode);
mem_6502[conio + 16] = (byte)defaddr;
mem_6502[conio + 17] = (byte)(defaddr >> 8);
defaddr = add_natv(sysgrplot);
mem_6502[conio + 18] = (byte)defaddr;
mem_6502[conio + 19] = (byte)(defaddr >> 8);
defaddr = add_natv(systone);
mem_6502[conio + 20] = (byte)defaddr;
mem_6502[conio + 21] = (byte)(defaddr >> 8);
defaddr = add_natv(sysrnd);
mem_6502[conio + 22] = (byte)defaddr;
mem_6502[conio + 23] = (byte)(defaddr >> 8);
//
// Exported FILEIO function table.
//
//word fileio[]
//word = @a2getpfx, @a2setpfx, @a2getfileinfo, @a2setfileinfo, @a23geteof, @a23seteof, @a2iobufs, @a2open, @a2close
//word = @a23read, @a2write, @a2create, @a23destroy, @a23rename
//word = @a2newline, @a2online, @a2readblock, @a2writeblock
stodci("FILEIO", dci); add_sym(dci, fileio);
defaddr = add_natv(sysgetpfx);
mem_6502[fileio + 0] = (byte)defaddr;
mem_6502[fileio + 1] = (byte)(defaddr >> 8);
defaddr = add_natv(syssetpfx);
mem_6502[fileio + 2] = (byte)defaddr;
mem_6502[fileio + 3] = (byte)(defaddr >> 8);
defaddr = add_natv(sysgetfileinfo);
mem_6502[fileio + 4] = (byte)defaddr;
mem_6502[fileio + 5] = (byte)(defaddr >> 8);
defaddr = add_natv(syssetfileinfo);
mem_6502[fileio + 6] = (byte)defaddr;
mem_6502[fileio + 7] = (byte)(defaddr >> 8);
defaddr = add_natv(sysgeteof);
mem_6502[fileio + 8] = (byte)defaddr;
mem_6502[fileio + 9] = (byte)(defaddr >> 8);
defaddr = add_natv(sysseteof);
mem_6502[fileio + 10] = (byte)defaddr;
mem_6502[fileio + 11] = (byte)(defaddr >> 8);
defaddr = add_natv(sysiobufs);
mem_6502[fileio + 12] = (byte)defaddr;
mem_6502[fileio + 13] = (byte)(defaddr >> 8);
defaddr = add_natv(sysopen); // sysopen
mem_6502[cmdsys + 8] = (byte)defaddr;
mem_6502[cmdsys + 9] = (byte)(defaddr >> 8);
mem_6502[fileio + 14] = (byte)defaddr;
mem_6502[fileio + 15] = (byte)(defaddr >> 8);
defaddr = add_natv(sysclose); // sysclose
mem_6502[cmdsys + 10] = (byte)defaddr;
mem_6502[cmdsys + 11] = (byte)(defaddr >> 8);
mem_6502[fileio + 16] = (byte)defaddr;
mem_6502[fileio + 17] = (byte)(defaddr >> 8);
defaddr = add_natv(sysread); // sysread
mem_6502[cmdsys + 12] = (byte)defaddr;
mem_6502[cmdsys + 13] = (byte)(defaddr >> 8);
mem_6502[fileio + 18] = (byte)defaddr;
mem_6502[fileio + 19] = (byte)(defaddr >> 8);
defaddr = add_natv(syswrite); // syswrite
mem_6502[cmdsys + 14] = (byte)defaddr;
mem_6502[cmdsys + 15] = (byte)(defaddr >> 8);
mem_6502[fileio + 20] = (byte)defaddr;
mem_6502[fileio + 21] = (byte)(defaddr >> 8);
defaddr = add_natv(syscreate);
mem_6502[fileio + 22] = (byte)defaddr;
mem_6502[fileio + 23] = (byte)(defaddr >> 8);
defaddr = add_natv(sysdestroy);
mem_6502[fileio + 24] = (byte)defaddr;
mem_6502[fileio + 25] = (byte)(defaddr >> 8);
defaddr = add_natv(sysrename);
mem_6502[fileio + 26] = (byte)defaddr;
mem_6502[fileio + 27] = (byte)(defaddr >> 8);
defaddr = add_natv(sysnewline);
mem_6502[fileio + 28] = (byte)defaddr;
mem_6502[fileio + 29] = (byte)(defaddr >> 8);
defaddr = add_natv(sysonline);
mem_6502[fileio + 30] = (byte)defaddr;
mem_6502[fileio + 31] = (byte)(defaddr >> 8);
defaddr = add_natv(sysunimpl); // readblock
mem_6502[fileio + 32] = (byte)defaddr;
mem_6502[fileio + 33] = (byte)(defaddr >> 8);
defaddr = add_natv(sysunimpl); // writeblock
mem_6502[fileio + 34] = (byte)defaddr;
mem_6502[fileio + 35] = (byte)(defaddr >> 8);
}