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

Some encoding working

parent 56692fcd
OBJS = ilxi.o alu.o asm.o cpu.o error.o host.o storage.o lexer.o
FBCFLAGS = -g
FBCFLAGS = -g
#-d LEXDEBUG
ilxi: $(OBJS)
......
'
' asm.bas
'
' assembles instructions into dp:asm_offset
'
#include "asm.bi"
#include "cpu.bi"
#include "lexer.bi"
dim shared asm_offset as ushort = 0
function asm_encode_amod(ops_following as ubyte, amod as ubyte, disp as ubyte) as ubyte
' 7 6543 210
' +-+----+---+
' |O|MOD |DSP|
' +-+----+---+
' 1 6318 421
' 2 426
' 8
dim t as ubyte = 0
if ops_following = 1 then
t or= (1 shl 7)
end if
t or= (amod shl 3)
t or= (disp)
return t
end function
function asm_amod_following(amod as ubyte) as ubyte
return (amod and O_MASK) shr 7
end function
function asm_amod_amod(amod as ubyte) as ubyte
return (amod and AMOD_MASK) shr 4
end function
function asm_amod_disp(amod as ubyte) as ubyte
return (amod and DISP_MASK)
end function
function asm_encode_address(ops_following as ubyte, addr_string as string) as t_operand
'
' xxxx immediate
' %ga reg direct
' #xxxx mem direct
' (%ga) reg indirect
' (#xxxx) mem indirect
'
' Any of the last 4 with +xxxx appended indicates displacement;
' &H02-&HFF by powers of 2
'
dim byte_count as ubyte = 0
dim addr_part as string
dim addr_val as ushort
dim amod as ubyte
dim tmp as t_operand
dim is_immediate as ubyte = 0
dim is_register as ubyte = 0
dim is_memory as ubyte = 0
dim is_indirect as ubyte = 0
dim has_displacement as ubyte = 0
dim displacement as ubyte = 0
select case left(addr_string, 1)
case "%"
is_register = 1
addr_part = mid(addr_string, 2)
case "#"
is_memory = 1
addr_part = mid(addr_string, 2)
case "("
is_indirect = 1
select case mid(addr_string, 2, 1)
case "%"
is_register = 1
addr_part = mid(addr_string, 3)
addr_part = left(addr_part, instr(addr_part, ")") - 1)
case "#"
is_memory = 1
addr_part = mid(addr_string, 3)
addr_part = left(addr_part, instr(addr_part, ")") - 1)
end select
case else
is_immediate = 1
end select
if instr(addr_string, "+") > 0 then
has_displacement = 1
displacement = valint(mid(addr_string, instr(addr_string, "+") + 1))
select case displacement
case 2
displacement = 0
case 4
displacement = 1
case 8
displacement = 2
case 16
displacement = 3
case 32
displacement = 4
case 64
displacement = 5
case 128
displacement = 6
case 256
displacement = 7
end select
end if
if is_immediate = 1 then ' immediate
amod = asm_encode_amod(ops_following, AM_IMM, displacement)
elseif is_register = 1 then
if is_indirect = 1 then
if has_displacement = 1 then ' register indirect + displacement
amod = asm_encode_amod(ops_following, AM_REGID, displacement)
else ' reigster indirect, no displacement
amod = asm_encode_amod(ops_following, AM_REGI, displacement)
end if
else
if has_displacement = 1 then ' register direct + displacement
amod = asm_encode_amod(ops_following, AM_REGDD, displacement)
else ' register direct, no displacement
amod = asm_encode_amod(ops_following, AM_REGD, displacement)
end if
end if
elseif is_memory = 1 then
if is_indirect = 1 then
if has_displacement = 1 then ' memory indirect + displacement
amod = asm_encode_amod(ops_following, AM_MEMID, displacement)
else ' memory indirect, no displacement
amod = asm_encode_amod(ops_following, AM_MEMI, displacement)
end if
else
if has_displacement = 1 then ' memory direct + displacement
amod = asm_encode_amod(ops_following, AM_MEMDD, displacement)
else ' memory direct, no displacement
amod = asm_encode_amod(ops_following, AM_MEMD, displacement)
end if
end if
end if
if is_memory = 1 then
addr_val = valint(addr_part)
tmp.low_byte = addr_val and &HFF
tmp.high_byte = (addr_val and &HFF00) shr 8
if addr_val > 255 then
tmp.byte_count = 2
else
tmp.byte_count = 1
end if
elseif is_register = 1 then
addr_val = asm_encode_register(addr_part)
tmp.low_byte = addr_val
tmp.byte_count = 1
endif
tmp.amod = amod
return tmp
end function
function asm_encode_register(register_name as string) as ubyte
select case lcase(register_name)
case "pc"
return NREG_PC
case "ec"
return NREG_EC
case "es"
return NREG_ES
case "hf"
return NREG_HF
case "rf"
return NREG_RF
case "ei"
return NREG_EI
case "te"
return NREG_TE
case "pl"
return NREG_PL
case "cp"
return NREG_CP
case "dp"
return NREG_DP
case "sp"
return NREG_SP
case "so"
return NREG_SO
case "ga"
return NREG_GA
case "gb"
return NREG_GB
case "gc"
return NREG_GC
case "gd"
return NREG_GD
case "ge"
return NREG_GE
case "gf"
return NREG_GF
case "gg"
return NREG_GG
case "gh"
return NREG_GH
case "gi"
return NREG_GI
case "gj"
return NREG_GJ
case "gk"
return NREG_GK
case "gl"
return NREG_GL
case "gm"
return NREG_GM
case "gn"
return NREG_GN
case "go"
return NREG_GO
case "gp"
return NREG_GP
end select
end function
function asm_encode_opcode(instruction as string) as ubyte
select case lcase(instruction)
case "copy"
return OP_COPY
case "add"
return OP_ADD
case "sub"
return OP_SUB
case "mul"
return OP_MUL
case "div"
return OP_DIV
case "shl"
return OP_SHL
case "shr"
return OP_SHR
case "or"
return OP_OR
case "not"
return OP_NOT
case "and"
return OP_AND
case "xor"
return OP_XOR
case "eqv"
return OP_EQV
case "eq"
return OP_EQ
case "ne"
return OP_NE
case "gt"
return OP_GT
case "lt"
return OP_LT
case "ge"
return OP_GE
case "le"
return OP_LE
case "branch"
return OP_BRANCH
case "beq"
return OP_BEQ
case "bne"
return OP_BNE
case "ble"
return OP_BLE
case "bge"
return OP_BGE
case "blt"
return OP_BLT
case "bgt"
return OP_BGT
case "scall"
return OP_SCALL
case "lcall"
return OP_LCALL
case "icall"
return OP_ICALL
case "sret"
return OP_SRET
case "lret"
return OP_LRET
case "iret"
return OP_IRET
case "push"
return OP_PUSH
case "pop"
return OP_POP
case "nop"
return OP_NOP
case "hlt"
return OP_HLT
end select
end function
sub asm_assemble(instruction as string)
end sub
sub asm_assemble_interactive(origin_address as ushort)
end sub
\ No newline at end of file
......@@ -9,43 +9,44 @@
'
#include "cpu.bi"
#include "storage.bi"
#include "asm.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
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()
......@@ -58,17 +59,23 @@ sub cpu()
dim dst as integer
dim inst_size as ubyte
dim tmp as t_operand
tmp = asm_encode_address(1, "%ga")
tmp = asm_encode_address(1, "#05")
tmp = asm_encode_address(1, "#1024")
tmp = asm_encode_address(1, "(%ga)+4")
tmp = asm_encode_address(1, "(#05)+4")
tmp = asm_encode_address(1, "(#1024)+4")
cpu_state.hf = 0
do
opcode = cpu_fetch()
opcode = cpu_fetch()
inst_size = cpu_decode(opcode)
select case opcode
case OP_LOAD
case OP_STORE
case OP_COPY
case OP_ADD
......@@ -142,7 +149,7 @@ sub cpu()
end select
if cpu_state.pc >= PAGESIZE then
if cpu_state.pc >= (PAGESIZE - 1) then
cpu_state.hf = 1
cpu_state.ec = 0
cpu_state.es = 0
......@@ -195,7 +202,7 @@ sub cpu_dump_state()
print ""
end sub
sub cpu_set_reg_alpha(register as string, value as integer)
sub cpu_set_reg_alpha(register as string, value as ushort)
select case register
case REG_PC
......@@ -257,7 +264,7 @@ sub cpu_set_reg_alpha(register as string, value as integer)
end select
end sub
function cpu_get_reg_alpha(register as string) as integer
function cpu_get_reg_alpha(register as string) as ushort
select case register
case REG_PC
......
......@@ -12,24 +12,26 @@
' |BYTE 1 | BYTE 2 |BYTE 3 |
' +--------+----------+--------+
'
' OPCODE (instruction opcode) 0-255
' O (operands following) 0 = no operands following; 1 = 1 operand following
' MOD (addressing mode)
' 0000 = immediate
' 0001 = register direct
' 0010 = memory direct
' 0011 = register indirect
' 0100 = memory indirect
' 0101 = register indirect + displacement
' 0110 = memory indirect + displacement
' DISP 000 = 2 bytes displacement
' 001 = 4 bytes displacement
' 010 = 8 bytes displacement
' 011 = 16 bytes displacement
' 100 = 32 bytes displacement
' 101 = 64 bytes displacement
' 110 = 128 bytes displacement
' 111 = 256 bytes displacement
' OPCODE (instruction opcode) 0-255
' O (operands following) 0 = no operands following; 1 = 1 operand following
' MOD (addressing mode)
' 0 0000 = immediate
' 1 0001 = register direct
' 2 0010 = memory direct
' 3 0011 = register direct + displacement
' 4 0100 = memory direct + displacement
' 5 0101 = register indirect
' 6 0110 = memory indirect
' 7 0111 = register indirect + displacement
' 8 1000 = memory indirect + displacement
' DISP 0 000 = 2 bytes displacement
' 1 001 = 4 bytes displacement
' 2 010 = 8 bytes displacement
' 3 011 = 16 bytes displacement
' 4 100 = 32 bytes displacement
' 5 101 = 64 bytes displacement
' 6 110 = 128 bytes displacement
' 7 111 = 256 bytes displacement
'
' BYTE 1 is the OPCODE byte
' BYTE 2 is the AMOD byte for the first operand, describing
......@@ -98,10 +100,12 @@
#define AM_IMM 0
#define AM_REGD 1
#define AM_MEMD 2
#define AM_REGI 3
#define AM_MEMI 4
#define AM_REGID 5
#define AM_MEMID 6
#define AM_REGDD 3
#define AM_MEMDD 4
#define AM_REGI 5
#define AM_MEMI 6
#define AM_REGID 7
#define AM_MEMID 8
'
' addressing displacements; 4 most significant bits
......@@ -196,7 +200,8 @@
#define NREG_GO 54
#define NREG_GP 55
type t_cpu_state
type t_cpu_state
pc as ushort 'program counter
ec as ushort 'error code
......@@ -226,7 +231,7 @@ type t_cpu_state
gl as ushort 'general l
gm as ushort 'general m
gn as ushort 'general n
go as ushort 'general o
go as ushort 'general o
gp as ushort 'general p
end type
......@@ -248,4 +253,4 @@ declare sub cpu_dump_state()
declare function cpu_fetch() as ubyte
declare function cpu_decode(opcode as ubyte) as ubyte
declare sub cpu_set_reg_alpha(register as string, value as ushort)
declare function cpu_get_reg_alpha(register as string) as ushort
\ No newline at end of file
declare function cpu_get_reg_alpha(register as string) as ushort
'
' ilxi.bas
'
#include "ilxi.bi"
#include "cpu.bi"
#include "lexer.bi"
#include "storage.bi"
#include "asm.bi"
startup
sub startup()
print "ILXI Virtual Machine"
print "ILXIM Virtual Machine"
print " Copyright (C) 2015 Coherent Logic Development LLC"
print ""
......@@ -16,109 +22,124 @@ sub startup()
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 "getr"
ilxi_getr get_lexer_entry(1).strval
case "setr"
line input "ilxim> ", cli_cmd
arg_count = lex(cli_cmd)
cmd_name = get_lexer_entry(0).strval
select case cmd_name
case "assemble"
dim le_origin as lexer_entry
dim origin_addr as ushort
if get_lexer_entry(1).lexer_class = LC_BYTE then
origin_addr = get_lexer_entry(1).byteval
else
origin_addr = get_lexer_entry(1).intval
end if
asm_assemble_interactive origin_addr
case "getr"
ilxi_getr get_lexer_entry(1).strval
case "setr"
dim regval as integer
if get_lexer_entry(2).lexer_class = LC_BYTE then
regval = get_lexer_entry(2).byteval
elseif get_lexer_entry(2).lexer_class = LC_INT then
regval = get_lexer_entry(2).intval
end if
if get_lexer_entry(2).lexer_class = LC_BYTE then
regval = get_lexer_entry(2).byteval
elseif get_lexer_entry(2).lexer_class = LC_INT then
regval = get_lexer_entry(2).intval
end if
ilxi_setr get_lexer_entry(1).strval, regval
case "getm"
dim le_from as lexer_entry
dim le_to as lexer_entry
dim m_from as integer
dim m_to as integer
case "getm"
dim le_from as lexer_entry
dim le_to as lexer_entry
dim m_from as integer
dim m_to as integer
le_from = get_lexer_entry(1)
le_to = get_lexer_entry(2)
if le_from.lexer_class = LC_BYTE then
m_from = le_from.byteval
else
m_from = le_from.intval
end if
if le_to.lexer_class = LC_BYTE then
m_to = le_to.byteval
else
m_to = le_to.intval
end if
le_from = get_lexer_entry(1)
le_to = get_lexer_entry(2)
if le_from.lexer_class = LC_BYTE then
m_from = le_from.byteval
else
m_from = le_from.intval
end if
if le_to.lexer_class = LC_BYTE then
m_to = le_to.byteval
else
m_to = le_to.intval
end if
dim i as integer
dim k as integer
for i = m_from to m_to step 8
print
print trim(ilxi_pad_left(hex(cpu_state.dp), "0", 4)); ":";
print trim(ilxi_pad_left(hex(i), "0", 4)),
for k = i to i + 7
print ilxi_pad_left(hex(st_read_byte(cpu_state.dp, k)), "0", 2); " ";