Bring PLASMA up-to-date

This commit is contained in:
David Schmenk 2015-01-02 17:29:02 -08:00
parent f6b38066c7
commit 7d6860b1d5
6 changed files with 207 additions and 125 deletions

View File

@ -4,15 +4,23 @@ const databuff = $2000
const MODADDR = $1000
const symtbl = $0C00
const freemem = $0006
const getlnbuf = $01FF
//
// System flags: memory allocator screen holes.
//
const restxt1 = $0001
const restxt2 = $0002
const reshgr1 = $0004
const reshgr2 = $0008
const resxhgr1 = $0010
const resxhgr2 = $0020
const resxtxt1 = $0004
const resxtxt2 = $0008
const reshgr1 = $0010
const reshgr2 = $0020
const resxhgr1 = $0040
const resxhgr2 = $0080
//
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
//
// Pedefined functions.
//
@ -25,40 +33,43 @@ predef loadmod, execmod, lookupstrmod
//
// System variable.
//
word version = $0010 // 00.10
word version = $0011 // 00.11
word systemflags = 0
word heap
word xheap = $0800
word lastsym = symtbl
byte perr
word cmdptr
byte cmdln = "" // Overlay exported strings table
//
// Standard Library exported functions.
//
byte stdlibstr[] = "STDLIB"
byte machidstr[] = "MACHID"
byte sysstr[] = "SYSCALL"
byte callstr[] = "CALL"
byte putcstr[] = "PUTC"
byte putlnstr[] = "PUTLN"
byte putsstr[] = "PUTS"
byte getcstr[] = "GETC"
byte getsstr[] = "GETS"
byte hpmarkstr[] = "HEAPMARK"
byte hpalignstr[] = "HEAPALLOCALIGN"
byte hpallocstr[] = "HEAPALLOC"
byte hprelstr[] = "HEAPRELEASE"
byte hpavailstr[] = "HEAPAVAIL"
byte memsetstr[] = "MEMSET"
byte memcpystr[] = "MEMCPY"
byte uisgtstr[] = "ISUGT"
byte uisgestr[] = "ISUGE"
byte uisltstr[] = "ISULT"
byte uislestr[] = "ISULE"
byte loadstr[] = "MODLOAD"
byte execstr[] = "MODEXEC"
byte modadrstr[] = "MODADDR"
word exports[] = @sysstr, @syscall
byte stdlibstr = "STDLIB"
byte machidstr = "MACHID"
byte sysstr = "SYSCALL"
byte callstr = "CALL"
byte putcstr = "PUTC"
byte putlnstr = "PUTLN"
byte putsstr = "PUTS"
byte getcstr = "GETC"
byte getsstr = "GETS"
byte hpmarkstr = "HEAPMARK"
byte hpalignstr = "HEAPALLOCALIGN"
byte hpallocstr = "HEAPALLOC"
byte hprelstr = "HEAPRELEASE"
byte hpavailstr = "HEAPAVAIL"
byte memsetstr = "MEMSET"
byte memcpystr = "MEMCPY"
byte uisgtstr = "ISUGT"
byte uisgestr = "ISUGE"
byte uisltstr = "ISULT"
byte uislestr = "ISULE"
byte loadstr = "MODLOAD"
byte execstr = "MODEXEC"
byte modadrstr = "MODADDR"
byte argstr = "ARGS"
byte autorun = "AUTORUN"
byte prefix[] // overlay with exported symbols table
word exports = @sysstr, @syscall
word = @callstr, @call
word = @putcstr, @cout
word = @putlnstr, @crout
@ -79,18 +90,17 @@ word = @loadstr, @loadmod
word = @execstr, @execmod
word = @modadrstr, @lookupstrmod
word = @machidstr, MACHID
word = @argstr, @cmdln
word = 0
word stdlibsym = @exports
word stdlibsym = @exports
//
// String pool.
//
byte autorun[] = "AUTORUN"
byte verstr[] = "PLASMA "
byte freestr[] = "MEM FREE:$"
byte errorstr[] = "ERR:$"
byte okstr[] = "OK"
byte huhstr[] = "?\n"
byte prefix[32] = ""
byte verstr = "PLASMA "
byte freestr = "MEM FREE:$"
byte errorstr = "ERR:$"
byte okstr = "OK"
byte huhstr = "?\n"
//
// Utility functions
//
@ -167,7 +177,7 @@ asm exec
STX IFPL
LDA #$BF
STA IFPH
DEX
LDX #$FE
TXS
LDX #ESTKSZ/2
BIT ROMEN
@ -268,10 +278,12 @@ REVCPY ;CLC
LDA ESTKH-2,X
ADC ESTKH-1,X
STA SRCH
INC ESTKH-2,X
DEC DSTH
DEC SRCH
LDY #$FF
LDA ESTKL-2,X
BEQ REVCPYLP
INC ESTKH-2,X
REVCPYLP LDA (SRC),Y
STA (DST),Y
DEY
@ -316,9 +328,9 @@ asm memxcpy
end
asm crout
DEX
LDA #$8D
STA ESTKL,X
// FALL THROUGH TO COUT
LDA #$0D
BNE +
; FALL THROUGH TO COUT
end
//
// CHAR OUT
@ -345,6 +357,7 @@ asm cin
BIT LCRDEN+LCBNK2
DEX
LDY #$00
AND #$7F
STA ESTKL,X
STY ESTKH,X
RTS
@ -478,7 +491,7 @@ asm uword_islt
end
//
// Utility routines.
//
//
// A DCI string is one that has the high bit set for every character except the last.
// More efficient than C or Pascal strings.
//
@ -761,11 +774,11 @@ def allocalignheap(size, pow2, freeaddr)
return addr
end
def markheap
return heap//
return heap
end
def releaseheap(newheap)
heap = newheap//
return @newheap - heap//
heap = newheap
return @newheap - heap
end
def allocxheap(size)
word xaddr
@ -909,9 +922,9 @@ def loadmod(mod)
while ^moddep
if !lookupmod(moddep)
close(refnum)
refnum = 0
refnum = 0
if loadmod(moddep) < 0
return -perr
return -perr
fin
fin
moddep = moddep + dcitos(moddep, @str)
@ -926,7 +939,7 @@ def loadmod(mod)
//
// Reset read pointer.
//
refnum = open(@filename, iobuffer)
refnum = open(@filename, iobuffer)
rdlen = read(refnum, @header, 128)
fin
fin
@ -980,10 +993,10 @@ def loadmod(mod)
//
while ^rld
if ^rld == $02
//
//
// This is a bytcode def entry - add it to the def directory.
//
adddef(defbank, rld=>1 - defofst + defaddr, @deflast)
adddef(defbank, rld=>1 - defofst + defaddr, @deflast)
else
addr = rld=>1 + modfix
if uword_isge(addr, modaddr) // Skip fixups to header
@ -1019,7 +1032,7 @@ def loadmod(mod)
sym = esd
esd = esd + dcitos(esd, @str)
if ^esd & $08
//
//
// EXPORT symbol - add it to the global symbol table.
//
addr = esd=>1 + modfix - MODADDR
@ -1046,15 +1059,21 @@ def loadmod(mod)
//
// Call init routine if it exists.
//
fixup = 0 // This is repurposed for the return code
if init
fixup = adddef(defbank, init - defofst + defaddr, @deflast)()
if defbank
xheap = init - defofst + defaddr
else
modend = init - defofst + defaddr
if fixup < modinitkeep
//
// Free init routine unless initkeep
//
if defbank
xheap = init - defofst + defaddr
else
modend = init - defofst + defaddr
fin
else
fixup = fixup & ~modinitkeep
fin
else
fixup = 0
fin
//
// Free up the end-of-module in main memory.
@ -1147,7 +1166,7 @@ def catalog(optpath)
return 0
end
def stripchars(strptr)
while ^strptr and ^(strptr + 1) <> ' '
while ^strptr and ^(strptr + 1) > ' '
memcpy(strptr + 1, strptr + 2, ^strptr)
^strptr = ^strptr - 1
loop
@ -1166,7 +1185,7 @@ def striptrail(strptr)
byte i
for i = 1 to ^strptr
if (strptr)[i] == ' '
if ^(strptr + i) <= ' '
^strptr = i - 1
return
fin
@ -1213,7 +1232,7 @@ def execsys(sysfile)
memcpy(sysfile, $280, ^$280 + 1)
if stripchars(sysfile) and ^$2000 == $4C and *$2003 == $EEEE
stripspaces(sysfile)
if ^$2006 <= ^sysfile
if ^$2005 >= ^sysfile + 1
memcpy($2006, sysfile, ^sysfile + 1)
fin
fin
@ -1226,18 +1245,22 @@ end
def execmod(modfile)
byte moddci[17]
word saveheap, savexheap, savesym, saveflags
if stodci(modfile, @moddci)
saveheap = heap
savexheap = xheap
savesym = lastsym
saveflags = systemflags
^lastsym = 0
perr = loadmod(@moddci)
savexheap = xheap
savesym = lastsym
saveflags = systemflags
^lastsym = 0
perr = loadmod(@moddci)
if perr < modkeep
lastsym = savesym
xheap = savexheap
heap = saveheap
else
perr = perr & ~modkeep
fin
systemflags = saveflags
lastsym = savesym
xheap = savexheap
heap = saveheap
fin
end
//
@ -1255,44 +1278,46 @@ while *stdlibsym
stdlibsym = stdlibsym + 4
loop
//
// Try to run autorun module.
// Try to load autorun.
//
resetmemfiles()
execmod(@autorun)
autorun = open(@autorun, iobuffer)
if autorun > 0
cmdln = read(autorun, @stdlibstr, 128)
close(autorun)
else
//
// Print some startup info.
//
prstr(@verstr)
prbyte(version.1)
cout('.')
prbyte(version.0)
crout
prstr(@freestr)
prword(availheap)
crout
fin
perr = 0
//
// Print some startup info.
//
prstr(@verstr)
prbyte(version.1)
cout('.')
prbyte(version.0)
crout
prstr(@freestr)
prword(availheap)
crout
while 1
prstr(getpfx(@prefix))
cmdptr = rdstr($BA)
if ^cmdptr
when toupper(parsecmd(cmdptr))
if cmdln
when toupper(parsecmd(@cmdln))
is 'Q'
reboot()
break
is 'C'
catalog(cmdptr)
catalog(@cmdln)
break
is 'P'
setpfx(cmdptr)
setpfx(@cmdln)
break
is 'V'
volumes()
break
is '-'
execsys(cmdptr)
execsys(@cmdln)
break
is '+'
execmod(cmdptr)
execmod(@cmdln)
break
otherwise
prstr(@huhstr)
@ -1306,5 +1331,7 @@ while 1
fin
crout()
fin
prstr(getpfx(@prefix))
memcpy(@cmdln, rdstr($BA), 128)
loop
done

View File

@ -94,7 +94,17 @@ int idlocal_add(char *name, int len, int type, int size)
{
printf("Local variable size overflow\n");
return (0);
}
}
if (idconst_lookup(name, len) > 0)
{
parse_error("const/local name conflict\n");
return (0);
}
if (idlocal_lookup(name, len) > 0)
{
parse_error("local label already defined\n");
return (0);
}
name[len] = '\0';
emit_idlocal(name, localsize);
name[len] = c;
@ -116,6 +126,16 @@ int idglobal_add(char *name, int len, int type, int size)
printf("Global variable count overflow\n");
return (0);
}
if (idconst_lookup(name, len) > 0)
{
parse_error("const/global name conflict\n");
return (0);
}
if (idglobal_lookup(name, len) > 0)
{
parse_error("global label already defined\n");
return (0);
}
name[len] = '\0';
name[len] = c;
idglobal_name[globals][0] = len;
@ -254,7 +274,7 @@ char *tag_string(int tag, int type)
{
static char str[16];
char t;
if (type & EXTERN_TYPE)
t = 'X';
else if (type & DEF_TYPE)
@ -351,7 +371,7 @@ void emit_rld(void)
void emit_esd(void)
{
int i;
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
for (i = 0; i < globals; i++)
{
@ -612,7 +632,7 @@ void emit_globaladdr(int tag, int offset, int type)
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$26\t\t\t; LA\t%s+%d\n", DB, taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "" : taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_indexbyte(void)
{

View File

@ -22,35 +22,36 @@ t_token keywords[] = {
ENDCASE_TOKEN, 'W', 'E', 'N', 'D',
FOR_TOKEN, 'F', 'O', 'R',
TO_TOKEN, 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
STEP_TOKEN, 'S', 'T', 'E', 'P',
NEXT_TOKEN, 'N', 'E', 'X', 'T',
REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
CONTINUE_TOKEN, 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'E',
ASM_TOKEN, 'A', 'S', 'M',
DEF_TOKEN, 'D', 'E', 'F',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
END_TOKEN, 'E', 'N', 'D',
DONE_TOKEN, 'D', 'O', 'N', 'E',
LOGIC_NOT_TOKEN, 'N', 'O', 'T',
LOGIC_AND_TOKEN, 'A', 'N', 'D',
LOGIC_OR_TOKEN, 'O', 'R',
LOGIC_OR_TOKEN, 'O', 'R',
BYTE_TOKEN, 'B', 'Y', 'T', 'E',
WORD_TOKEN, 'W', 'O', 'R', 'D',
CONST_TOKEN, 'C', 'O', 'N', 'S', 'T',
STRUC_TOKEN, 'S', 'T', 'R', 'U', 'C',
PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F',
SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S',
SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S',
EOL_TOKEN
};
void parse_error(char *errormsg)
{
char *error_carrot = statement;
fprintf(stderr, "\n%4d: %s\n ", lineno, statement);
for (error_carrot = statement; error_carrot != tokenstr; error_carrot++)
putc(*error_carrot == '\t' ? '\t' : ' ', stderr);
@ -219,6 +220,9 @@ t_token scan(void)
case '\'':
*scanpos = '\'';
break;
case '\"':
*scanpos = '\"';
break;
case '\\':
*scanpos = '\\';
break;
@ -232,8 +236,7 @@ t_token scan(void)
for (scanshift = scanpos + 1; *scanshift; scanshift++)
scanshift[0] = scanshift[1];
}
else
scanpos++;
scanpos++;
}
if (!*scanpos++)
{

View File

@ -5,7 +5,7 @@
#include "codegen.h"
#include "parse.h"
int infunc = 0, break_tag = 0, stack_loop = 0;
int infunc = 0, break_tag = 0, cont_tag = 0, stack_loop = 0;
t_token prevstmnt;
t_token binary_ops_table[] = {
@ -357,6 +357,8 @@ int parse_value(int rvalue)
(type & BPTR_TYPE) ? emit_lb() : emit_lw();
emit_value = 1;
}
else
(type & BPTR_TYPE) ? emit_lb() : emit_lw();
type &= ~(VAR_TYPE | ADDR_TYPE);
type |= WORD_TYPE;
scantoken = scantoken == PTRB_TOKEN ? DOT_TOKEN : COLON_TOKEN;
@ -450,7 +452,7 @@ int parse_value(int rvalue)
/*
* Function call
*/
if (emit_value && !(type & (FUNC_TYPE | CONST_TYPE)))
if (emit_value)
{
if (scan_lookahead() != CLOSE_PAREN_TOKEN)
emit_push();
@ -636,7 +638,7 @@ int parse_expr()
}
int parse_stmnt(void)
{
int tag_prevbrk, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
int type, addr, step;
char *idptr;
@ -694,6 +696,8 @@ int parse_stmnt(void)
case WHILE_TOKEN:
tag_while = tag_new(BRANCH_TYPE);
tag_wend = tag_new(BRANCH_TYPE);
tag_prevcnt = cont_tag;
cont_tag = tag_while;
tag_prevbrk = break_tag;
break_tag = tag_wend;
emit_codetag(tag_while);
@ -712,11 +716,14 @@ int parse_stmnt(void)
emit_brnch(tag_while);
emit_codetag(tag_wend);
break_tag = tag_prevbrk;
cont_tag = tag_prevcnt;
break;
case REPEAT_TOKEN:
tag_prevbrk = break_tag;
break_tag = tag_new(BRANCH_TYPE);
tag_repeat = tag_new(BRANCH_TYPE);
tag_prevcnt = cont_tag;
cont_tag = tag_new(BRANCH_TYPE);
emit_codetag(tag_repeat);
scan();
while (parse_stmnt()) next_line();
@ -725,6 +732,8 @@ int parse_stmnt(void)
parse_error("Missing REPEAT/UNTIL");
return (0);
}
emit_codetag(cont_tag);
cont_tag = tag_prevcnt;
if (!parse_expr())
{
parse_error("Bad expression");
@ -739,6 +748,8 @@ int parse_stmnt(void)
tag_prevbrk = break_tag;
break_tag = tag_new(BRANCH_TYPE);
tag_for = tag_new(BRANCH_TYPE);
tag_prevcnt = cont_tag;
cont_tag = tag_for;
if (scan() != ID_TOKEN)
{
parse_error("Missing FOR variable");
@ -794,6 +805,7 @@ int parse_stmnt(void)
return (0);
}
emit_brnch(tag_for);
cont_tag = tag_prevcnt;
emit_codetag(break_tag);
emit_drop();
break_tag = tag_prevbrk;
@ -854,6 +866,15 @@ int parse_stmnt(void)
break_tag = tag_prevbrk;
stack_loop--;
break;
case CONTINUE_TOKEN:
if (cont_tag)
emit_brnch(cont_tag);
else
{
parse_error("CONTINUE without loop");
return (0);
}
break;
case BREAK_TOKEN:
if (break_tag)
emit_brnch(break_tag);

View File

@ -55,8 +55,10 @@ INTERP = $03D0
;* *
;******************************
* = $2000
LDX #$FF
LDX #$FE
TXS
LDX #$00
STX $01FF
;*
;* DISCONNECT /RAM
;*
@ -152,7 +154,7 @@ RAMDONE CLI
STA LCDEFCMD,Y
DEY
BPL -
JMP CMDEXEC
JMP CMDENTRY
GETPFXPARMS !BYTE 1
!WORD STRBUF ; PATH STRING GOES HERE
;************************************************
@ -232,7 +234,9 @@ BYE LDY DEFCMD
STA STRBUF,Y
DEY
BPL -
CMDEXEC = *
INY ; CLEAR CMDLINE BUFF
STY $01FF
CMDENTRY = *
;
; DEACTIVATE 80 COL CARDS
;
@ -284,18 +288,27 @@ CMDEXEC = *
!BYTE $CC
!WORD CLOSEPARMS
BNE FAIL
;
; INIT VM ENVIRONMENT STACK POINTERS
;
; LDA #$00 ; INIT FRAME POINTER
STA IFPL
LDA #$BF
STA IFPH
LDX #$FE ; INIT STACK POINTER (YES, $FE. SEE GETS)
TXS
LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX
JMP $2000 ; JUMP TO LOADED SYSTEM COMMAND
;
; PRINT FAIL MESSAGE, WAIT FOR KEYPRESS, AND REBOOT
;
FAIL INC $3F4 ; INVALIDATE POWER-UP BYTE
LDY #$01
LDY #33
- LDA FAILMSG,Y
ORA #$80
JSR $FDED
INY
CPY FAILMSG
BNE -
DEY
BPL -
JSR $FD0C ; WAIT FOR KEYPRESS
JMP ($FFFC) ; RESET
OPENPARMS !BYTE 3
@ -305,13 +318,12 @@ REFNUM !BYTE 0
READPARMS !BYTE 4
!BYTE 0
!WORD $2000
!WORD $1100
!WORD $9F00
!WORD 0
CLOSEPARMS !BYTE 1
!BYTE 0
DISABLE80 !BYTE 21, 13, '1', 26, 13
FAILMSG !BYTE 39
!TEXT "MISSING CMD. PRESS ANY KEY TO RESET..."
FAILMSG !TEXT "...TESER OT YEK YNA .DMC GNISSIM"
PAGE0 = *
;******************************
;* *
@ -340,10 +352,10 @@ PAGE3 = *
BIT LCRDEN+LCBNK2 ; $03DC - INDIRECT INTERPX ENTRY
JMP IINTRPX
}
DEFCMD !FILL 33
DEFCMD !FILL 28
ENDBYE = *
}
LCDEFCMD = *-33 ; DEFCMD IN LC MEMORY
LCDEFCMD = *-28 ; DEFCMD IN LC MEMORY
;*****************
;* *
;* OPXCODE TABLE *
@ -496,7 +508,6 @@ NEG LDA #$00
;* DIV TOS-1 BY TOS
;*
DIV JSR _DIV
INX
LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1
BCS NEG
JMP NEXTOP
@ -504,7 +515,6 @@ DIV JSR _DIV
;* MOD TOS-1 BY TOS
;*
MOD JSR _DIV
INX
LDA TMPL ; REMNDRL
STA ESTKL,X
LDA TMPH ; REMNDRH

View File

@ -43,7 +43,8 @@
#define BREAK_TOKEN TOKEN(29)
#define SYSFLAGS_TOKEN TOKEN(30)
#define STRUC_TOKEN TOKEN(31)
#define EVAL_TOKEN TOKEN(32)
#define CONTINUE_TOKEN TOKEN(32)
//#define EVAL_TOKEN TOKEN(32)
/*
* Double operand operators.
*/