Commit 7add47aa authored by John P. Willis's avatar John P. Willis

Signal handling added; implementation of all bitwise operators

parent d77e65a0
VM_OBJS = ilxi.o asm.o cpu.o error.o host.o storage.o lexer.o inst.o util.o bus.o console.o
XIASM_OBJS = xiasm.o asm.o cpu.o lexer.o storage.o inst.o error.o util.o console.o bus.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
XIASM_OBJS = xiasm.o asm.o cpu.o lexer.o storage.o inst.o error.o util.o console.o bus.o signal.o
FBCFLAGS = -g -mt
#-d LEXDEBUG
......@@ -26,6 +26,9 @@ ilxi: $(VM_OBJS)
asm.o: asm.bas
fbc $(FBCFLAGS) -o asm.o -c asm.bas
signal.o: signal.bas
fbc $(FBCFLAGS) -o signal.o -c signal.bas
bus.o: bus.bas
fbc $(FBCFLAGS) -o bus.o -c bus.bas
......
......@@ -426,6 +426,10 @@ function asm_encode_opcode(instruction as string) as ubyte
return OP_PUSH
case "pop"
return OP_POP
case "in"
return OP_IN
case "out"
return OP_OUT
case "nop"
return OP_NOP
case "hlt"
......@@ -493,6 +497,10 @@ function asm_decode_opcode(opcode as ubyte) as string
return "push"
case OP_POP
return "pop"
case OP_IN
return "in"
case OP_OUT
return "out"
case OP_NOP
return "nop"
case OP_HLT
......@@ -563,7 +571,7 @@ function asm_operand_count(opcode as ubyte) as ubyte
return 2
case OP_BRANCH, OP_SCALL, OP_ICALL, OP_PUSH, OP_POP
return 1
case OP_LCALL
case OP_LCALL, OP_IN, OP_OUT
return 2
case OP_BEQ, OP_BNE, OP_BZ, OP_BLT, OP_BGT
return 1
......
......@@ -9,6 +9,7 @@
#include "inst.bi"
#include "console.bi"
#include "bus.bi"
#include "signal.bi"
sub init_cpu()
......@@ -54,9 +55,19 @@ sub init_cpu()
st_load_page "rom.bin", 0
bus_init
signal_init
end sub
function cpu_get_cppc() as string
dim tmp as string
tmp = ilxi_pad_left(hex(cpu_state.cp), "0", 4) & ":"
tmp &= ilxi_pad_left(hex(cpu_state.pc), "0", 4)
end function
sub cpu()
dim clock_count as long = 0
......@@ -236,6 +247,10 @@ sub cpu()
inst_push operands(1)
case OP_POP
inst_pop operands(1)
case OP_IN
inst_in operands(1), operands(2)
case OP_OUT
inst_out operands(1), operands(2)
case OP_NOP
' do nothing
case OP_HLT
......
......@@ -89,6 +89,9 @@
#define OP_PUSH 033
#define OP_POP 034
#define OP_IN 040
#define OP_OUT 041
#define OP_NOP 254
#define OP_HLT 255
......@@ -315,6 +318,7 @@ end type
common shared cpu_state as t_cpu_state
declare sub init_cpu()
declare function cpu_get_cppc() as string
declare sub cpu()
declare sub cpu_dump_state()
declare sub cpu_set_flag(flag as ushort)
......
......@@ -9,8 +9,9 @@
#define ERR_INVALID_OFFSET 2
'
' 51-100: scheduling
' 51-100: arithmetic
'
#define ERR_DIVZERO 51
'
' 101-150: i/o
......
......@@ -8,6 +8,7 @@
#include "cpu.bi"
#include "ilxi.bi"
#include "error.bi"
#include "bus.bi"
function inst_getbyte(op as t_operand, page as integer) as ubyte
......@@ -188,7 +189,6 @@ sub inst_add(dest as t_operand, source as t_operand)
dim result as integer
cpu_clear_flag FL_CARRY
cpu_clear_flag FL_OVERFLOW
cpu_clear_flag FL_ZERO
select case dest.data_type
......@@ -198,9 +198,8 @@ sub inst_add(dest as t_operand, source as t_operand)
result = a1 + a2
if result > &HFF then
result = &HFE
result = result and &HFF
cpu_set_flag FL_CARRY
cpu_set_flag FL_OVERFLOW
end if
inst_setbyte dest, cpu_state.dp, cubyte(result)
......@@ -210,9 +209,8 @@ sub inst_add(dest as t_operand, source as t_operand)
result = a1 + a2
if result > &HFFFF then
result = &HFFFE
result = result and &HFFFF
cpu_set_flag FL_CARRY
cpu_set_flag FL_OVERFLOW
end if
inst_setword dest, cpu_state.dp, cushort(result)
......@@ -229,6 +227,44 @@ sub inst_sub(dest as t_operand, source as t_operand)
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_CARRY
cpu_clear_flag FL_ZERO
cpu_clear_flag FL_SIGN
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = a1 - a2
if result < 0 then
result = abs(result)
cpu_set_flag FL_CARRY
cpu_set_flag FL_SIGN
end if
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = a1 - a2
if result < 0 then
result = abs(result)
cpu_set_flag FL_CARRY
cpu_set_flag FL_SIGN
end if
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_sub()
sub inst_mul(dest as t_operand, source as t_operand)
......@@ -237,6 +273,42 @@ sub inst_mul(dest as t_operand, source as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = a1 * a2
if result > &HFF then
result = result and &HFF
cpu_set_flag FL_OVERFLOW
end if
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = a1 * a2
if result > &HFFFF then
result = result and &HFFFF
cpu_set_flag FL_OVERFLOW
end if
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_mul()
sub inst_div(dest as t_operand, source as t_operand)
......@@ -244,7 +316,47 @@ sub inst_div(dest as t_operand, source as t_operand)
if dest.immediate = 1 then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
cpu_clear_flag FL_OVERFLOW
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
if a2 = 0 then machine_error ERR_DIVZERO, 10
result = a1 / a2
if result > &HFF then
result = result and &HFF
cpu_set_flag FL_OVERFLOW
end if
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
if a2 = 0 then machine_error ERR_DIVZERO, 10
result = a1 / a2
if result > &HFFFF then
result = result and &HFFFF
cpu_set_flag FL_OVERFLOW
end if
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_div()
sub inst_shl(dest as t_operand, count as t_operand)
......@@ -253,6 +365,42 @@ sub inst_shl(dest as t_operand, count as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
cpu_clear_flag FL_OVERFLOW
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(count, cpu_state.dp)
result = a1 shl a2
if result > &HFF then
result = result and &HFF
cpu_set_flag FL_OVERFLOW
end if
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(count, cpu_state.dp)
result = a1 shl a2
if result > &HFFFF then
result = result and &HFFFF
cpu_set_flag FL_OVERFLOW
end if
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_shl()
sub inst_shr(dest as t_operand, count as t_operand)
......@@ -261,6 +409,42 @@ sub inst_shr(dest as t_operand, count as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
cpu_clear_flag FL_SIGN
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(count, cpu_state.dp)
result = a1 shr a2
if result < 0 then
result = abs(result)
cpu_set_flag FL_SIGN
end if
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(count, cpu_state.dp)
result = a1 shr a2
if result < 0 then
result = abs(result)
cpu_set_flag FL_SIGN
end if
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_shr()
sub inst_or(dest as t_operand, source as t_operand)
......@@ -269,6 +453,33 @@ sub inst_or(dest as t_operand, source as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = a1 or a2
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = a1 or a2
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_or()
sub inst_not(dest as t_operand, source as t_operand)
......@@ -277,6 +488,33 @@ sub inst_not(dest as t_operand, source as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = not a2
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = not a2
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_not()
sub inst_and(dest as t_operand, source as t_operand)
......@@ -285,6 +523,33 @@ sub inst_and(dest as t_operand, source as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = a1 and a2
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = a1 and a2
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_and()
sub inst_xor(dest as t_operand, source as t_operand)
......@@ -293,6 +558,33 @@ sub inst_xor(dest as t_operand, source as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = a1 xor a2
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = a1 xor a2
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_xor()
sub inst_eqv(dest as t_operand, source as t_operand)
......@@ -301,6 +593,33 @@ sub inst_eqv(dest as t_operand, source as t_operand)
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
dim a1 as ushort
dim a2 as ushort
dim result as integer
cpu_clear_flag FL_ZERO
select case dest.data_type
case DT_BYTE
a1 = inst_getbyte(dest, cpu_state.dp)
a2 = inst_getbyte(source, cpu_state.dp)
result = a1 eqv a2
inst_setbyte dest, cpu_state.dp, cubyte(result)
case DT_WORD
a1 = inst_getword(dest, cpu_state.dp)
a2 = inst_getword(source, cpu_state.dp)
result = a1 eqv a2
inst_setword dest, cpu_state.dp, cushort(result)
end select
if result = 0 then cpu_set_flag FL_ZERO
end sub ' inst_eqv()
sub inst_cmp(dest as t_operand, source as t_operand)
......@@ -436,6 +755,44 @@ sub inst_pop(dest as t_operand)
end sub ' inst_pop()
sub inst_in(dest as t_operand, port as t_operand)
' cannot store a result in an immediate value
if dest.immediate = 1 then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
if dest.data_type <> DT_WORD then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
if port.data_type <> DT_WORD then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
inst_setword dest, cpu_state.dp, bus_input(inst_getword(port, cpu_state.dp))
end sub ' inst_in()
sub inst_out(port as t_operand, value as t_operand)
if port.data_type <> DT_WORD then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
if value.data_type <> DT_WORD then
machine_error ERR_INVALID_DATA_TYPE, 10
exit sub
end if
bus_output inst_getword(port, cpu_state.dp), inst_getword(value, cpu_state.dp)
end sub ' inst_out()
sub inst_hlt()
cpu_set_flag FL_HALT
end sub ' inst_hlt()
\ No newline at end of file
......@@ -33,4 +33,6 @@ declare sub inst_lret()
declare sub inst_iret()
declare sub inst_push(dest as t_operand)
declare sub inst_pop(dest as t_operand)
declare sub inst_in(dest as t_operand, port as t_operand)
declare sub inst_out(port as t_operand, value as t_operand)
declare sub inst_hlt()
\ No newline at end of file
'
' signal.bas
'
#include "signal.bi"
#include "cpu.bi"
sub signal_init()
signal(SIGINT, @signal_sigint)
end sub ' signal_init()
sub signal_sigint(signum as integer)
print "signal_sigint(): interrupted at "; cpu_get_cppc()
cpu_set_flag FL_HALT
end sub ' signal_sigint()
\ No newline at end of file
'
' signal.bi
'
#define SIGINT 2
#define SIG_IGN cptr(sighandler_t, 1)
type sighandler_t as sub cdecl (byval as integer)
declare function signal cdecl alias "signal" (byval signum as integer, byval handler as sighandler_t) as sighandler_t
declare sub signal_init()
declare sub signal_sigint(signum as integer)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment