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

COPY working

parent 614a5d3d
......@@ -34,9 +34,9 @@ function asm_encode_amod(ops_following as ubyte, amod as ubyte, disp as ubyte) a
return t
end function ' asm_encode_amod()
function asm_amod_following(amod as ubyte) as ubyte
function asm_amod_datatype(amod as ubyte) as ubyte
return (amod and O_MASK) shr 7
end function ' asm_amod_following()
end function ' asm_amod_datatype()
function asm_amod_amod(amod as ubyte) as ubyte
return (amod and AMOD_MASK) shr 3
......@@ -184,7 +184,7 @@ function asm_encode_address(ops_following as ubyte, addr_string as string) as t_
addr_val = valint(addr_part)
tmp.low_byte = addr_val and &HFF
tmp.high_byte = (addr_val and &HF00) shr 8
tmp.high_byte = (addr_val and &HFF00) shr 8
tmp.byte_count = 2 ' always assume byte count = 2 for immediate data
elseif is_register = 1 then
......@@ -220,6 +220,14 @@ function asm_encode_register(register_name as string) as ubyte
return NREG_SP
case "so"
return NREG_SO
case "ss"
return NREG_SS
case "ds"
return NREG_DS
case "si"
return NREG_SI
case "di"
return NREG_DI
case "ga"
return NREG_GA
case "gb"
......@@ -295,6 +303,14 @@ function asm_decode_register(reg as ubyte) as string
return "sp"
case NREG_SO
return "so"
case NREG_SS
return "ss"
case NREG_DS
return "ds"
case NREG_SI
return "si"
case NREG_DI
return "di"
case NREG_GA
return "ga"
case NREG_GB
......@@ -352,15 +368,15 @@ end function ' asm_decode_register()
function asm_encode_opcode(instruction as string) as ubyte
select case lcase(instruction)
case "copy"
case "copy", "copy"
return OP_COPY
case "add"
case "add", "add"
return OP_ADD
case "sub"
case "sub", "sub"
return OP_SUB
case "mul"
case "mul", "mul"
return OP_MUL
case "div"
case "div", "div"
return OP_DIV
case "shl"
return OP_SHL
......@@ -484,6 +500,7 @@ sub asm_assemble(instruction as string)
dim opcode as ubyte = 0
dim operand as t_operand
dim ops_following as ubyte = 0
dim data_type as ubyte = 0
dim i as integer
......@@ -494,22 +511,23 @@ sub asm_assemble(instruction as string)
inst = get_lexer_entry(0).strval
opcode = asm_encode_opcode(inst)
select case lcase(get_lexer_entry(1).strval)
case "byte"
data_type = DT_BYTE
case "word"
data_type = DT_WORD
end select
st_write_byte cpu_state.ep, asm_offset, opcode
operand_count = asm_operand_count(opcode)
for i = 1 to operand_count
for i = 2 to operand_count + 1
asm_offset = asm_offset + 1
if i < operand_count then
ops_following = 1
else
ops_following = 0
end if
operand = asm_encode_address(ops_following, get_lexer_entry(i).strval)
operand = asm_encode_address(data_type, get_lexer_entry(i).strval)
' print "operand_count: "; operand_count; " operand: "; i; " amod: "; hex(operand.amod);
' print " low_byte: "; hex(operand.low_byte); " high_byte: "; hex(operand.high_byte)
......@@ -576,6 +594,15 @@ function asm_disassemble(page as ushort, offset as ushort) as string
operands(i).amod = st_read_byte(page, offset)
offset = offset + 1
if i = 1 then
select case asm_amod_datatype(operands(i).amod)
case DT_BYTE
tmp_str &= "byte "
case DT_WORD
tmp_str &= "word "
end select
end if
actual_amod = asm_amod_amod(operands(i).amod)
displacement = asm_decode_disp(asm_amod_disp(operands(i).amod))
......
......@@ -18,10 +18,12 @@ type t_operand
immediate as ubyte
has_displacement as ubyte
indirect as ubyte
data_type as ubyte ' 0 = byte, 1 = word
end type
declare function asm_encode_amod(ops_following as ubyte, amod as ubyte, disp as ubyte) as ubyte
declare function asm_amod_following(amod as ubyte) as ubyte
declare function asm_amod_datatype(amod as ubyte) as ubyte
declare function asm_amod_amod(amod as ubyte) as ubyte
declare function asm_amod_disp(amod as ubyte) as ubyte
declare function asm_decode_disp(disp as ubyte) as ushort
......
......@@ -21,7 +21,13 @@ sub init_cpu()
.dp = 0
.ep = 0
.sp = 0
.so = 0
.so = PAGESIZE - 1
.ss = 0
.ds = 0
.si = 0
.di = 0
.ga = 0
.gb = 0
......@@ -53,6 +59,7 @@ sub cpu()
dim operands() as t_operand
dim address_mode as ubyte
dim data_type as ubyte
cpu_clear_flag FL_HALT
......@@ -74,6 +81,10 @@ sub cpu()
for i = 1 to op_count
operands(i).amod = cpu_fetch()
operands(i).data_type = asm_amod_datatype(operands(i).amod)
address_mode = asm_amod_amod(operands(i).amod)
displacement = asm_decode_disp(asm_amod_disp(operands(i).amod))
......@@ -253,6 +264,33 @@ 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
cpu_state.so -= 1
end sub ' cpu_push_byte()
function cpu_pop_byte() as ubyte
dim retval as ubyte
retval = st_read_byte(cpu_state.sp, cpu_state.so)
cpu_state.so += 1
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
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)
cpu_state.so += 2
end function ' cpu_pop_word()
sub cpu_dump_state()
dim x as t_cpu_state
x = cpu_state
......@@ -262,7 +300,8 @@ sub cpu_dump_state()
print "Page Size:", PAGESIZE,"Page Count:",PAGECOUNT
print ""
print "PC "; ilxi_pad_left(hex(x.pc),"0",4), "EC "; ilxi_pad_left(hex(x.ec),"0",4), "ES "; ilxi_pad_left(hex(x.es),"0",4), "CP "; ilxi_pad_left(hex(x.cp),"0",4), "DP "; ilxi_pad_left(hex(x.dp),"0",4)
print "EP "; ilxi_pad_left(hex(x.ep),"0",4), "SP "; ilxi_pad_left(hex(x.sp),"0",4), "SO "; ilxi_pad_left(hex(x.so),"0",4), "FL "; ilxi_pad_left(hex(x.fl),"0",4)
print "EP "; ilxi_pad_left(hex(x.ep),"0",4), "SP "; ilxi_pad_left(hex(x.sp),"0",4), "SO "; ilxi_pad_left(hex(x.so),"0",4), "FL "; ilxi_pad_left(hex(x.fl),"0",4), "SS "; ilxi_pad_left(hex(x.ss),"0",4)
print "DS "; ilxi_pad_left(hex(x.ds),"0",4), "SI "; ilxi_pad_left(hex(x.ds),"0",4), "DI "; ilxi_pad_left(hex(x.di),"0",4)
print ""
print "GA "; ilxi_pad_left(hex(x.ga),"0",4), "GB "; ilxi_pad_left(hex(x.gb),"0",4), "GC "; ilxi_pad_left(hex(x.gc),"0",4), "GD "; ilxi_pad_left(hex(x.gd),"0",4), "GE "; ilxi_pad_left(hex(x.ge),"0",4)
print "GF "; ilxi_pad_left(hex(x.gf),"0",4), "GG "; ilxi_pad_left(hex(x.gg),"0",4), "GH "; ilxi_pad_left(hex(x.gh),"0",4), "GI "; ilxi_pad_left(hex(x.gi),"0",4), "GJ "; ilxi_pad_left(hex(x.gj),"0",4)
......@@ -326,6 +365,14 @@ sub cpu_set_reg_alpha(register as string, value as ushort)
cpu_state.sp = value
case REG_SO
cpu_state.so = value
case REG_SS
cpu_state.ss = value
case REG_DS
cpu_state.ds = value
case REG_SI
cpu_state.si = value
case REG_DI
cpu_state.di = value
case REG_GA
cpu_state.ga = value
case REG_GB
......@@ -406,6 +453,14 @@ function cpu_get_reg_alpha(register as string) as ushort
return cpu_state.sp
case REG_SO
return cpu_state.so
case REG_SS
return cpu_state.ss
case REG_DS
return cpu_state.ds
case REG_SI
return cpu_state.si
case REG_DI
return cpu_state.di
case REG_GA
return cpu_state.ga
case REG_GB
......@@ -486,6 +541,14 @@ sub cpu_set_reg(register as ubyte, value as ushort)
cpu_state.sp = value
case NREG_SO
cpu_state.so = value
case NREG_SS
cpu_state.ss = value
case NREG_DS
cpu_state.ds = value
case NREG_SI
cpu_state.si = value
case NREG_DI
cpu_state.di = value
case NREG_GA
cpu_state.ga = value
case NREG_GB
......@@ -567,6 +630,14 @@ function cpu_get_reg(register as ubyte) as ushort
return cpu_state.sp
case NREG_SO
return cpu_state.so
case NREG_SS
return cpu_state.ss
case NREG_DS
return cpu_state.ds
case NREG_SI
return cpu_state.si
case NREG_DI
return cpu_state.di
case NREG_GA
return cpu_state.ga
case NREG_GB
......
......@@ -57,7 +57,6 @@
#define OP_DATA 000
#define OP_COPY 001
#define OP_ADD 003
#define OP_SUB 004
#define OP_MUL 005
......@@ -140,6 +139,11 @@
#define REG_EP "ep"
#define REG_SP "sp"
#define REG_SO "so"
#define REG_SS "ss"
#define REG_DS "ds"
#define REG_SI "si"
#define REG_DI "di"
#define REG_GA "ga"
#define REG_GB "gb"
......@@ -186,6 +190,11 @@
#define NREG_EP 22
#define NREG_SP 23
#define NREG_SO 24
#define NREG_SS 25
#define NREG_DS 26
#define NREG_SI 27
#define NREG_DI 28
#define NREG_GA 40
#define NREG_GB 41
......@@ -247,6 +256,12 @@
#define PL_EXEC 2
#define PL_USER 3
'
' data types
'
#define DT_BYTE 0
#define DT_WORD 1
type t_cpu_state
pc as ushort 'program counter
......@@ -260,6 +275,12 @@ type t_cpu_state
ep as ushort 'extra page
sp as ushort 'stack page
so as ushort 'stack offset
ss as ushort 'source page
ds as ushort 'dest page
si as ushort 'source index
di as ushort 'dest index
ga as ushort 'general a
gb as ushort 'general b
......@@ -303,4 +324,8 @@ declare function cpu_fetch() 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
declare sub cpu_set_reg(register as ubyte, value as ushort)
declare function cpu_get_reg(register as ubyte) as ushort
\ No newline at end of file
declare function cpu_get_reg(register as ubyte) as ushort
declare sub cpu_push_byte(byteval as ubyte)
declare function cpu_pop_byte() as ubyte
declare sub cpu_push_word(wordval as ushort)
declare function cpu_pop_word() as ushort
\ No newline at end of file
......@@ -8,7 +8,6 @@
#define ERR_INVALID_PAGE_ID 1
#define ERR_INVALID_OFFSET 2
'
' 51-100: scheduling
'
......@@ -17,4 +16,9 @@
' 101-150: alu
'
'
' 151-200: instruction decoder
'
#define ERR_INVALID_DATA_TYPE 151
declare sub machine_error(error_code as integer, severity as integer)
\ No newline at end of file
......@@ -109,6 +109,10 @@ sub cli()
end if
ilxi_setr get_lexer_entry(1).strval, regval
case "pushb"
cpu_push_byte get_lexer_entry(1).byteval
case "pushw"
cpu_push_word get_lexer_entry(1).intval
case "getm"
dim le_from as lexer_entry
dim le_to as lexer_entry
......
......@@ -7,9 +7,147 @@
#include once "asm.bi"
#include "cpu.bi"
#include "ilxi.bi"
#include "error.bi"
function inst_getbyte(op as t_operand, page as integer) as ubyte
if op.register = 1 then
if op.indirect = 0 then 'register direct
select case op.low_byte
case NREG_LA, NREG_LB, NREG_LC, NREG_LC, NREG_LD, NREG_LE, NREG_HA, NREG_HB, NREG_HC, NREG_HD, NREG_HE
return cubyte(cpu_get_reg(op.low_byte))
case else
machine_error ERR_INVALID_DATA_TYPE, 10
exit function
end select
else 'register indirect
return st_read_byte(page, cpu_get_reg(op.low_byte) + op.displacement)
end if
elseif op.memory = 1 then
if op.indirect = 0 then 'memory direct
return st_read_byte(page, ((op.high_byte shl 8) or op.low_byte) + op.displacement)
else 'memory indirect
dim ptr_offset as ushort = (op.high_byte shl 8) or op.low_byte
dim ptr_val as ushort = st_read_word(page, ((op.high_byte shl 8) or op.low_byte))
return st_read_byte(page, ptr_val + op.displacement)
end if
elseif op.immediate = 1 then
return op.low_byte
end if
end function ' inst_getbyte()
function inst_getword(op as t_operand, page as integer) as ushort
if op.register = 1 then
if op.indirect = 0 then 'register direct
select case op.low_byte
case NREG_LA, NREG_LB, NREG_LC, NREG_LC, NREG_LD, NREG_LE, NREG_HA, NREG_HB, NREG_HC, NREG_HD, NREG_HE
machine_error ERR_INVALID_DATA_TYPE, 10
case else
return cpu_get_reg(op.low_byte)
end select
else 'register indirect
return st_read_word(page, cpu_get_reg(op.low_byte) + op.displacement)
end if
elseif op.memory = 1 then
if op.indirect = 0 then 'memory direct
return st_read_word(page, ((op.high_byte shl 8) or op.low_byte) + op.displacement)
else 'memory indirect
dim ptr_offset as ushort = (op.high_byte shl 8) or op.low_byte
dim ptr_val as ushort = st_read_word(page, ((op.high_byte shl 8) or op.low_byte))
return st_read_word(page, ptr_val + op.displacement)
end if
elseif op.immediate = 1 then
return ((op.high_byte shl 8) or op.low_byte)
end if
end function ' inst_getword()
sub inst_setbyte(op as t_operand, page as integer, value as ubyte)
if op.register = 1 then
if op.indirect = 0 then 'register direct
select case op.low_byte
case NREG_LA, NREG_LB, NREG_LC, NREG_LC, NREG_LD, NREG_LE, NREG_HA, NREG_HB, NREG_HC, NREG_HD, NREG_HE
cpu_set_reg op.low_byte, value
case else
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end select
else 'register indirect
st_write_byte page, cpu_get_reg(op.low_byte) + op.displacement, value
end if
elseif op.memory = 1 then
if op.indirect = 0 then 'memory direct
st_write_byte page, ((op.high_byte shl 8) or op.low_byte) + op.displacement, value
else 'memory indirect
dim ptr_offset as ushort = (op.high_byte shl 8) or op.low_byte
dim ptr_val as ushort = st_read_word(page, ((op.high_byte shl 8) or op.low_byte))
st_write_byte page, ptr_val + op.displacement, value
end if
elseif op.immediate = 1 then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
end sub ' inst_setbyte()
sub inst_setword(op as t_operand, page as integer, value as ushort)
if op.register = 1 then
if op.indirect = 0 then 'register direct
select case op.low_byte
case NREG_LA, NREG_LB, NREG_LC, NREG_LC, NREG_LD, NREG_LE, NREG_HA, NREG_HB, NREG_HC, NREG_HD, NREG_HE
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
case else
cpu_set_reg op.low_byte, value
end select
else 'register indirect
st_write_word page, cpu_get_reg(op.low_byte) + op.displacement, value
end if
elseif op.memory = 1 then
if op.indirect = 0 then 'memory direct
st_write_word page, ((op.high_byte shl 8) or op.low_byte) + op.displacement, value
else 'memory indirect
dim ptr_offset as ushort = (op.high_byte shl 8) or op.low_byte
dim ptr_val as ushort = st_read_word(page, ((op.high_byte shl 8) or op.low_byte))
st_write_word page, ptr_val + op.displacement, value
end if
elseif op.immediate = 1 then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
end sub ' inst_setword()
sub inst_copy(dest as t_operand, source as t_operand)
dim source_page as ushort = cpu_state.ss
dim dest_page as ushort = cpu_state.ds
if dest.data_type <> source.data_type then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
select case dest.data_type
case DT_BYTE
inst_setbyte dest, dest_page, inst_getbyte(source, source_page)
case DT_WORD
inst_setword dest, dest_page, inst_getword(source, source_page)
end select
end sub ' inst_copy()
sub inst_add(dest as t_operand, source as t_operand)
......
......@@ -28,6 +28,43 @@ sub st_write_byte(page as integer, offset as integer, value as byte)
mem(page).contents(offset) = value
end sub
function st_read_word(page as integer, offset as integer) as ushort
dim lsb as ubyte
dim msb as ubyte
if (page > (PAGECOUNT - 1)) or (page < 0) then
machine_error ERR_INVALID_PAGE_ID, 10
end if
if ((offset + 1) > (PAGESIZE - 1)) or (offset < 0) then
machine_error ERR_INVALID_OFFSET, 10
end if
lsb = st_read_byte(page, offset)
msb = st_read_byte(page, offset + 1)
return (msb shl 8) or lsb
end function
sub st_write_word(page as integer, offset as integer, wordval as ushort)
dim lsb as ubyte
dim msb as ubyte
if (page > (PAGECOUNT - 1)) or (page < 0) then
machine_error ERR_INVALID_PAGE_ID, 10
end if
if ((offset + 1) > (PAGESIZE - 1)) or (offset < 0) then
machine_error ERR_INVALID_OFFSET, 10
end if
lsb = wordval and &HFF
msb = (wordval and &HFF00) shr 8
st_write_byte page, offset, lsb
st_write_byte page, offset + 1, msb
end sub
sub st_load_page(file as string, page as integer)
dim file_handle as integer
......
......@@ -10,4 +10,6 @@ end type
declare function st_read_byte(page as integer, offset as integer) as byte
declare sub st_write_byte(page as integer, offset as integer, value as byte)
declare sub st_load_page(file as string, page as integer)
declare sub st_save_page(file as string, page as integer)
\ No newline at end of file
declare sub st_save_page(file as string, page as integer)
declare sub st_write_word(page as integer, offset as integer, wordval as ushort)
declare function st_read_word(page as integer, offset as integer) as ushort
\ No newline at end of file
......@@ -2,134 +2,154 @@
'
' xiasm.bas
'
' ILXI external assembler
' ILXIM external assembler
'
'
#define SYMTAB_SIZE &HFF
#include "asm.bi"
#include "storage.bi"
#include "lexer.bi"
#include "util.bi"
#include "xiasm.bi"
type symtab_entry
e_key as string
e_type as string
wordval as ushort
byteval as ubyte
strval as string
offset as byte
end type
sub main(args as string)
declare sub install_symbol(sym_entry as symtab_entry)
declare function lookup_symbol(key as string) as symtab_entry
declare function expand_macros(input_string as string) as string
dim arg_count as integer = 0
dim argi as integer = 0
dim shared symtab(SYMTAB_SIZE) as symtab_entry
dim shared stidx as integer = 0
arg_count = lex(args)
dim page_idx as integer = 0
dim arg_count as integer = 0
dim cur_arg as string
for argi = 0 to arg_count - 1
do_asm get_lexer_entry(argi).strval, argi
next argi
end
dim tmp_line as string
dim input_lines() as string
dim line_count as integer = 0
end sub
dim input_file_number as integer
dim input_file_name as string
sub do_asm(filename as string)
dim output_file_name as string
dim line_count as integer = read_source_file(filename)
input_file_name = command(-1)
input_file_number = freefile()
st_save_page output_file_name, 0
open input_file_name for input as #input_file_number
end sub
do while not eof(input_file_number)
function read_source_file(filename as string) as integer
line input #1, tmp_line
tmp_line = trim(tmp_line)
redim input_lines(1) as string
if (len(tmp_line) > 0) and (left(tmp_line, 1) <> ";") then
line_count += 1
redim preserve input_lines(line_count) as string
input_lines(line_count) = ltrim(tmp_line)
end if
loop
dim t_sym as symtab_entry
dim i as integer
for i = 1 to line_count
arg_count = lex(input_lines(i))
cur_arg = get_lexer_entry(0).strval
select case cur_arg
case "ORIGIN"
case "PROGRAM"
output_file_name = get_lexer_entry(3).strval
case "SYMBOL"
t_sym.e_key = get_lexer_entry(2).strval
t_sym.e_type = get_lexer_entry(1).strval
t_sym.offset = asm_offset
select case t_sym.e_type