Commit 46b54da1 authored by John P. Willis's avatar John P. Willis
Browse files

Various lexer fixes; initial stack debugging

parent 7add47aa
VM_OBJS = ilxi.o asm.o cpu.o error.o host.o storage.o lexer.o inst.o util.o bus.o console.o signal.o
XIASM_OBJS = xiasm.o asm.o cpu.o lexer.o storage.o inst.o error.o util.o console.o bus.o signal.o
VM_OBJS = ilxi.o asm.o cpu.o error.o host.o storage.o lexer.o inst.o util.o bus.o console.o signal.o message.o
XIASM_OBJS = xiasm.o asm.o cpu.o lexer.o storage.o inst.o error.o util.o console.o bus.o signal.o message.o
FBCFLAGS = -g -mt
#-d LEXDEBUG
# -d STACKDEBUG
# -d LEXDEBUG
all: vm assembler rom
all: vm assembler rom test
vm: ilxi
vm: ilxim
test: t_stack.bin
rom: rom.bin xiasm
rom.bin: rom.xa
./xiasm rom.xa
t_stack.bin: t_stack.xa
./xiasm t_stack.xa
assembler: xiasm
xiasm: $(XIASM_OBJS)
......@@ -20,8 +26,8 @@ xiasm: $(XIASM_OBJS)
xiasm.o: xiasm.bas
fbc $(FBCFLAGS) -m xiasm -o xiasm.o -c xiasm.bas
ilxi: $(VM_OBJS)
fbc $(FBCFLAGS) -x ilxi $(VM_OBJS)
ilxim: $(VM_OBJS)
fbc $(FBCFLAGS) -x ilxim $(VM_OBJS)
asm.o: asm.bas
fbc $(FBCFLAGS) -o asm.o -c asm.bas
......@@ -59,5 +65,8 @@ ilxi.o: ilxi.bas
util.o: util.bas
fbc $(FBCFLAGS) -o util.o -c util.bas
message.o: message.bas
fbc $(FBCFLAGS) -o message.o -c message.bas
clean:
rm -f *.o ilxi xiasm rom.bin
rm -f *.o ilxim xiasm rom.bin
......@@ -9,7 +9,7 @@
#include "lexer.bi"
#include "storage.bi"
#include "util.bi"
#include "console.bi"
function asm_encode_amod(ops_following as ubyte, amod as ubyte, disp as ubyte) as ubyte
......@@ -368,17 +368,17 @@ end function ' asm_decode_register()
function asm_encode_opcode(instruction as string) as ubyte
select case lcase(instruction)
case "copy", "copy"
case "copy"
return OP_COPY
case "cpsz"
return OP_CPSZ
case "add", "add"
case "add"
return OP_ADD
case "sub", "sub"
case "sub"
return OP_SUB
case "mul", "mul"
case "mul"
return OP_MUL
case "div", "div"
case "div"
return OP_DIV
case "shl"
return OP_SHL
......@@ -692,9 +692,36 @@ function asm_disassemble(page as ushort, offset as ushort) as string
next i
dasm_offset = offset
return tmp_str
end function ' asm_disassemble()
sub asm_disassemble_range(page as ushort, start_offset as ushort, count as ushort)
dim i as integer = 0
dasm_offset = start_offset
mutexlock console_mutex
do
i += 1
print ilxi_pad_left(hex(page), "0", 4); ":";
print ilxi_pad_left(hex(dasm_offset), "0", 4); " ";
print asm_disassemble(page, dasm_offset)
dasm_offset += 1
if i = count then exit do
loop
mutexunlock console_mutex
end sub ' asm_disassemble_range()
function asm_bytes_to_ushort(lsb as ubyte, msb as ubyte) as ushort
return (msb shl 8) or lsb
end function ' asm_bytes_to_ushort()
......
......@@ -2,6 +2,7 @@
' asm.bi
'
common shared asm_offset as ushort
common shared dasm_offset as ushort
#define O_MASK &H80
#define AMOD_MASK &H78
......@@ -37,3 +38,4 @@ declare sub asm_assemble(instruction as string)
declare function asm_disassemble(page as ushort, offset as ushort) as string
declare function asm_bytes_to_ushort(lsb as ubyte, msb as ubyte) as ushort
declare sub asm_assemble_interactive(origin_address as ushort)
declare sub asm_disassemble_range(page as ushort, start_offset as ushort, count as ushort)
\ No newline at end of file
......@@ -8,6 +8,8 @@
#include "cpu.bi"
#include "storage.bi"
#include "error.bi"
#include "message.bi"
#include "console.bi"
sub bus_clear()
......@@ -30,7 +32,7 @@ sub bus_init()
dim i as integer
for i = 1 to dev_count
print "bus_init(): initializing device "; devices(i)
message_print "bus_init(): initializing device " & devices(i)
bus(devices(i)).dev_thread_started = 0
bus(devices(i)).dev_thread_stop_flag = 0
......@@ -44,7 +46,7 @@ sub bus_start()
dim i as integer
for i = 1 to dev_count
print "bus_start(): starting device "; devices(i)
message_print "bus_start(): starting device " & devices(i)
bus(devices(i)).dev_thread = threadcreate(bus(devices(i)).dev_cycle, @devices(i))
bus(devices(i)).dev_thread_started = 1
......@@ -60,7 +62,7 @@ sub bus_stop()
if bus(devices(i)).dev_thread_started = 1 then
bus(devices(i)).dev_thread_stop_flag = 1
print "bus_stop(): stopping device "; devices(i)
message_print "bus_stop(): stopping device " & devices(i)
threadwait bus(devices(i)).dev_thread
bus(devices(i)).dev_thread_started = 0
......@@ -88,15 +90,20 @@ sub bus_attach(device_number as ushort, dev as dev_entry)
for port = dev.io_base to dev.io_base + (dev.io_port_count - 1)
if io_ports(port) >= 0 then
mutexlock console_mutex
print "bus_attach(): port "; port;
print " requested by device "; device_number;
print " already bound to device "; io_ports(port)
print "bus_attach(): failed for device "; device_number
mutexunlock console_mutex
exit sub
else
print "bus_attach(): allocating port "; port; " to device "; device_number
message_print "bus_attach(): allocating port " & port & " to device " & device_number
io_ports(port) = device_number
end if
......
......@@ -26,7 +26,7 @@ sub console_attach()
end sub
sub console_init()
console_mutex = mutexcreate()
end sub
sub console_reset()
......@@ -42,9 +42,14 @@ sub console_output(port_number as ushort, value as ushort)
end sub
sub console_cycle(byval userdata as any ptr)
dim i as integer
dim c as ubyte
dim old_row as integer
dim old_col as integer
dim col as ubyte = 1 'x
dim row as ubyte = 1 'y
......@@ -52,6 +57,11 @@ sub console_cycle(byval userdata as any ptr)
col = 1
row = 1
old_row = csrlin()
old_col = pos()
mutexlock console_mutex
for i = CONSOLE_OFFSET to CONSOLE_LIMIT - 1
c = st_read_byte(CONSOLE_PAGE, i)
locate row, col, 0: print chr(c);
......@@ -62,8 +72,12 @@ sub console_cycle(byval userdata as any ptr)
else
col = col + 1
end if
next i
next i
locate old_row, old_col
mutexunlock console_mutex
sleep 25
if bus_get_stop_flag(0) = 1 then exit do
......
......@@ -5,6 +5,8 @@
#define CONSOLE_WIDTH 80
#define CONSOLE_HEIGHT 25
common shared console_mutex as any ptr
declare sub console_attach()
declare sub console_init()
declare sub console_reset()
......
......@@ -10,11 +10,12 @@
#include "console.bi"
#include "bus.bi"
#include "signal.bi"
#include "message.bi"
sub init_cpu()
with cpu_state
.pc = 1
.pc = 0
.ec = 0
.es = 0
......@@ -24,7 +25,7 @@ sub init_cpu()
.dp = 0
.ep = 0
.sp = 0
.so = PAGESIZE - 2
.so = PAGESIZE - 1
.ss = 0
.ds = 0
......@@ -66,6 +67,8 @@ function cpu_get_cppc() as string
tmp = ilxi_pad_left(hex(cpu_state.cp), "0", 4) & ":"
tmp &= ilxi_pad_left(hex(cpu_state.pc), "0", 4)
return tmp
end function
sub cpu()
......@@ -91,14 +94,6 @@ sub cpu()
do
inst_pc = cpu_state.pc
if cpu_get_flag(FL_DEBUG) then
print ilxi_pad_left(hex(cpu_state.cp), "0", 4); ":";
print ilxi_pad_left(hex(inst_pc), "0", 4); " ";
print asm_disassemble(cpu_state.cp, inst_pc)
end if
opcode = cpu_fetch()
op_count = asm_operand_count(opcode)
......@@ -273,25 +268,23 @@ sub cpu()
cpu_state.es = 0
end if
if cpu_get_flag(FL_HALT) then
if cpu_state.es > 0 then
print ""
print "cpu(): trap "; trim(str(cpu_state.ec)); " at pc = "; trim(str(cpu_state.pc))
else
print ""
print "cpu(): halt at "; ilxi_pad_left(hex(cpu_state.cp), "0", 4); ":"; ilxi_pad_left(hex(inst_pc), "0", 4)
end if
exit do
end if
if cpu_get_flag(FL_DEBUG) then exit do
if cpu_get_flag(FL_HALT) then exit do
if cpu_get_flag(FL_DEBUG) then exit do
loop
bus_stop
if cpu_get_flag(FL_DEBUG) = 0 then
if cpu_state.es > 0 then
message_print "cpu(): trap at " & cpu_get_cppc()
else
message_print "cpu(): halt at " & cpu_get_cppc()
end if
else
message_print cpu_get_cppc() & " " & asm_disassemble(cpu_state.cp, cpu_state.pc)
end if
end sub ' cpu()
function cpu_fetch() as ubyte
......@@ -303,13 +296,13 @@ function cpu_fetch() as ubyte
return t_byte
end function ' cpu_fetch()
function cpu_get_effective_address(operand as t_operand) as ushort
end function ' cpu_get_effective_address()
sub cpu_push_byte(byteval as ubyte)
st_write_byte cpu_state.sp, cpu_state.so, byteval
#ifdef STACKDEBUG
message_print "cpu_push_byte(): " & hex(byteval)
#endif
cpu_state.so -= 1
end sub ' cpu_push_byte()
......@@ -319,18 +312,34 @@ function cpu_pop_byte() as ubyte
retval = st_read_byte(cpu_state.sp, cpu_state.so)
cpu_state.so += 1
#ifdef STACKDEBUG
message_print "cpu_pop_byte(): " & hex(retval)
#endif
return retval
end function ' cpu_pop_byte()
sub cpu_push_word(wordval as ushort)
st_write_word cpu_state.sp, cpu_state.so - 1, wordval
cpu_state.so -= 2
#ifdef STACKDEBUG
locate 30,1
message_print "cpu_push_word(): " & hex(wordval)
#endif
cpu_state.so -= 1
end sub ' cpu_push_word()
function cpu_pop_word() as ushort
dim retval as ushort
retval = st_read_word(cpu_state.sp, cpu_state.so)
#ifdef STACKDEBUG
locate 30,1
message_print "cpu_pop_word(): " & hex(retval)
#endif
cpu_state.so += 2
end function ' cpu_pop_word()
......@@ -338,6 +347,8 @@ sub cpu_dump_state()
dim x as t_cpu_state
x = cpu_state
mutexlock console_mutex
print ""
print ""
print "Page Size:", PAGESIZE,"Page Count:",PAGECOUNT
......@@ -359,6 +370,8 @@ sub cpu_dump_state()
print " PL="; cpu_get_pl(); " PF="; cpu_get_flag(FL_PARITY); " SF="; cpu_get_flag(FL_SIGN); " DF="; cpu_get_flag(FL_DEBUG);
print ""
mutexunlock console_mutex
end sub ' cpu_dump_state()
sub cpu_set_flag(flag as ushort)
......
......@@ -16,7 +16,7 @@
' +--------+----------+--------+
'
' OPCODE (instruction opcode) 0-255
' O (operands following) 0 = no operands following; 1 = 1 operand following
' O (data type) 0 = byte; 1 = word
' MOD (addressing mode)
' 0 0000 = immediate
' 1 0001 = register direct
......@@ -42,13 +42,6 @@
' the operand will be one byte. If the addressing mode is a memory address,
' the operand will be two bytes.
'
' The end of an instruction is indicated by a zero in the most significant bit of
' the AMOD byte of a given operand.
'
' Example:
'
' STORE GA, [CP]+2
'
' opcodes
......
......@@ -10,6 +10,7 @@
#include "util.bi"
#include "console.bi"
#include "bus.bi"
#include "message.bi"
startup
......@@ -17,10 +18,13 @@ sub startup()
color 12,0: color 7,0 ' hack to get around weird terminal bug around 7 being the default
cls
message_init
print "ILXIM Virtual Machine"
print " Copyright (C) 2015 Coherent Logic Development LLC"
print ""
message_print "ILXIM Virtual Machine"
message_print " Copyright (C) 2015 Coherent Logic Development LLC"
message_print ""
bus_clear
console_attach
......@@ -33,6 +37,7 @@ end sub
sub cli()
dim last_cmd as string
dim cli_cmd as string
dim cmd_name as string
dim trace as integer
......@@ -41,8 +46,16 @@ sub cli()
trace = 0
do
last_cmd = cli_cmd
mutexlock console_mutex
line input "ilxim> ", cli_cmd
mutexunlock console_mutex
if cli_cmd = "" then cli_cmd = last_cmd
arg_count = lex(cli_cmd)
cmd_name = get_lexer_entry(0).strval
......@@ -82,27 +95,29 @@ sub cli()
end if
asm_assemble_interactive origin_addr
case "disassemble"
case "disassemble", "di"
dim page_addr as ushort
dim offset_addr as ushort
dim start_offset_addr as ushort
dim da_count as ushort
page_addr = cpu_state.cp
if get_lexer_entry(1).lexer_class = LC_BYTE then
page_addr = get_lexer_entry(1).byteval
start_offset_addr = get_lexer_entry(1).byteval
else
page_addr = get_lexer_entry(1).intval
start_offset_addr = get_lexer_entry(1).intval
end if
if get_lexer_entry(2).lexer_class = LC_BYTE then
offset_addr = get_lexer_entry(2).byteval
da_count = get_lexer_entry(2).byteval
else
offset_addr = get_lexer_entry(2).intval
end if
print ilxi_pad_left(hex(page_addr), "0", 4); ":";
print ilxi_pad_left(hex(offset_addr), "0", 4); " ";
da_count = get_lexer_entry(2).intval
endif
asm_disassemble_range page_addr, start_offset_addr, da_count
print asm_disassemble(page_addr, offset_addr)
case "step"
cpu_clear_flag FL_DEBUG
cpu_set_flag FL_DEBUG
cpu
case "getr"
......@@ -146,6 +161,8 @@ sub cli()
dim i as integer
dim k as integer
mutexlock console_mutex
for i = m_from to m_to step 8
print
......@@ -166,6 +183,9 @@ sub cli()
print
print
mutexunlock console_mutex
case "setm"
dim le_setm_addr as lexer_entry
dim le_setm_value as lexer_entry
......@@ -201,15 +221,17 @@ sub cli()
cpu
case "reset"
init_cpu
case "exit"
end
case else
shell cli_cmd
message_print "cli(): invalid command '" & cmd_name & "'"
end select
loop until cli_cmd = "exit"
end sub
sub ilxi_getr(register as string)
print ucase(register); ": "; trim(str(cpu_get_reg_alpha(lcase(register))))
sub ilxi_getr(register as string)
message_print ucase(register) & ": " & trim(str(cpu_get_reg_alpha(lcase(register))))
end sub
sub ilxi_setr(register as string, value as integer)
......
......@@ -101,6 +101,8 @@ end sub ' inst_setbyte()
sub inst_setword(op as t_operand, page as integer, value as ushort)
print "inst_setword(): "; value
if op.register = 1 then
if op.indirect = 0 then 'register direct
......@@ -731,9 +733,9 @@ sub inst_push(dest as t_operand)
select case dest.data_type
case DT_BYTE
cpu_push_byte inst_getbyte(dest, cpu_state.ds)
cpu_push_byte inst_getbyte(dest, cpu_state.dp)
case DT_WORD
cpu_push_word inst_getword(dest, cpu_state.ds)
cpu_push_word inst_getword(dest, cpu_state.dp)
end select
end sub ' inst_push()
......@@ -748,9 +750,9 @@ sub inst_pop(dest as t_operand)
select case dest.data_type
case DT_BYTE
inst_setbyte dest, cpu_state.ds, cpu_pop_byte()
inst_setbyte dest, cpu_state.dp, cpu_pop_byte()
case DT_WORD
inst_setword dest, cpu_state.ds, cpu_pop_word()
inst_setword dest, cpu_state.dp, cpu_pop_word()
end select
end sub ' inst_pop()
......
......@@ -20,6 +20,10 @@ function lex(input_str as string) as integer
dim recog_state as byte = LC_UNKNOWN
#ifdef LEXDEBUG
print "initial recog_state = LC_UNKNOWN"
#endif
lex_reset_storage
for i = 1 to len(input_str)
......@@ -30,33 +34,101 @@ function lex(input_str as string) as integer
case chr(34) ' double quote
if recog_state = LC_STR then
lex_post_string b
#ifdef LEXDEBUG
print "lex(): state transition (quote found) "; recog_state; "->";
#endif
recog_state = LC_UNKNOWN
#ifdef LEXDEBUG
print recog_state
#endif
b = ""
if not (i + 1 >= len(input_str)) then
if mid(input_str, i + 1, 1) = " " or mid(input_str, i + 1, 1) = "," then
i += 1
continue for
end if
end if
else
#ifdef LEXDEBUG
print "lex(): state transition (quote found) "; recog_state; "->";
#endif
recog_state = LC_STR
#ifdef LEXDEBUG
print recog_state
#endif
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
#ifdef LEXDEBUG
print "lex(): state transition (found 0-9) "; recog_state; "->";
#endif
recog_state = LC_NUM
#ifdef LEXDEBUG
print recog_state
#endif
end if
end if
case "a", "A", "b", "B", "c", "C", "e", "E", "f", "F"
case "a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"
if recog_state = LC_NUM then
hex_number = 1
b = b & ucase(c)
else
b = b & c
end if
case "h"
if recog_state = LC_NUM and (mid(input_str, i + 1, 1) = " " or mid(input_str, i + 1, 1) = "," or i = len(input_str)) then
hex_number = 1
else
b = b & c
end if
case "."
b = b & c
if (recog_state <> LC_STR) and (recog_state <> LC_WORD) then
#ifdef LEXDEBUG
print "lex(): state transition (found .) "; recog_state; "->";
#endif
recog_state = LC_FLOAT
#ifdef LEXDEBUG
print recog_state
#endif
end if