implement most of the missing functions for sic simulator

This commit is contained in:
jakob 2026-01-05 12:32:30 +01:00
parent 25c1c1eb6c
commit 24455d9eb8
6 changed files with 706 additions and 142 deletions

120
sim/log.log Normal file
View file

@ -0,0 +1,120 @@
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B
a: 000000
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000000
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B
a: 00002A
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000003
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B
a: 000045
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000006
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B000045
a: 000045
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000009
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B000045
a: 00002A
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 00000C
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B000045
a: 00000F
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 00000F
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B00004500000F
a: 00000F
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000012
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B00004500000F
a: 00002A
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000015
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B00004500000F
a: 00046E
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000018
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B00004500000F00046E
a: 00046E
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 00001B
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B00004500000F00046E
a: 00002A
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 00001E
sw: 000000
0320361B20360F203603202D1F202D0F20300320242320240F202A03201B27201B0F20242320150F202103200C1F201B0F20180F20033F2FFD00002A00001B00004500000F00046E
a: 000001
x: 000000
l: 000000
b: 000000
s: 000000
t: 000000
f: 000000
pc: 000021
sw: 000000

View file

@ -20,13 +20,34 @@ fn step(
machine
}
fn status(machine: machine.Machine) {
io.println(machine.state_string(machine))
}
pub fn main() -> Nil {
let machine = machine.init("../arith.obj")
let instructions = machine.get_instructions()
io.println(machine.state_string(machine))
status(machine)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = run_for(machine, instructions, 16)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
let machine = step(machine, instructions)
Nil
}

84
sim/src/sim/device.gleam Normal file
View file

@ -0,0 +1,84 @@
import file_streams/file_open_mode
import file_streams/file_stream
import gleam/bit_array
import gleam/io
import gleam/option
pub opaque type DeviceType {
Stdin
Stdout
Stderr
Default
}
pub type Device {
Device(
stream: option.Option(file_stream.FileStream),
dev_type: DeviceType,
buffer: BitArray,
has_data: Bool,
)
}
pub fn open(name: String) -> Device {
case name {
"0.dev" -> Device(option.None, Stdin, <<>>, False)
"1.dev" -> Device(option.None, Stdout, <<>>, False)
"2.dev" -> Device(option.None, Stderr, <<>>, False)
_ -> {
let assert Ok(str) =
file_stream.open(name, [file_open_mode.Read, file_open_mode.Write])
Device(option.Some(str), Default, <<>>, False)
}
}
}
pub fn read(device: Device) -> #(BitArray, Device) {
#(device.buffer, Device(..device, buffer: <<>>, has_data: False))
}
pub fn write(device: Device, char: BitArray) -> Device {
let _ = case device.dev_type {
Default -> {
let assert option.Some(stream) = device.stream
let assert Ok(_r) = file_stream.write_bytes(stream, char)
let assert Ok(_r) = file_stream.sync(stream)
Nil
}
Stdout -> {
let assert Ok(str) = bit_array.to_string(char)
io.print(str)
}
Stderr -> {
let assert Ok(str) = bit_array.to_string(char)
io.print_error(str)
}
_ -> Nil
}
device
}
pub fn test_device(device: Device) -> Device {
case device.dev_type {
Default -> {
let assert option.Some(stream) = device.stream
let data = file_stream.read_bytes(stream, 1)
case data {
Ok(char) -> Device(..device, buffer: char, has_data: True)
Error(_) -> Device(..device, buffer: <<>>, has_data: False)
}
}
_ -> device
}
}
pub fn close(device: Device) {
case device.dev_type {
Default -> {
let assert option.Some(stream) = device.stream
let assert Ok(_) = file_stream.close(stream)
Nil
}
_ -> Nil
}
}

View file

@ -1,17 +1,25 @@
import gleam/bit_array
import gleam/dict
import gleam/int
import gleam/list
import gleam/order
import gleam/result
import gleam/string
import sim/device
import sim/loader
import sim/memory
import sim/registers
pub type Machine {
Machine(memory: memory.Memory, registers: registers.Registers)
Machine(
memory: memory.Memory,
registers: registers.Registers,
devices: dict.Dict(Int, device.Device),
)
}
pub fn init(program: String) -> Machine {
Machine(loader.load_obj(program), registers.new())
Machine(loader.load_obj(program), registers.new(), dict.new())
}
pub fn state_string(machine: Machine) -> String {
@ -66,6 +74,92 @@ fn fetch_instruction(
}
}
fn get_operand34(machine: Machine, code: BitArray, size: Int) -> BitArray {
let assert <<_opcode:6, n:1, i:1, x:1, b:1, p:1, _e:1, offset:bits>> = code
let addr =
case b, p {
1, 0 -> memory.to_int(machine.registers.b) + memory.to_int(offset)
0, 1 -> memory.to_int(machine.registers.pc) + memory.to_int(offset)
0, 0 -> memory.to_int(offset)
_, _ -> panic
}
+ case x {
0 -> 0
_ -> memory.to_int(machine.registers.x)
}
let getter = case size {
1 -> memory.get_char_at
3 -> memory.get_int_at
6 -> memory.get_float_at
_ -> panic
}
case n, i {
0, 1 -> memory.left_pad_to_length(<<addr>>, size * 8)
1, 1 -> getter(machine.memory, addr)
1, 0 ->
getter(
machine.memory,
memory.to_int(memory.get_int_at(machine.memory, addr)),
)
_, _ -> panic
}
}
fn get_address34(machine: Machine, code: BitArray, size: Int) -> BitArray {
let assert <<_opcode:6, n:1, i:1, x:1, b:1, p:1, _e:1, offset:bits>> = code
let addr =
case b, p {
1, 0 -> memory.to_int(machine.registers.b) + memory.to_int(offset)
0, 1 -> memory.to_int(machine.registers.pc) + memory.to_int(offset)
0, 0 -> memory.to_int(offset)
_, _ -> panic
}
+ case x {
0 -> 0
_ -> memory.to_int(machine.registers.x)
}
let getter = case size {
1 -> memory.get_char_at
3 -> memory.get_int_at
6 -> memory.get_float_at
_ -> panic
}
case n, i {
0, 1 -> panic
1, 1 -> <<addr:24>>
1, 0 -> getter(machine.memory, addr)
_, _ -> panic
}
}
fn get_register(machine: Machine, code: Int) -> BitArray {
case code {
0 -> machine.registers.a
1 -> machine.registers.x
2 -> machine.registers.l
3 -> machine.registers.b
4 -> machine.registers.s
5 -> machine.registers.t
_ -> panic
}
}
fn set_register(
machine: Machine,
code: Int,
value: BitArray,
) -> registers.Registers {
case code {
0 -> registers.Registers(..machine.registers, a: value)
1 -> registers.Registers(..machine.registers, x: value)
2 -> registers.Registers(..machine.registers, l: value)
3 -> registers.Registers(..machine.registers, b: value)
4 -> registers.Registers(..machine.registers, s: value)
5 -> registers.Registers(..machine.registers, t: value)
_ -> panic
}
}
pub fn step(machine: Machine, instructions: List(Def)) -> Machine {
let assert <<pc:24>> = machine.registers.pc
@ -124,252 +218,454 @@ pub fn get_def(instructions: List(Def), first_byte: BitArray) -> Def {
pub fn get_instructions() -> List(Def) {
[
Def(6, 3, "ADD", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let operand = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
memory.get_int_at(
machine.memory,
memory.to_int(machine.registers.pc) + memory.to_int(offset),
)
_ -> panic
}
let operand = get_operand34(machine, code, 3)
Machine(
machine.memory,
registers.Registers(..machine.registers, a: <<
..machine,
registers: registers.Registers(..machine.registers, a: <<
{ memory.to_int(machine.registers.a) + memory.to_int(operand) }:24,
>>),
)
}),
Def(22, 3, "ADDF", fn(machine: Machine, code: BitArray) -> Machine {
Def(22, 3, "ADDF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(36, 2, "ADDR", fn(machine: Machine, code: BitArray) -> Machine {
machine
let assert <<_opcode:8, reg1:4, reg2:4>> = code
let assert <<operand1:24>> = get_register(machine, reg1)
let assert <<operand2:24>> = get_register(machine, reg2)
let value = operand2 + operand1
Machine(..machine, registers: set_register(machine, reg2, <<value:24>>))
}),
Def(16, 3, "AND", fn(machine: Machine, code: BitArray) -> Machine {
Def(16, 3, "AND", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(45, 2, "CLEAR", fn(machine: Machine, code: BitArray) -> Machine {
machine
let assert <<_opcode:8, reg1:4, _reg2:4>> = code
Machine(..machine, registers: set_register(machine, reg1, <<0:24>>))
}),
Def(10, 3, "COMP", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_operand34(machine, code, 3)
let sw = case bit_array.compare(machine.registers.a, operand) {
order.Lt -> <<0x80:24>>
order.Eq -> <<0:24>>
order.Gt -> <<0x40:24>>
}
Machine(
..machine,
registers: registers.Registers(..machine.registers, sw: sw),
)
}),
Def(34, 3, "COMPF", fn(machine: Machine, code: BitArray) -> Machine {
Def(34, 3, "COMPF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(40, 2, "COMPR", fn(machine: Machine, code: BitArray) -> Machine {
machine
}),
Def(9, 3, "DIV", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let operand = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
memory.get_int_at(
machine.memory,
memory.to_int(machine.registers.pc) + memory.to_int(offset),
let assert <<_opcode:8, reg1:4, reg2:4>> = code
let sw = case
bit_array.compare(
get_register(machine, reg1),
get_register(machine, reg2),
)
_ -> panic
{
order.Lt -> <<0x80:24>>
order.Eq -> <<0:24>>
order.Gt -> <<0x40:24>>
}
Machine(
machine.memory,
registers.Registers(..machine.registers, a: <<
..machine,
registers: registers.Registers(..machine.registers, sw: sw),
)
}),
Def(9, 3, "DIV", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, a: <<
{ memory.to_int(machine.registers.a) / memory.to_int(operand) }:24,
>>),
)
}),
Def(25, 3, "DIVF", fn(machine: Machine, code: BitArray) -> Machine {
Def(25, 3, "DIVF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(39, 2, "DIVR", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_opcode:8, reg1:4, reg2:4>> = code
let assert <<operand1:24>> = get_register(machine, reg1)
let assert <<operand2:24>> = get_register(machine, reg2)
let value = operand2 / operand1
Machine(..machine, registers: set_register(machine, reg2, <<value:24>>))
}),
Def(49, 1, "FIX", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(49, 1, "FIX", fn(machine: Machine, code: BitArray) -> Machine {
Def(48, 1, "FLOAT", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(48, 1, "FLOAT", fn(machine: Machine, code: BitArray) -> Machine {
machine
}),
Def(61, 1, "HIO", fn(machine: Machine, code: BitArray) -> Machine {
Def(61, 1, "HIO", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(15, 3, "J", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let addr = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
memory.to_int(machine.registers.pc) + memory.to_int(offset)
_ -> todo
}
let addr = get_address34(machine, code, 3)
Machine(
machine.memory,
registers.Registers(..machine.registers, pc: <<addr:24>>),
..machine,
registers: registers.Registers(..machine.registers, pc: addr),
)
}),
Def(12, 3, "JEQ", fn(machine: Machine, code: BitArray) -> Machine {
machine
let addr = get_address34(machine, code, 3)
case machine.registers.sw {
<<0:24>> ->
Machine(
..machine,
registers: registers.Registers(..machine.registers, pc: addr),
)
_ -> machine
}
}),
Def(13, 3, "JGT", fn(machine: Machine, code: BitArray) -> Machine {
machine
let addr = get_address34(machine, code, 3)
case machine.registers.sw {
<<0x40:24>> ->
Machine(
..machine,
registers: registers.Registers(..machine.registers, pc: addr),
)
_ -> machine
}
}),
Def(14, 3, "JLT", fn(machine: Machine, code: BitArray) -> Machine {
machine
let addr = get_address34(machine, code, 3)
case machine.registers.sw {
<<0x80:24>> ->
Machine(
..machine,
registers: registers.Registers(..machine.registers, pc: addr),
)
_ -> machine
}
}),
Def(18, 3, "JSUB", fn(machine: Machine, code: BitArray) -> Machine {
machine
let addr = get_address34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(
..machine.registers,
l: machine.registers.pc,
pc: addr,
),
)
}),
Def(0, 3, "LDA", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let operand = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
memory.get_int_at(
machine.memory,
memory.to_int(machine.registers.pc) + memory.to_int(offset),
)
_ -> todo
}
let operand = get_operand34(machine, code, 3)
Machine(
machine.memory,
registers.Registers(..machine.registers, a: operand),
..machine,
registers: registers.Registers(..machine.registers, a: operand),
)
}),
Def(26, 3, "LDB", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, b: operand),
)
}),
Def(20, 3, "LDCH", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, a: <<
0:16,
operand:bits,
>>),
)
}),
Def(28, 3, "LDF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(28, 3, "LDF", fn(machine: Machine, code: BitArray) -> Machine {
machine
Def(2, 3, "LDL", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, l: operand),
)
}),
Def(2, 3, "LDL", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(27, 3, "LDS", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, s: operand),
)
}),
Def(29, 3, "LDT", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, t: operand),
)
}),
Def(1, 3, "LDX", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(52, 3, "LPS", fn(machine: Machine, code: BitArray) -> Machine {
Def(1, 3, "LDX", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, x: operand),
)
}),
Def(52, 3, "LPS", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(8, 3, "MUL", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let operand = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
memory.get_int_at(
machine.memory,
memory.to_int(machine.registers.pc) + memory.to_int(offset),
)
_ -> panic
}
let operand = get_operand34(machine, code, 3)
Machine(
machine.memory,
registers.Registers(..machine.registers, a: <<
..machine,
registers: registers.Registers(..machine.registers, a: <<
{ memory.to_int(machine.registers.a) * memory.to_int(operand) }:24,
>>),
)
}),
Def(24, 3, "MULF", fn(machine: Machine, code: BitArray) -> Machine {
Def(24, 3, "MULF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(38, 2, "MULR", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_opcode:8, reg1:4, reg2:4>> = code
let assert <<operand1:24>> = get_register(machine, reg1)
let assert <<operand2:24>> = get_register(machine, reg2)
let value = operand2 * operand1
Machine(..machine, registers: set_register(machine, reg2, <<value:24>>))
}),
Def(50, 1, "NORM", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(50, 1, "NORM", fn(machine: Machine, code: BitArray) -> Machine {
Def(17, 3, "OR", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(17, 3, "OR", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(54, 3, "RD", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(43, 2, "RMO", fn(machine: Machine, code: BitArray) -> Machine {
Def(54, 3, "RD", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<devnr:8>> = get_operand34(machine, code, 1)
let #(char, dev) = case dict.get(machine.devices, devnr) {
Ok(d) -> device.read(d)
Error(Nil) -> {
let d = device.open(int.to_base16(devnr) <> ".dev")
device.read(d)
}
}
Machine(
..machine,
registers: registers.Registers(..machine.registers, a: <<
0:16,
char:bits,
>>),
devices: dict.insert(machine.devices, devnr, dev),
)
}),
Def(43, 2, "RMO", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(19, 3, "RSUB", fn(machine: Machine, code: BitArray) -> Machine {
Def(19, 3, "RSUB", fn(machine: Machine, _code: BitArray) -> Machine {
Machine(
..machine,
registers: registers.Registers(
..machine.registers,
pc: machine.registers.l,
),
)
}),
Def(41, 2, "SHIFTL", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(41, 2, "SHIFTL", fn(machine: Machine, code: BitArray) -> Machine {
Def(42, 2, "SHIFTR", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(42, 2, "SHIFTR", fn(machine: Machine, code: BitArray) -> Machine {
Def(60, 1, "SIO", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(60, 1, "SIO", fn(machine: Machine, code: BitArray) -> Machine {
machine
}),
Def(59, 3, "SSK", fn(machine: Machine, code: BitArray) -> Machine {
Def(59, 3, "SSK", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(3, 3, "STA", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let memory = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
memory.to_int(machine.registers.pc) + memory.to_int(offset),
memory.to_int(operand),
machine.registers.a,
)
_ -> todo
}
Machine(memory, machine.registers)
Machine(..machine, memory: memory)
}),
Def(30, 3, "STB", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
memory.to_int(operand),
machine.registers.b,
)
Machine(..machine, memory: memory)
}),
Def(21, 3, "STCH", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_char_at(
machine.memory,
memory.to_int(operand),
machine.registers.a,
)
Machine(..machine, memory: memory)
}),
Def(32, 3, "STF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(32, 3, "STF", fn(machine: Machine, code: BitArray) -> Machine {
Def(53, 3, "STI", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(53, 3, "STI", fn(machine: Machine, code: BitArray) -> Machine {
machine
Def(5, 3, "STL", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
memory.to_int(operand),
machine.registers.l,
)
Machine(..machine, memory: memory)
}),
Def(5, 3, "STL", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(31, 3, "STS", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
memory.to_int(operand),
machine.registers.s,
)
Machine(..machine, memory: memory)
}),
Def(58, 3, "STSW", fn(machine: Machine, code: BitArray) -> Machine {
machine
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
memory.to_int(operand),
machine.registers.sw,
)
Machine(..machine, memory: memory)
}),
Def(33, 3, "STT", fn(machine: Machine, code: BitArray) -> Machine {
machine
}),
Def(4, 3, "STX", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(7, 3, "SUB", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_:12, offset:bits>> = code
let operand = case code {
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
memory.get_int_at(
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
memory.to_int(machine.registers.pc) + memory.to_int(offset),
memory.to_int(operand),
machine.registers.t,
)
_ -> panic
}
Machine(
Machine(..machine, memory: memory)
}),
Def(4, 3, "STX", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_address34(machine, code, 3)
echo bit_array.base16_encode(operand)
let memory =
memory.set_int_at(
machine.memory,
registers.Registers(..machine.registers, a: <<
memory.to_int(operand),
machine.registers.x,
)
Machine(..machine, memory: memory)
}),
Def(7, 3, "SUB", fn(machine: Machine, code: BitArray) -> Machine {
let operand = get_operand34(machine, code, 3)
Machine(
..machine,
registers: registers.Registers(..machine.registers, a: <<
{ memory.to_int(machine.registers.a) - memory.to_int(operand) }:24,
>>),
)
}),
Def(23, 3, "SUBF", fn(machine: Machine, code: BitArray) -> Machine {
Def(23, 3, "SUBF", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(23, 2, "SUBR", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<_opcode:8, reg1:4, reg2:4>> = code
let assert <<operand1:24>> = get_register(machine, reg1)
let assert <<operand2:24>> = get_register(machine, reg2)
let value = operand2 - operand1
Machine(..machine, registers: set_register(machine, reg2, <<value:24>>))
}),
Def(23, 2, "SVC", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(23, 2, "SVC", fn(machine: Machine, code: BitArray) -> Machine {
machine
Def(23, 3, "TD", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<devnr:8>> = get_operand34(machine, code, 1)
let #(dev, machine) = case dict.get(machine.devices, devnr) {
Ok(d) -> #(d, machine)
Error(Nil) -> {
let d = device.open(int.to_base16(devnr) <> ".dev")
#(
d,
Machine(..machine, devices: dict.insert(machine.devices, devnr, d)),
)
}
}
let dev = device.test_device(dev)
Machine(
..machine,
devices: dict.insert(machine.devices, devnr, dev),
registers: registers.Registers(..machine.registers, sw: <<0x40:24>>),
)
}),
Def(23, 3, "TD", fn(machine: Machine, code: BitArray) -> Machine { machine }),
Def(23, 1, "TIO", fn(machine: Machine, code: BitArray) -> Machine {
Def(23, 1, "TIO", fn(machine: Machine, _code: BitArray) -> Machine {
machine
}),
Def(23, 3, "TIX", fn(machine: Machine, code: BitArray) -> Machine {
machine
let assert <<x:24>> = machine.registers.x
let x = x + 1
let operand = get_operand34(machine, code, 3)
let sw = case bit_array.compare(machine.registers.x, operand) {
order.Lt -> <<0x80:24>>
order.Eq -> <<0:24>>
order.Gt -> <<0x40:24>>
}
Machine(
..machine,
registers: registers.Registers(..machine.registers, sw: sw, x: <<x:24>>),
)
}),
Def(23, 2, "TIXR", fn(machine: Machine, code: BitArray) -> Machine {
machine
let assert <<x:24>> = machine.registers.x
let x = x + 1
let assert <<_opcode:8, reg1:4, _reg2:4>> = code
let sw = case
bit_array.compare(machine.registers.x, get_register(machine, reg1))
{
order.Lt -> <<0x80:24>>
order.Eq -> <<0:24>>
order.Gt -> <<0x40:24>>
}
Machine(
..machine,
registers: registers.Registers(..machine.registers, sw: sw, x: <<x:24>>),
)
}),
Def(23, 3, "WD", fn(machine: Machine, code: BitArray) -> Machine {
let assert <<devnr:8>> = get_operand34(machine, code, 1)
let assert <<_:16, char:bits>> = machine.registers.a
let dev = case dict.get(machine.devices, devnr) {
Ok(d) -> device.write(d, char)
Error(Nil) -> {
let d = device.open(int.to_base16(devnr) <> ".dev")
device.write(d, char)
}
}
Machine(..machine, devices: dict.insert(machine.devices, devnr, dev))
}),
Def(23, 3, "WD", fn(machine: Machine, code: BitArray) -> Machine { machine }),
]
}

View file

@ -3,7 +3,7 @@ import gleam/bit_array
pub type Memory =
BitArray
fn pad_to_length(memory: Memory, lenght: Int) -> Memory {
pub fn pad_to_length(memory: Memory, lenght: Int) -> Memory {
case bit_array.bit_size(memory) < lenght {
True -> {
pad_to_length(<<memory:bits, 0:1>>, lenght)
@ -12,20 +12,29 @@ fn pad_to_length(memory: Memory, lenght: Int) -> Memory {
}
}
pub fn insert_at(memory: Memory, pos: Int, value: BitArray) -> Memory {
let memory = case pos >= bit_array.bit_size(memory) {
pub fn left_pad_to_length(memory: Memory, lenght: Int) -> Memory {
case bit_array.bit_size(memory) < lenght {
True -> {
pad_to_length(memory, pos)
pad_to_length(<<0:1, memory:bits>>, lenght)
}
_ -> memory
}
}
pub fn insert_at(memory: Memory, pos: Int, value: BitArray) -> Memory {
let memory = case pos > bit_array.byte_size(memory) {
True -> {
pad_to_length(memory, pos * 8)
}
False -> memory
}
let length = bit_array.bit_size(value)
let length = bit_array.byte_size(value)
let assert Ok(head) = bit_array.slice(memory, 0, pos)
case
bit_array.slice(
memory,
pos + length,
bit_array.bit_size(memory) - pos - length,
bit_array.byte_size(memory) - pos - length,
)
{
Ok(tail) -> <<head:bits, value:bits, tail:bits>>
@ -52,7 +61,7 @@ pub fn set_int_at(memory: Memory, pos: Int, value: BitArray) -> Memory {
}
pub fn get_float_at(memory: Memory, pos: Int) -> BitArray {
let assert Ok(value) = bit_array.slice(memory, pos, 5)
let assert Ok(value) = bit_array.slice(memory, pos, 6)
value
}

View file

@ -1,4 +1,6 @@
import gleeunit
import sim/device
import sim/memory
pub fn main() -> Nil {
gleeunit.main()
@ -11,3 +13,35 @@ pub fn hello_world_test() {
assert greeting == "Hello, Joe!"
}
pub fn pad_test() {
assert <<1, 2, 3, 0>> == memory.pad_to_length(<<1, 2, 3>>, 32)
}
pub fn insert_test() {
assert <<1, 2, 3, 4>> == memory.insert_at(<<1, 2, 3>>, 3, <<4>>)
assert <<1, 2, 3, 0, 5>> == memory.insert_at(<<1, 2, 3>>, 4, <<5>>)
assert <<1, 67, 3>> == memory.insert_at(<<1, 2, 3>>, 1, <<67>>)
}
pub fn open_test() {
let d0 = device.open("0")
device.close(d0)
}
pub fn test_device_test() {
let d1 = device.open("1")
assert <<>> == device.read(d1).0
let d1 = device.test_device(d1)
assert d1.has_data == True
let #(char, d1) = device.read(d1)
assert <<"a">> == char
assert d1.has_data == False
assert <<>> == device.read(d1).0
device.close(d1)
let d0 = device.open("0")
let d0 = device.test_device(d0)
assert d0.has_data == False
device.close(d0)
}