Updates for code generation and module initialization

This commit is contained in:
David Schmenk 2014-05-06 15:26:12 -07:00
parent e230d98e8c
commit 3858728528
12 changed files with 883 additions and 134 deletions

500
PLASMA/src/cmd.pla Normal file
View File

@ -0,0 +1,500 @@
const iobuffer = $0800
const databuff = $0C00
const autorun = $01FF
byte version[] = "PLASMA VM VERSION 0.9"
byte errorstr[] = "ERROR: $"
byte okstr[] = "OK"
byte prefix[32] = ""
byte perr
word cmdptr
;
; Utility functions
;
; CALL PRODOS
; SYSCALL(CMD, PARAMS)
;
asm prodos
LDA ESTKL,X
LDY ESTKH,X
STA PARAMS
STY PARAMS+1
INX
LDA ESTKL,X
STA CMD
STX ESP
JSR $BF00
CMD: !BYTE 00
PARAMS: !WORD 0000
BIT LCBNK2
LDX ESP
STA ESTKL,X
LDY #$00
STY ESTKH,X
RTS
end
;
; CALL LOADED SYSTEM PROGRAM
;
asm exec
LDX #$FF
TXS
BIT ROMEN
JMP $2000
end
;
; SET MEMORY TO 0
; MEMCLR(ADDR, SIZE)
;
asm memclr
LDY #$00
LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
INC ESTKL,X
INC ESTKH,X
TYA
SETMLP DEC ESTKL,X
BNE +
DEC ESTKH,X
BEQ ++
+ STA (DST),Y
INY
BNE SETMLP
INC DSTH
BNE SETMLP
+ INX
INX
RTS
end
;
; COPY MEMORY
; MEMCPY(DSTADDR, SRCADDR, SIZE)
;
asm memcpy
LDY #$00
LDA ESTKL,X
BNE +
LDA ESTKH,X
BEQ MEMEXIT
+ LDA ESTKL+2,X
STA DSTL
LDA ESTKH+2,X
STA DSTH
LDA ESTKL+1,X
STA SRCL
LDA ESTKH+1,X
STA SRCH
CMP DSTH
BCC REVCPY
BNE FORCPY
LDA SRCL
CMP DSTL
BCS FORCPY
REVCPY ; REVERSE DIRECTION COPY
; CLC
LDA ESTKL,X
ADC DSTL
STA DSTL
LDA ESTKH,X
ADC DSTH
STA DSTH
CLC
LDA ESTKL,X
ADC SRCL
STA SRCL
LDA ESTKH,X
ADC SRCH
STA SRCH
INC ESTKH,X
REVCPYLP
LDA DSTL
BNE +
DEC DSTH
+ DEC DSTL
LDA SRCL
BNE +
DEC SRCH
+ DEC SRCL
LDA (SRC),Y
STA (DST),Y
DEC ESTKL,X
BNE REVCPYLP
DEC ESTKH,X
BNE REVCPYLP
BEQ MEMEXIT
FORCPY INC ESTKH,X
FORCPYLP
LDA (SRC),Y
STA (DST),Y
INC DSTL
BNE +
INC DSTH
+ INC SRCL
BNE +
INC SRCH
+ DEC ESTKL,X
BNE FORCPYLP
DEC ESTKH,X
BNE FORCPYLP
MEMEXIT INX
INX
INX
RTS
end
;
; CHAR OUT
; COUT(CHAR)
;
asm cout
LDA ESTKL,X
INX
ORA #$80
BIT ROMIN
JSR $FDED
BIT LCBNK2
RTS
end
;
; CHAR IN
; RDKEY()
;
asm cin
BIT ROMIN
STX ESP
JSR $FD0C
LDX ESP
BIT LCBNK2
DEX
STA ESTKL,X
LDY #$00
STY ESTKH,X
RTS
end
;
; PRINT STRING
; PRSTR(STR)
;
asm prstr
LDY #$00
LDA ESTKL,X
STA SRCL
LDA ESTKH,X
STA SRCH
BIT ROMIN
LDA (SRC),Y
STA ESTKL,X
BEQ +
- INY
LDA (SRC),Y
ORA #$80
JSR $FDED
TYA
CMP ESTKL,X
BNE -
+ INX
BIT LCBNK2
RTS
end
;
; PRINT BYTE
;
asm prbyte
LDA ESTKL,X
INX
STX ESP
BIT ROMIN
JSR $FDDA
BIT LCBNK2
LDX ESP
RTS
end
;
; READ STRING
; STR = RDSTR(PROMPTCHAR)
;
asm rdstr
LDA ESTKL,X
STA $33
STX ESP
BIT ROMIN
JSR $FD6A
BIT LCBNK2
STX $01FF
- LDA $01FF,X
AND #$7F
STA $01FF,X
DEX
BPL -
LDX ESP
LDA #$FF
STA ESTKL,X
LDA #$01
STA ESTKH,X
RTS
end
asm toupper
LDA ESTKL,X
CMP #'a'
BCC +
CMP #'z'+1
BCS +
SEC
SBC #$20
STA ESTKL,X
+ RTS
end
;
; EXIT
;
asm reboot
BIT ROMIN
LDA #$00
STA $3F4 ; INVALIDATE POWER-UP BYTE
JMP ($FFFC) ; RESET
end
def crout
cout($0D)
end
;
; ProDOS routines
;
def getpfx(path)
byte params[3]
^path = 0
params.0 = 1
params:1 = path
perr = prodos($C7, @params)
return path
end
def setpfx(path)
byte params[3]
params.0 = 1
params:1 = path
perr = prodos($C6, @params)
return path
end
def online
byte params[4]
params.0 = 2
params.1 = 0
params:2 = $2000
perr = prodos($C5, @params)
return $2000
end
def open(path, buff)
byte params[6]
params.0 = 3
params:1 = path
params:3 = buff
params.5 = 0
perr = prodos($C8, @params)
return params.5
end
def close(refnum)
byte params[2]
params.0 = 1
params.1 = refnum
perr = prodos($CC, @params)
return perr
end
def read(refnum, buff, len)
byte params[8]
params.0 = 4
params.1 = refnum
params:2 = buff
params:4 = len
params:6 = 0
perr = prodos($CA, @params)
return params:6
end
;
; Command mode
;
def volumes
word strbuf
byte i
strbuf = online()
for i = 0 to 15
^strbuf = ^strbuf & $0F
if ^strbuf
cout('/')
prstr(strbuf)
crout()
fin
strbuf = strbuf + 16
next
end
def catalog(optpath)
byte path[64]
byte refnum
byte firstblk
byte entrylen, entriesblk
byte i, type, len
word entry, filecnt
if ^optpath
memcpy(optpath, @path, ^optpath + 1)
else
getpfx(@path)
prstr(@path)
crout()
fin
refnum = open(@path, iobuffer);
if perr
return perr
fin
firstblk = 1
repeat
if read(refnum, databuff, 512) == 512
entry = databuff + 4
if firstblk
entrylen = databuff.$23
entriesblk = databuff.$24
filecnt = databuff:$25
entry = entry + entrylen
fin
for i = firstblk to entriesblk
type = ^entry
if type <> 0
len = type & $0F
^entry = len
prstr(entry)
if type & $F0 == $D0 ; Is it a directory?
cout('/')
len = len + 1
elsif (entry).$10 == $FF
cout('*')
len = len + 1
fin
for len = 19 - len downto 0
cout(' ')
next
filecnt = filecnt - 1
fin
entry = entry + entrylen
next
firstblk = 0
else
filecnt = 0
fin
until filecnt == 0
close(refnum)
crout()
return 0
end
def stripchars(strptr)
while ^strptr and ^(strptr + 1) <> ' '
memcpy(strptr + 2, strptr + 1, ^strptr)
^strptr = ^strptr - 1
loop
return ^strptr
end
def stripspaces(strptr)
while ^strptr and ^(strptr + ^strptr) <= ' '
^strptr = ^strptr - 1
loop
while ^strptr and ^(strptr + 1) <= ' '
memcpy(strptr + 2, strptr + 1, ^strptr)
^strptr = ^strptr - 1
loop
end
def striptrail(strptr)
byte i
for i = 1 to ^strptr
if (strptr)[i] == ' '
^strptr = i - 1
return
fin
next
end
def parsecmd(strptr)
byte cmd
cmd = 0
stripspaces(strptr)
if ^strptr
cmd = ^(strptr + 1)
memcpy(strptr + 2, strptr + 1, ^strptr)
^strptr = ^strptr - 1
fin
stripspaces(strptr)
return cmd
end
def resetmemfiles
;
; Close all files
;
^$BFD8 = 0
close(0)
;
; Set memory bitmap
;
memclr($BF58, 24)
^$BF58 = $CF
^$BF6F = $01
end
def execsys(sysfile)
byte refnum
word len
if ^sysfile
memcpy(sysfile, $280, ^sysfile + 1)
striptrail(sysfile)
refnum = open(sysfile, iobuffer)
if refnum
len = read(refnum, $2000, $FFFF)
resetmemfiles()
if len
memcpy($280, sysfile, ^$280 + 1)
if stripchars(sysfile) and ^$2000 == $4C and *$2003 == $EEEE
stripspaces(sysfile)
if ^$2006 <= ^sysfile
memcpy(sysfile, $2006, ^sysfile + 1)
fin
fin
striptrail($280)
exec()
fin
fin
fin
end
resetmemfiles()
execsys(autorun)
prstr(@version)
crout();
while 1
prstr(getpfx(@prefix))
cmdptr = rdstr($BA)
when toupper(parsecmd(cmdptr))
is 'Q'
reboot()
is 'C'
catalog(cmdptr)
is 'P'
setpfx(cmdptr)
is 'V'
volumes();
is '-'
execsys(cmdptr)
perr = $46
wend
if perr
prstr(@errorstr)
prbyte(perr)
else
prstr(@okstr)
fin
crout()
loop
done

View File

@ -236,12 +236,22 @@ int fixup_new(int tag, int type, int size)
/*
* Emit assembly code.
*/
#define BYTECODE_SEG 2
#define BYTECODE_SEG 8
#define INIT 16
static int outflags = 0;
static char *DB = ".BYTE";
static char *DW = ".WORD";
static char *DS = ".RES";
static char LBL = ':';
char *supper(char *s)
{
static char su[80];
int i;
for (i = 0; s[i]; i++)
su[i] = toupper(s[i]);
su[i] = '\0';
return su;
}
char *tag_string(int tag, int type)
{
static char str[16];
@ -260,6 +270,17 @@ char *tag_string(int tag, int type)
sprintf(str, "_%c%03d", t, tag);
return str;
}
void emit_dci(char *str, int len)
{
if (len--)
{
printf("\t; DCI STRING: %s\n", supper(str));
printf("\t%s\t$%02X", DB, toupper(*str++) | (len ? 0x80 : 0x00));
while (len--)
printf(",$%02X", toupper(*str++) | (len ? 0x80 : 0x00));
printf("\n");
}
}
void emit_flags(int flags)
{
outflags = flags;
@ -277,35 +298,83 @@ void emit_header(void)
printf("; ACME COMPATIBLE OUTPUT\n");
else
printf("; CA65 COMPATIBLE OUTPUT\n");
printf("_SEGBEGIN%c\n", LBL);
printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW);
printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW);
printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW);
if (outflags & MODULE)
{
printf("_SEGBEGIN%c\n", LBL);
printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW);
printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW);
printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW);
printf("\t%s\t_INIT\t\t\t; MODULE INITIALIZATION ROUTINE\n", DW);
}
}
void emit_rld(void)
{
int i;
printf(";\n; RE-LOCATEABLE DICTIONARY\n;\n");
/*
* First emit the bytecode definition entrypoint information.
*/
for (i = 0; i < globals; i++)
if (!(idglobal_type[i] & EXTERN_TYPE) && (idglobal_type[i] & DEF_TYPE))
{
printf("\t%s\t$02\t\t\t; CODE TABLE FIXUP\n", DB);
printf("\t%s\t_C%03d\t\t\n", DW, idglobal_tag[i]);
printf("\t%s\t$00\n", DB);
}
/*
* Now emit the fixup table.
*/
for (i = 0; i < fixups; i++)
{
if (fixup_type[i] & EXTERN_TYPE)
{
printf("\t%s\t$%02X\t\t\t; EXTERNAL FIXUP\n", DB, 0x11 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DB, fixup_tag[i]);
}
else
{
printf("\t%s\t$%02X\t\t\t; INTERNAL FIXUP\n", DB, 0x01 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t$00\n", DB);
}
}
printf("\t%s\t$00\t\t\t; END OF RLD\n", DB);
}
void emit_esd(void)
{
int i;
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
for (i = 0; i < globals; i++)
{
if (idglobal_type[i] & EXTERN_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$10\t\t\t; EXTERNAL SYMBOL FLAG\n", DB);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DW, idglobal_tag[i]);
}
else if (idglobal_type[i] & EXPORT_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$08\t\t\t; ENTRY SYMBOL FLAG\n", DB);
printf("\t%s\t%s\t\t\n", DW, tag_string(idglobal_tag[i], idglobal_type[i]));
}
}
printf("\t%s\t$00\t\t\t; END OF ESD\n", DB);
}
void emit_trailer(void)
{
if (!(outflags & BYTECODE_SEG))
emit_bytecode_seg();
printf("_SEGEND%c\n", LBL);
}
char *supper(char *s)
{
static char su[80];
int i;
for (i = 0; s[i]; i++)
su[i] = toupper(s[i]);
su[i] = '\0';
return su;
}
void emit_dci(char *str, int len)
{
if (len--)
if (!(outflags & INIT))
printf("_INIT\t=\t0\n");
if (outflags & MODULE)
{
printf("\t; DCI STRING: %s\n", supper(str));
printf("\t%s\t$%02X", DB, toupper(*str++) | (len ? 0x80 : 0x00));
while (len--)
printf(",$%02X", toupper(*str++) | (len ? 0x80 : 0x00));
printf("\n");
printf("_SEGEND%c\n", LBL);
emit_rld();
emit_esd();
}
}
void emit_moddep(char *name, int len)
@ -317,7 +386,7 @@ void emit_moddep(char *name, int len)
}
void emit_bytecode_seg(void)
{
if (!(outflags & BYTECODE_SEG))
if ((outflags & MODULE) && !(outflags & BYTECODE_SEG))
printf("_SUBSEG%c\t\t\t\t; BYTECODE STARTS\n", LBL);
outflags |= BYTECODE_SEG;
}
@ -411,6 +480,19 @@ int emit_data(int vartype, int consttype, long constval, int constsize)
}
return (datasize);
}
void emit_def(char *name, int is_bytecode)
{
if (!(outflags & MODULE))
{
printf("%s%c\n", name, LBL);
if (is_bytecode)
{
printf("\tJSR $03D0\n");
printf("\t%s\t$00\n", DB);
printf("\t%s\t*+2\n", DW);
}
}
}
void emit_codetag(int tag)
{
printf("_B%03d%c\n", tag, LBL);
@ -492,6 +574,20 @@ void emit_saw(int tag, int type)
printf("\t%s\t$7A\t\t\t; SAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_sab_ofst(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$78\t\t\t; SAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_saw_ofst(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7A\t\t\t; SAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_dab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
@ -589,9 +685,6 @@ void emit_ret(void)
{
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_def(int defopt)
{
}
void emit_enter(int framesize, int cparams)
{
if (framesize > 2)
@ -599,6 +692,8 @@ void emit_enter(int framesize, int cparams)
}
void emit_start(void)
{
printf("_INIT%c\n", LBL);
outflags |= INIT;
}
void emit_dup(void)
{
@ -716,60 +811,3 @@ int emit_op(t_token op)
}
return (1);
}
void emit_rld(void)
{
int i;
printf(";\n; RE-LOCATEABLE DICTIONARY\n;\n");
/*
* First emit the bytecode definition entrypoint information.
*/
for (i = 0; i < globals; i++)
if (!(idglobal_type[i] & EXTERN_TYPE) && (idglobal_type[i] & DEF_TYPE))
{
printf("\t%s\t$02\t\t\t; CODE TABLE FIXUP\n", DB);
printf("\t%s\t_C%03d\t\t\n", DW, idglobal_tag[i]);
printf("\t%s\t$00\n", DB);
}
/*
* Now emit the fixup table.
*/
for (i = 0; i < fixups; i++)
{
if (fixup_type[i] & EXTERN_TYPE)
{
printf("\t%s\t$%02X\t\t\t; EXTERNAL FIXUP\n", DB, 0x11 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DB, fixup_tag[i]);
}
else
{
printf("\t%s\t$%02X\t\t\t; INTERNAL FIXUP\n", DB, 0x01 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t$00\n", DB);
}
}
printf("\t%s\t$00\t\t\t; END OF RLD\n", DB);
}
void emit_esd(void)
{
int i;
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
for (i = 0; i < globals; i++)
{
if (idglobal_type[i] & EXTERN_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$10\t\t\t; EXTERNAL SYMBOL FLAG\n", DB);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DW, idglobal_tag[i]);
}
else if (idglobal_type[i] & EXPORT_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$08\t\t\t; ENTRY SYMBOL FLAG\n", DB);
printf("\t%s\t%s\t\t\n", DW, tag_string(idglobal_tag[i], idglobal_type[i]));
}
}
printf("\t%s\t$00\t\t\t; END OF ESD\n", DB);
}

View File

@ -1,4 +1,5 @@
#define ACME 1
#define MODULE 2
void emit_flags(int flags);
void emit_header(void);
void emit_trailer(void);
@ -10,6 +11,7 @@ void emit_idlocal(char *name, int value);
void emit_idglobal(int value, int size, char *name);
void emit_idfunc(int tag, int type, char *name);
void emit_idconst(char *name, int value);
void emit_def(char *name, int is_bytecode);
int emit_data(int vartype, int consttype, long constval, int constsize);
void emit_codetag(int tag);
void emit_const(int cval);
@ -27,6 +29,8 @@ void emit_dlb(int index);
void emit_dlw(int index);
void emit_sab(int tag, int type);
void emit_saw(int tag, int type);
void emit_sab_ofst(int tag, int offset, int type);
void emit_saw_ofst(int tag, int ofset, int type);
void emit_dab(int tag, int type);
void emit_daw(int tag, int type);
void emit_call(int tag, int type);
@ -51,7 +55,6 @@ void emit_pull(void);
void emit_drop(void);
void emit_leave(int framesize);
void emit_ret(void);
void emit_def(int defopt);
void emit_enter(int framesize, int cparams);
void emit_start(void);
void emit_rld(void);

62
PLASMA/src/loadcmd.s Normal file
View File

@ -0,0 +1,62 @@
SRC = TMP
SRCL = SRC
SRCH = SRC+1
DST = SRC+2
DSTL = DST
DSTH = DST+1
ESP = DST+2
!PSEUDOPC $1000 {
;*
;* CLEAR COMMAND LINE LENGTH BYTE IF CALLED FROM 'BYE'
;*
LDY #$00
LDX #$FE ; LEAVE ROOM FOR COMMAND LINE LENGTH BYTE
TXS
BVS +
STY $01FF ; CLEAR AUTORUN COMMAND WHEN CALLED FROM 'BYE'
;*
;* MOVE REST OF CMD FROM LANGUAGE CARD
;*
+ STY $06
STY $08
LDA #$D2
STA $07
LDA #$11
STA $09
BIT LCRDEN+LCBNK2
- LDA ($06),Y
STA ($08),Y
INY
BNE -
INC $07
INC $09
LDA $07
CMP #$E0
BNE -
;*
;* DEACTIVATE 80 COL CARDS
;*
BIT ROMEN
LDY #4
- LDA DISABLE80,Y
JSR $FDED
DEY
BPL -
BIT $C054 ; SET TEXT MODE
BIT $C051
BIT $C058
JSR $FC58 ; HOME
;*
;* JUMP TO INTERPRETER
;*
BIT LCRDEN+LCBNK2
LDX #$00
LDA #$BF
STX IFPL
STA IFPH
JSR INTERP
!BYTE 0
!WORD START
DISABLE80 !BYTE 21, 13, '1', 26, 13
!SOURCE "cmd.a"
}

View File

@ -32,15 +32,15 @@ $(PLVM): plvm.c
cc plvm.c -o $(PLVM)
TESTLIB: testlib.pla $(PLVM) $(PLASM)
./$(PLASM) -A < testlib.pla > testlib.a
./$(PLASM) -AM < testlib.pla > testlib.a
acme --setpc 4096 -o TESTLIB testlib.a
test: test.pla TESTLIB $(PLVM) $(PLASM)
./$(PLASM) -A < test.pla > test.a
./$(PLASM) -AM < test.pla > test.a
acme --setpc 4096 -o TEST.BIN test.a
./$(PLVM) TEST.BIN MAIN
debug: test.pla TESTLIB $(PLVM) $(PLASM)
./$(PLASM) -A < test.pla > test.a
./$(PLASM) -AM < test.pla > test.a
acme --setpc 4096 -o TEST.BIN test.a
./$(PLVM) -s TEST.BIN MAIN

View File

@ -863,32 +863,54 @@ int parse_stmnt(void)
case ID_TOKEN:
idptr = tokenstr;
type = id_type(tokenstr, tokenlen);
if (type & (VAR_TYPE | FUNC_TYPE))
addr = id_tag(tokenstr, tokenlen);
if (type & VAR_TYPE)
{
addr = id_tag(tokenstr, tokenlen);
if (scan() == SET_TOKEN)
int elem_type = type;
long elem_offset = 0;
if (scan() == DOT_TOKEN || scantoken == COLON_TOKEN)
{
if (type & VAR_TYPE)
{
if (!parse_expr())
{
parse_error("Bad expression");
return (0);
}
if (type & LOCAL_TYPE)
(type & BYTE_TYPE) ? emit_slb(addr) : emit_slw(addr);
else
(type & BYTE_TYPE) ? emit_sab(addr, type) : emit_saw(addr, type);
break;
}
/*
* Structure member offset
*/
int elem_size;
elem_type = (scantoken == DOT_TOKEN) ? BYTE_TYPE : WORD_TYPE;
if (!parse_constval(&elem_offset, &elem_size))
scantoken = ID_TOKEN;
else
scan();
printf("Structure offset = %d\n", elem_offset);
}
else if ((scantoken == EOL_TOKEN) && (type & FUNC_TYPE))
if (scantoken == SET_TOKEN)
{
if (!parse_expr())
{
parse_error("Bad expression");
return (0);
}
if (type & LOCAL_TYPE)
(elem_type & BYTE_TYPE) ? emit_slb(addr + elem_offset) : emit_slw(addr + elem_offset);
else if (elem_offset)
(elem_type & BYTE_TYPE) ? emit_sab_ofst(addr, elem_offset, type) : emit_saw_ofst(addr, elem_offset, type);
else
(elem_type & BYTE_TYPE) ? emit_sab(addr, type) : emit_saw(addr, type);
break;
}
}
else if (type & FUNC_TYPE)
{
if (scan() == EOL_TOKEN)
{
emit_call(addr, type);
emit_drop();
break;
}
}
else
{
parse_error("Syntax error");
return (0);
}
tokenstr = idptr;
default:
scan_rewind(tokenstr);
@ -1160,6 +1182,7 @@ int parse_defs(void)
c = tokenstr[tokenlen];
tokenstr[tokenlen] = '\0';
emit_idfunc(func_tag, type, tokenstr);
emit_def(tokenstr, 1);
tokenstr[tokenlen] = c;
idlocal_reset();
if (scan() == OPEN_PAREN_TOKEN)
@ -1230,6 +1253,7 @@ int parse_defs(void)
c = tokenstr[tokenlen];
tokenstr[tokenlen] = '\0';
emit_idfunc(func_tag, type, tokenstr);
emit_def(tokenstr, 0);
tokenstr[tokenlen] = c;
if (scan() == OPEN_PAREN_TOKEN)
{
@ -1250,7 +1274,6 @@ int parse_defs(void)
}
scan();
}
emit_def(1);
do
{
if (scantoken == EOL_TOKEN || scantoken == COMMENT_TOKEN)
@ -1288,7 +1311,5 @@ int parse_module(void)
}
}
emit_trailer();
emit_rld();
emit_esd();
return (0);
}

View File

@ -6,12 +6,30 @@
int main(int argc, char **argv)
{
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A')
emit_flags(ACME);
if (parse_module())
{
fprintf(stderr, "Compilation complete.\n");
int j, i, flags = 0;
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
j = 1;
while (argv[i][j])
{
switch(argv[i][j++])
{
case 'A':
flags |= ACME;
break;
case 'M':
flags |= MODULE;
break;
}
}
}
return (0);
}
emit_flags(flags);
if (parse_module())
{
fprintf(stderr, "Compilation complete.\n");
}
return (0);
}

View File

@ -45,6 +45,10 @@ byte symtbl[SYMTBLSZ];
byte *lastsym = symtbl;
byte modtbl[MODTBLSZ];
byte *lastmod = modtbl;
/*
* Predef.
*/
void interp(code *ip);
/*
* Utility routines.
*
@ -269,7 +273,7 @@ int extern_lookup(byte *esd, int index)
}
int load_mod(byte *mod)
{
int len, size, end, magic, bytecode, fixup, addr, modaddr = mark_heap();
int len, size, end, magic, bytecode, fixup, addr, init = 0, modaddr = mark_heap();
byte *moddep, *rld, *esd, *cdd, *sym;
byte header[128];
char filename[32], string[17];
@ -286,7 +290,8 @@ int load_mod(byte *mod)
* This is a relocatable bytecode module.
*/
bytecode = header[4] | (header[5] << 8);
moddep = header + 6;
init = header[6] | (header[7] << 8);
moddep = header + 8;
if (*moddep)
{
/*
@ -329,6 +334,7 @@ int load_mod(byte *mod)
printf("Module code+data size: %d\n", len);
printf("Module magic: $%04X\n", magic);
printf("Module bytecode: $%04X\n", bytecode);
printf("Module init: $%04X\n", init);
}
/*
* Print out the Re-Location Dictionary.
@ -415,6 +421,14 @@ int load_mod(byte *mod)
* Reserve heap space for relocated module.
*/
alloc_heap(end - modaddr);
/*
* Call init routine.
*/
if (init)
{
interp(mem_data + init + modaddr - MOD_ADDR);
POP;
}
return (fd > 0);
}
void interp(code *ip);

View File

@ -72,12 +72,97 @@ DVSIGN = TMPX
CLD
BIT LCRWEN+LCBNK2
BIT LCRWEN+LCBNK2
;*
;* INSTALL PAGE 3 VECTORS
;*
LDY #$10
- LDA PAGE3,Y
STA $03D0,Y
DEY
BPL -
;*
;* MOVE VM INTO LANGUAGE CARD
;*
LDA #<VMCORE
STA $06
LDA #>VMCORE
STA $07
LDA #$00
STA $08
LDA #$D0
STA $09
LDY #$00
- LDA ($06),Y ; COPY VM+CMD INTO LANGUAGE CARD
STA ($08),Y
INY
BNE -
INC $07
INC $09
LDA $09
CMP #$E0
BNE -
;*
;* INIT STACKS, FRAMES, AND HEAPS
;*
LDX #$FE
TXS
LDX #$00
STX $01FF
LDX #ESTKSZ/2
;*
;* LOOK FOR STARTUP FILE
;*
JSR PRODOS ; OPEN AUTORUN
!BYTE $C8
!WORD OPENPARMS
BCC +
JMP EXIT
+ LDA REFNUM
STA NLPARMS+1
JSR PRODOS
!BYTE $C9
!WORD NLPARMS
BCC +
JMP EXIT
+ LDA REFNUM
STA READPARMS+1
JSR PRODOS
!BYTE $CA
!WORD READPARMS
BCC +
JMP EXIT
+ LDX READPARMS+6
STX $01FF
EXIT JSR PRODOS
!BYTE $CC
!WORD CLOSEPARMS
LDY #$00
STY $06
LDA #$D1
STA $07
- LDA ($06),Y ; LOAD FIRST PAGE OF CMD INTO PLACE
STA $1000,Y
INY
BNE -
LDA #$7F
ADC #$01 ; SET V FLAG
JMP $1007 ; CALL CMD
AUTORUN !BYTE 7,"AUTORUN"
OPENPARMS !BYTE 3
!WORD AUTORUN
!WORD $0800
REFNUM !BYTE 0
NLPARMS !BYTE 3
!BYTE 0
!BYTE $7F
!BYTE $0D
READPARMS !BYTE 4
!BYTE 0
!WORD $0200
!WORD $0080
!WORD 0
CLOSEPARMS !BYTE 1
!BYTE 0
PAGE3 = *
!PSEUDOPC $03D0 {
;*
@ -90,7 +175,7 @@ CALLADR JSR $0000
BIT LCRDEN+LCBNK2
RTS
}
PLASMA = *
VMCORE = *
!PSEUDOPC $D000 {
;*
;* OPCODE TABLE
@ -104,6 +189,22 @@ OPTBL !WORD ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E
!WORD LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E
!WORD SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E
;*
;* OPXCODE TABLE
;*
OPXTBL !WORD ZEROX,ADDX,SUBX,MULX,DIVX,MODX,INCRX,DECRX ; 00 02 04 06 08 0A 0C 0E
!WORD NEGX,COMPX,BANDX,IORX,XORX,SHLX,SHRX,IDXWX ; 10 12 14 16 18 1A 1C 1E
!WORD LNOTX,LORX,LANDX,LAX,LLAX,CBX,CWX,SWAPX ; 20 22 24 26 28 2A 2C 2E
!WORD DROPX,DUPX,PUSHX,PULLX,BRLTX,BRGTX,BREQX,BRNEX ; 30 32 34 36 38 3A 3C 3E
!WORD ISEQX,ISNEX,ISGTX,ISLTX,ISGEX,ISLEX,BRFLSX,BRTRUX; 40 42 44 46 48 4A 4C 4E
!WORD BRNCHX,IBRNCHX,CALLX,ICALX,ENTERX,LEAVEX,RETX,NEXTOPX; 50 52 54 56 58 5A 5C 5E
!WORD LBX,LWX,LLBX,LLWX,LABX,LAWX,DLBX,DLWX ; 60 62 64 66 68 6A 6C 6E
!WORD SBX,SWX,SLBX,SLWX,SABX,SAWX,DABX,DAWX ; 70 72 74 76 78 7A 7C 7E
;*
;* COMMAND PROCESSING
;*
!SOURCE loadcmd.s
; !BINARY CMDLINE.BIN
;*
;* ENTER INTO BYTECODE INTERPRETER
;*
INTERP PLA
@ -145,24 +246,10 @@ NEXTOPX CLI
FETCHOPX SEI
STA ALTRDON
LDA (IP),Y
ORA #$80 ; SELECT OPX OPCODES
STA *+5
JMP (OPXTBL)
;*
;* ALIGN TO NEXT PAGE
;*
!ALIGN 255, 0
;*
;* OPXCODE TABLE
;*
OPXTBL !WORD ZEROX,ADDX,SUBX,MULX,DIVX,MODX,INCRX,DECRX ; 00 02 04 06 08 0A 0C 0E
!WORD NEGX,COMPX,BANDX,IORX,XORX,SHLX,SHRX,IDXWX ; 10 12 14 16 18 1A 1C 1E
!WORD LNOTX,LORX,LANDX,LAX,LLAX,CBX,CWX,SWAPX ; 20 22 24 26 28 2A 2C 2E
!WORD DROPX,DUPX,PUSHX,PULLX,BRLTX,BRGTX,BREQX,BRNEX ; 30 32 34 36 38 3A 3C 3E
!WORD ISEQX,ISNEX,ISGTX,ISLTX,ISGEX,ISLEX,BRFLSX,BRTRUX; 40 42 44 46 48 4A 4C 4E
!WORD BRNCHX,IBRNCHX,CALLX,ICALX,ENTERX,LEAVEX,RETX,NEXTOPX; 50 52 54 56 58 5A 5C 5E
!WORD LBX,LWX,LLBX,LLWX,LABX,LAWX,DLBX,DLWX ; 60 62 64 66 68 6A 6C 6E
!WORD SBX,SWX,SLBX,SLWX,SABX,SAWX,DABX,DAWX ; 70 72 74 76 78 7A 7C 7E
;*
;* ADD TOS TO TOS-1
;*
ADD LDA ESTKL,X

View File

@ -13,6 +13,7 @@ _SEGBEGIN
;
!WORD $DA7E ; MAGIC #
!WORD _SUBSEG ; BYTECODE SUB-SEGMENT
!WORD _INIT ; BYTECODE INIT ROUTINE
;
; MODULE DEPENDENCY LIST
; NOTE: DCI = PSUEDO OP FOR ASCII STRING WITH HI BIT SET EXCEPT LAST CHAR
@ -59,6 +60,8 @@ FIXUP7 !WORD $0000
!BYTE $54 ; CALL INCNT
FIXUP8 !WORD $0000
!BYTE $5A ; LEAVE
_INIT
!BYTE $5C ; RET
;
; END OF CODE/DATA + BYTECODE SEGMENT
;

View File

@ -49,4 +49,5 @@ export def indirect
mainptr()
end
ascii
done

View File

@ -4,6 +4,7 @@
import stdlib
predef cls, gotoxy, puts, putc
end
byte loadstr[] = "testlib loaded!\n"
;
; Define functions.
;
@ -20,4 +21,5 @@ export def puti(i)
fin
end
puts(@loadstr);
done