Commit 7e535c46 authored by John P. Willis's avatar John P. Willis
Browse files

Initial commit

parents
OBJS = ilxi.o alu.o asm.o cpu.o error.o host.o storage.o lexer.o
FBCFLAGS = -g
#-d LEXDEBUG
ilxi: $(OBJS)
fbc $(FBCFLAGS) -x ilxi $(OBJS)
alu.o: alu.bas
fbc $(FBCFLAGS) -o alu.o -c alu.bas
asm.o: asm.bas
fbc $(FBCFLAGS) -o asm.o -c asm.bas
cpu.o: cpu.bas
fbc $(FBCFLAGS) -o cpu.o -c cpu.bas
error.o: error.bas
fbc $(FBCFLAGS) -o error.o -c error.bas
host.o: host.bas
fbc $(FBCFLAGS) -o host.o -c host.bas
storage.o: storage.bas
fbc $(FBCFLAGS) -o storage.o -c storage.bas
lexer.o: lexer.bas
fbc $(FBCFLAGS) -o lexer.o -c lexer.bas
ilxi.o: ilxi.bas
fbc -m ilxi $(FBCFLAGS) -o ilxi.o -c ilxi.bas
clean:
rm -f *.o ilxi
'
' cpu.bas
'
'
' instruction format
'
' OPCODE SRCMOD SRCBYTES SRC DSTMOD DSTBYTES DST
'
#include "cpu.bi"
#include "storage.bi"
sub init_cpu()
with cpu_state
.pc = 0
.ec = 0
.es = 0
.hf = 0
.rf = 0
.ei = 1
.te = 0
.pl = 0
.cp = 0
.dp = 0
.sp = 0
.so = 0
.ga = 0
.gb = 0
.gc = 0
.gd = 0
.ge = 0
.gf = 0
.gg = 0
.gh = 0
.gi = 0
.gj = 0
.gk = 0
.gl = 0
.gm = 0
.gn = 0
.go = 0
.gp = 0
end with
end sub
sub cpu()
dim opcode as byte
dim srcmod as byte
dim srcbytes as byte
dim src as integer
dim dstmod as byte
dim dstbytes as byte
dim dst as integer
dim inst_size as byte
cpu_state.hf = 0
do
opcode = cpu_fetch()
inst_size = cpu_decode(opcode)
select case opcode
case 0 'NOP
case 1 'HLT
cpu_state.hf = 1
case else
end select
if cpu_state.pc >= PAGESIZE then
cpu_state.hf = 1
cpu_state.ec = 0
cpu_state.es = 0
end if
if cpu_state.hf > 0 then
if cpu_state.es > 0 then
print "cpu(): trap "; trim(str(cpu_state.ec)); " at pc = "; trim(str(cpu_state.pc))
else
print "cpu(): halt at pc = "; trim(str(cpu_state.pc))
end if
exit do
end if
if (cpu_state.pc + inst_size) <= PAGESIZE then
cpu_state.pc = cpu_state.pc + inst_size
end if
if cpu_state.te > 0 then cpu_dump_state
loop
end sub
function cpu_fetch() as byte
return st_read_byte(cpu_state.cp, cpu_state.pc)
end function
function cpu_decode(opcode as byte) as byte
return 1
end function
sub cpu_dump_state()
dim x as t_cpu_state
x = cpu_state
print ""
print ""
print "Page Size:", PAGESIZE,"Page Count:",PAGECOUNT
print ""
print "PC "; x.pc, "EC "; x.ec, "ES "; x.es, "HF "; x.hf, "RF "; x.rf
print "CP "; x.cp, "DP "; x.dp, "SP "; x.sp, "SO "; x.so, "EI"; x.ei
print "TE "; x.te, "PL "; x.pl
print ""
print "GA "; x.ga, "GB "; x.gb, "GC "; x.gc, "GD "; x.gd, "GE "; x.ge
print "GF "; x.gf, "GG "; x.gg, "GH "; x.gh, "GI "; x.gi, "GJ "; x.gj
print "GK "; x.gk, "GL "; x.gl, "GM "; x.gm, "GN "; x.gn, "GO "; x.go
print "GP "; x.gp
print ""
end sub
sub cpu_set_reg_alpha(register as string, value as byte)
select case register
case REG_PC
cpu_state.pc = value
case REG_EC
cpu_state.ec = value
case REG_ES
cpu_state.es = value
case REG_HF
cpu_state.hf = value
case REG_RF
cpu_state.rf = value
case REG_EI
cpu_state.ei = value
case REG_TE
cpu_state.te = value
case REG_PL
cpu_state.pl = value
case REG_CP
cpu_state.cp = value
case REG_DP
cpu_state.dp = value
case REG_SP
cpu_state.sp = value
case REG_SO
cpu_state.so = value
case REG_GA
cpu_state.ga = value
case REG_GB
cpu_state.gb = value
case REG_GC
cpu_state.gc = value
case REG_GD
cpu_state.gd = value
case REG_GE
cpu_state.ge = value
case REG_GF
cpu_state.gf = value
case REG_GG
cpu_state.gg = value
case REG_GH
cpu_state.gh = value
case REG_GI
cpu_state.gi = value
case REG_GJ
cpu_state.gj = value
case REG_GK
cpu_state.gk = value
case REG_GL
cpu_state.gl = value
case REG_GM
cpu_state.gm = value
case REG_GN
cpu_state.gn = value
case REG_GO
cpu_state.go = value
case REG_GP
cpu_state.gp = value
end select
end sub
function cpu_get_reg_alpha(register as string) as byte
select case register
case REG_PC
return cpu_state.pc
case REG_EC
return cpu_state.ec
case REG_ES
return cpu_state.es
case REG_HF
return cpu_state.hf
case REG_RF
return cpu_state.rf
case REG_EI
return cpu_state.ei
case REG_TE
return cpu_state.te
case REG_PL
return cpu_state.pl
case REG_CP
return cpu_state.cp
case REG_DP
return cpu_state.dp
case REG_SP
return cpu_state.sp
case REG_SO
return cpu_state.so
case REG_GA
return cpu_state.ga
case REG_GB
return cpu_state.gb
case REG_GC
return cpu_state.gc
case REG_GD
return cpu_state.gd
case REG_GE
return cpu_state.ge
case REG_GF
return cpu_state.gf
case REG_GG
return cpu_state.gg
case REG_GH
return cpu_state.gh
case REG_GI
return cpu_state.gi
case REG_GJ
return cpu_state.gj
case REG_GK
return cpu_state.gk
case REG_GL
return cpu_state.gl
case REG_GM
return cpu_state.gm
case REG_GN
return cpu_state.gn
case REG_GO
return cpu_state.go
case REG_GP
return cpu_state.gp
end select
end function
\ No newline at end of file
'
' cpu.bi
'
'
' register names (string)
'
#define REG_PC "pc"
#define REG_EC "ec"
#define REG_ES "es"
#define REG_HF "hf"
#define REG_RF "rf"
#define REG_EI "ei"
#define REG_TE "te"
#define REG_PL "pl"
#define REG_CP "cp"
#define REG_DP "dp"
#define REG_SP "sp"
#define REG_SO "so"
#define REG_GA "ga"
#define REG_GB "gb"
#define REG_GC "gc"
#define REG_GD "gd"
#define REG_GE "ge"
#define REG_GF "gf"
#define REG_GG "gg"
#define REG_GH "gh"
#define REG_GI "gi"
#define REG_GJ "gj"
#define REG_GK "gk"
#define REG_GL "gl"
#define REG_GM "gm"
#define REG_GN "gn"
#define REG_GO "go"
#define REG_GP "gp"
'
' register encodings (numeric)
'
#define NREG_PC 0
#define NREG_EC 1
#define NREG_ES 2
#define NREG_HF 3
#define NREG_RF 4
#define NREG_EI 5
#define NREG_TE 6
#define NREG_PL 7
#define NREG_CP 20
#define NREG_DP 21
#define NREG_SP 22
#define NREG_SO 23
#define NREG_GA 40
#define NREG_GB 41
#define NREG_GC 42
#define NREG_GD 43
#define NREG_GE 44
#define NREG_GF 45
#define NREG_GG 46
#define NREG_GH 47
#define NREG_GI 48
#define NREG_GJ 49
#define NREG_GK 50
#define NREG_GL 51
#define NREG_GM 52
#define NREG_GN 53
#define NREG_GO 54
#define NREG_GP 55
type t_cpu_state
pc as integer 'program counter
ec as integer 'error code
es as integer 'error severity
hf as integer 'halt flag
rf as integer 'result flag
ei as integer 'enable interrupts
te as integer 'trace enable
pl as integer 'privilege level
cp as integer 'code page
dp as integer 'data page
sp as integer 'stack page
so as integer 'stack offset
ga as integer 'general a
gb as integer 'general b
gc as integer 'general c
gd as integer 'general d
ge as integer 'general e
gf as integer 'general f
gg as integer 'general g
gh as integer 'general h
gi as integer 'general i
gj as integer 'general j
gk as integer 'general k
gl as integer 'general l
gm as integer 'general m
gn as integer 'general n
go as integer 'general o
gp as integer 'general p
end type
common shared cpu_state as t_cpu_state
declare sub init_cpu()
declare sub cpu()
declare sub cpu_dump_state()
declare function cpu_fetch() as byte
declare function cpu_decode(opcode as byte) as byte
declare sub cpu_set_reg_alpha(register as string, value as byte)
declare function cpu_get_reg_alpha(register as string) as byte
\ No newline at end of file
#include "error.bi"
#include "cpu.bi"
sub machine_error(error_code as integer, severity as integer)
'
' copy error info to proper flags and dump state
'
dim new_ec as integer
cpu_state.ec = error_code
cpu_state.es = severity
if severity >= 10 then
cpu_state.hf = 1
end if
end sub
\ No newline at end of file
'
' error.bi
'
'
' 1 - 50: storage
'
#define ERR_INVALID_PAGE_ID 1
#define ERR_INVALID_OFFSET 2
'
' 51-100: scheduling
'
'
' 101-150: alu
'
declare sub machine_error(error_code as integer, severity as integer)
\ No newline at end of file
#include "ilxi.bi"
#include "cpu.bi"
#include "lexer.bi"
startup
sub startup()
print "ILXI Virtual Machine"
print " Copyright (C) 2015 Coherent Logic Development LLC"
print ""
init_cpu
cli
end
end sub
sub cli()
dim cli_cmd as string
dim cmd_name as string
dim trace as integer
dim arg_count as integer = 0
trace = 0
do
line input "ilxi> ", cli_cmd
arg_count = lex(cli_cmd)
cmd_name = get_lexer_entry(0).strval
select case cmd_name
case "gr"
case "dumpcpu"
cpu_dump_state
case "trace"
if trace = 0 then
trace = 1
print "trace on"
else
trace = 0
print "trace off"
end if
cpu_state.te = trace
case "ver"
print "ILXI 0.1"
case "run"
cpu
case "reset"
init_cpu
cpu_state.te = trace
case else
shell cli_cmd
end select
loop until cli_cmd = "exit"
end sub
\ No newline at end of file
declare sub startup()
declare sub cli()
\ No newline at end of file
'
' lexer.bas
'
#include "lexer.bi"
function lex(input_str as string) as integer
dim i as integer
dim c as string
dim b as string
dim tmp_byte as byte
dim tmp_int as integer
dim tmp_float as double
dim in_quoted_string as integer = 0
dim recog_state as byte = LC_UNKNOWN
lex_reset_storage
for i = 1 to len(input_str)
c = mid(input_str, i, 1)
select case c
case chr(34) ' double quote
if recog_state = LC_STR then
lex_post_string b
recog_state = LC_UNKNOWN
b = ""
else
recog_state = LC_STR
end if
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
b = b & c
if (recog_state <> LC_STR) and (recog_state <> LC_WORD) then
if recog_state <> LC_FLOAT then
recog_state = LC_NUM
end if
end if
case "."
b = b & c
if (recog_state <> LC_STR) and (recog_state <> LC_WORD) then
recog_state = LC_FLOAT
end if
case " "
if recog_state = LC_NUM then
if val(b) < 256 then
lex_post_byte cubyte(val(b))
elseif val(b) >= 256 then
lex_post_int valint(b)
end if
b = ""
recog_state = LC_UNKNOWN
elseif recog_state = LC_FLOAT then
lex_post_float val(b)
b = ""
recog_state = LC_UNKNOWN
elseif recog_state = LC_WORD then
lex_post_word b
b = ""
recog_state = LC_UNKNOWN
elseif recog_state = LC_STR then
b = b & c
end if
case else
b = b & c
if recog_state <> LC_STR then
recog_state = LC_WORD
end if
end select
next i
'
' handle running off the end with no space found
'
if recog_state = LC_NUM then
if val(b) < 256 then
lex_post_byte cubyte(val(b))
elseif val(b) >= 256 then
lex_post_int valint(b)
end if
elseif recog_state = LC_FLOAT then
lex_post_float val(b)
b = ""
elseif recog_state = LC_WORD then
lex_post_word b
b = ""
elseif recog_state = LC_STR then
print "lex(): unterminated string literal"
exit function
end if
#ifdef LEXDEBUG
print "lexer_index = "; lexer_index
for i = 0 to lexer_index - 1
print trim(str(i));": ";
print " lexer_class = "; lexer_entries(i).lexer_class;
print " byteval = "; lexer_entries(i).byteval; " intval = "; lexer_entries(i).intval;
print " floatval = "; lexer_entries(i).floatval;
print " strval = "; lexer_entries(i).strval
next i
#endif
return lexer_index
end function
sub lex_reset_storage()
dim i as integer
for i = 0 to (LEXSIZE - 1)
with lexer_entries(i)
.lexer_class = LC_UNKNOWN
.intval = 0
.floatval = 0
.byteval = 0
.strval = ""
end with
next i
lexer_index = 0
end sub
sub lex_post_word(input_string as string)
with lexer_entries(lexer_index)
.lexer_class = LC_WORD
.strval = input_string
end with
if lexer_index <= LEXSIZE then
lexer_index = lexer_index + 1
else
print "lex_post_word(): lexer overflow"
exit sub
end if
end sub
sub lex_post_string(input_string as string)
with lexer_entries(lexer_index)