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
|
|
@ -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
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/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),
|
||||
)
|
||||
_ -> panic
|
||||
let assert <<_opcode:8, reg1:4, reg2:4>> = code
|
||||
let sw = case
|
||||
bit_array.compare(
|
||||
get_register(machine, reg1),
|
||||
get_register(machine, reg2),
|
||||
)
|
||||
{
|
||||
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>> ->
|
||||
memory.set_int_at(
|
||||
machine.memory,
|
||||
memory.to_int(machine.registers.pc) + memory.to_int(offset),
|
||||
machine.registers.a,
|
||||
)
|
||||
_ -> todo
|
||||
}
|
||||
Machine(memory, machine.registers)
|
||||
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.a,
|
||||
)
|
||||
|
||||
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
|
||||
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 {
|
||||
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(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 }),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue