implement most of the missing functions for sic simulator
This commit is contained in:
parent
25c1c1eb6c
commit
24455d9eb8
6 changed files with 706 additions and 142 deletions
120
sim/log.log
Normal file
120
sim/log.log
Normal 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
|
||||||
|
|
@ -20,13 +20,34 @@ fn step(
|
||||||
machine
|
machine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn status(machine: machine.Machine) {
|
||||||
|
io.println(machine.state_string(machine))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main() -> Nil {
|
pub fn main() -> Nil {
|
||||||
let machine = machine.init("../arith.obj")
|
let machine = machine.init("../arith.obj")
|
||||||
let instructions = machine.get_instructions()
|
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 = run_for(machine, instructions, 16)
|
||||||
let machine = step(machine, instructions)
|
|
||||||
let machine = step(machine, instructions)
|
|
||||||
let machine = step(machine, instructions)
|
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
84
sim/src/sim/device.gleam
Normal file
84
sim/src/sim/device.gleam
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,17 +1,25 @@
|
||||||
import gleam/bit_array
|
import gleam/bit_array
|
||||||
|
import gleam/dict
|
||||||
|
import gleam/int
|
||||||
import gleam/list
|
import gleam/list
|
||||||
|
import gleam/order
|
||||||
import gleam/result
|
import gleam/result
|
||||||
import gleam/string
|
import gleam/string
|
||||||
|
import sim/device
|
||||||
import sim/loader
|
import sim/loader
|
||||||
import sim/memory
|
import sim/memory
|
||||||
import sim/registers
|
import sim/registers
|
||||||
|
|
||||||
pub type Machine {
|
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 {
|
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 {
|
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 {
|
pub fn step(machine: Machine, instructions: List(Def)) -> Machine {
|
||||||
let assert <<pc:24>> = machine.registers.pc
|
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) {
|
pub fn get_instructions() -> List(Def) {
|
||||||
[
|
[
|
||||||
Def(6, 3, "ADD", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(6, 3, "ADD", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
let assert <<_:12, offset:bits>> = code
|
let operand = get_operand34(machine, code, 3)
|
||||||
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
|
|
||||||
}
|
|
||||||
Machine(
|
Machine(
|
||||||
machine.memory,
|
..machine,
|
||||||
registers.Registers(..machine.registers, a: <<
|
registers: registers.Registers(..machine.registers, a: <<
|
||||||
{ memory.to_int(machine.registers.a) + memory.to_int(operand) }:24,
|
{ 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(36, 2, "ADDR", fn(machine: Machine, code: BitArray) -> 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(45, 2, "CLEAR", fn(machine: Machine, code: BitArray) -> 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 {
|
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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(40, 2, "COMPR", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(40, 2, "COMPR", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
machine
|
let assert <<_opcode:8, reg1:4, reg2:4>> = code
|
||||||
}),
|
let sw = case
|
||||||
Def(9, 3, "DIV", fn(machine: Machine, code: BitArray) -> Machine {
|
bit_array.compare(
|
||||||
let assert <<_:12, offset:bits>> = code
|
get_register(machine, reg1),
|
||||||
let operand = case code {
|
get_register(machine, reg2),
|
||||||
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
|
)
|
||||||
memory.get_int_at(
|
{
|
||||||
machine.memory,
|
order.Lt -> <<0x80:24>>
|
||||||
memory.to_int(machine.registers.pc) + memory.to_int(offset),
|
order.Eq -> <<0:24>>
|
||||||
)
|
order.Gt -> <<0x40:24>>
|
||||||
_ -> panic
|
|
||||||
}
|
}
|
||||||
Machine(
|
Machine(
|
||||||
machine.memory,
|
..machine,
|
||||||
registers.Registers(..machine.registers, a: <<
|
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,
|
{ 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(39, 2, "DIVR", fn(machine: Machine, code: BitArray) -> 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(49, 1, "FIX", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(48, 1, "FLOAT", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(48, 1, "FLOAT", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(61, 1, "HIO", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
|
||||||
}),
|
|
||||||
Def(61, 1, "HIO", fn(machine: Machine, code: BitArray) -> Machine {
|
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(15, 3, "J", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(15, 3, "J", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
let assert <<_:12, offset:bits>> = code
|
let addr = get_address34(machine, code, 3)
|
||||||
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
|
|
||||||
}
|
|
||||||
Machine(
|
Machine(
|
||||||
machine.memory,
|
..machine,
|
||||||
registers.Registers(..machine.registers, pc: <<addr:24>>),
|
registers: registers.Registers(..machine.registers, pc: addr),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
Def(12, 3, "JEQ", fn(machine: Machine, code: BitArray) -> Machine {
|
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 {
|
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 {
|
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 {
|
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 {
|
Def(0, 3, "LDA", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
let assert <<_:12, offset:bits>> = code
|
let operand = get_operand34(machine, code, 3)
|
||||||
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
|
|
||||||
}
|
|
||||||
Machine(
|
Machine(
|
||||||
machine.memory,
|
..machine,
|
||||||
registers.Registers(..machine.registers, a: operand),
|
registers: registers.Registers(..machine.registers, a: operand),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
Def(26, 3, "LDB", fn(machine: Machine, code: BitArray) -> Machine {
|
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 {
|
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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(28, 3, "LDF", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(2, 3, "LDL", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
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 {
|
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 {
|
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(1, 3, "LDX", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
Def(52, 3, "LPS", 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(8, 3, "MUL", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(8, 3, "MUL", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
let assert <<_:12, offset:bits>> = code
|
let operand = get_operand34(machine, code, 3)
|
||||||
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
|
|
||||||
}
|
|
||||||
Machine(
|
Machine(
|
||||||
machine.memory,
|
..machine,
|
||||||
registers.Registers(..machine.registers, a: <<
|
registers: registers.Registers(..machine.registers, a: <<
|
||||||
{ memory.to_int(machine.registers.a) * memory.to_int(operand) }:24,
|
{ 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(38, 2, "MULR", fn(machine: Machine, code: BitArray) -> 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(50, 1, "NORM", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(17, 3, "OR", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(17, 3, "OR", fn(machine: Machine, code: BitArray) -> Machine { machine }),
|
Def(54, 3, "RD", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
Def(54, 3, "RD", fn(machine: Machine, code: BitArray) -> Machine { machine }),
|
let assert <<devnr:8>> = get_operand34(machine, code, 1)
|
||||||
Def(43, 2, "RMO", fn(machine: Machine, code: BitArray) -> Machine {
|
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
|
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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(41, 2, "SHIFTL", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(42, 2, "SHIFTR", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(42, 2, "SHIFTR", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(60, 1, "SIO", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(60, 1, "SIO", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(59, 3, "SSK", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
|
||||||
}),
|
|
||||||
Def(59, 3, "SSK", fn(machine: Machine, code: BitArray) -> Machine {
|
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(3, 3, "STA", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(3, 3, "STA", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
let assert <<_:12, offset:bits>> = code
|
let operand = get_address34(machine, code, 3)
|
||||||
let memory = case code {
|
echo bit_array.base16_encode(operand)
|
||||||
<<_:6, 1:1, 1:1, 0:1, 0:1, 1:1, 0:1, _:bits>> ->
|
let memory =
|
||||||
memory.set_int_at(
|
memory.set_int_at(
|
||||||
machine.memory,
|
machine.memory,
|
||||||
memory.to_int(machine.registers.pc) + memory.to_int(offset),
|
memory.to_int(operand),
|
||||||
machine.registers.a,
|
machine.registers.a,
|
||||||
)
|
)
|
||||||
_ -> todo
|
|
||||||
}
|
Machine(..machine, memory: memory)
|
||||||
Machine(memory, machine.registers)
|
|
||||||
}),
|
}),
|
||||||
Def(30, 3, "STB", fn(machine: Machine, code: BitArray) -> Machine {
|
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 {
|
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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(32, 3, "STF", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(53, 3, "STI", fn(machine: Machine, _code: BitArray) -> Machine {
|
||||||
machine
|
machine
|
||||||
}),
|
}),
|
||||||
Def(53, 3, "STI", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(5, 3, "STL", 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.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 {
|
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 {
|
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 {
|
Def(33, 3, "STT", 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.t,
|
||||||
|
)
|
||||||
|
|
||||||
|
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,
|
||||||
|
memory.to_int(operand),
|
||||||
|
machine.registers.x,
|
||||||
|
)
|
||||||
|
|
||||||
|
Machine(..machine, memory: memory)
|
||||||
}),
|
}),
|
||||||
Def(4, 3, "STX", fn(machine: Machine, code: BitArray) -> Machine { machine }),
|
|
||||||
Def(7, 3, "SUB", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(7, 3, "SUB", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
let assert <<_:12, offset:bits>> = code
|
let operand = get_operand34(machine, code, 3)
|
||||||
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
|
|
||||||
}
|
|
||||||
Machine(
|
Machine(
|
||||||
machine.memory,
|
..machine,
|
||||||
registers.Registers(..machine.registers, a: <<
|
registers: registers.Registers(..machine.registers, a: <<
|
||||||
{ memory.to_int(machine.registers.a) - memory.to_int(operand) }:24,
|
{ 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(23, 2, "SUBR", fn(machine: Machine, code: BitArray) -> 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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(23, 2, "SVC", fn(machine: Machine, code: BitArray) -> Machine {
|
Def(23, 3, "TD", fn(machine: Machine, code: BitArray) -> Machine {
|
||||||
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
|
machine
|
||||||
}),
|
}),
|
||||||
Def(23, 3, "TIX", fn(machine: Machine, code: BitArray) -> 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 {
|
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 }),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import gleam/bit_array
|
||||||
pub type Memory =
|
pub type Memory =
|
||||||
BitArray
|
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 {
|
case bit_array.bit_size(memory) < lenght {
|
||||||
True -> {
|
True -> {
|
||||||
pad_to_length(<<memory:bits, 0:1>>, lenght)
|
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 {
|
pub fn left_pad_to_length(memory: Memory, lenght: Int) -> Memory {
|
||||||
let memory = case pos >= bit_array.bit_size(memory) {
|
case bit_array.bit_size(memory) < lenght {
|
||||||
True -> {
|
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
|
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)
|
let assert Ok(head) = bit_array.slice(memory, 0, pos)
|
||||||
case
|
case
|
||||||
bit_array.slice(
|
bit_array.slice(
|
||||||
memory,
|
memory,
|
||||||
pos + length,
|
pos + length,
|
||||||
bit_array.bit_size(memory) - pos - length,
|
bit_array.byte_size(memory) - pos - length,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Ok(tail) -> <<head:bits, value:bits, tail:bits>>
|
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 {
|
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
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import gleeunit
|
import gleeunit
|
||||||
|
import sim/device
|
||||||
|
import sim/memory
|
||||||
|
|
||||||
pub fn main() -> Nil {
|
pub fn main() -> Nil {
|
||||||
gleeunit.main()
|
gleeunit.main()
|
||||||
|
|
@ -11,3 +13,35 @@ pub fn hello_world_test() {
|
||||||
|
|
||||||
assert greeting == "Hello, Joe!"
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue