SPO_JakaFurlan/ass2/SICocaml/izvajalnik.ml
2025-11-26 16:42:36 +01:00

124 lines
No EOL
3.9 KiB
OCaml

type registers = {
mutable a : int;
mutable x : int;
mutable l : int;
mutable b : int;
mutable s : int;
mutable t : int;
mutable f : int;
mutable pc : int;
mutable sw : int
}
(*tip state predstavlja stanje SIC/XE, z pomnilnikom in registri*)
type state = {
regs : registers;
memory : Bytes.t
}
type nixbpe = {
n : int;
i : int;
x : int;
b : int;
p : int;
e : int
}
(*kreiramo začetno stanje*)
let regs = {a = 0; x = 0; l = 0; b = 0; s = 0; t = 0; f = 0; pc = 0; sw = 0}
let memSize = 1 lsl 20 (*2^20*)
let memory = Bytes.make memSize '\x00' (*mutbale kos pomnilnika velikosti memSize*)
let state = {regs; memory}
(*----Funkcije izvajalnika----*)
(*TODO - brali bomo vedno relativno od začetka instrukcije, PC bomo na koncu ukaza povečali za pravo velikost!*)
(*funkcije za javljanje napak*)
let notImplemented (mnemonic : string) = Printf.printf "mnemonic %s is not implemented!\n" mnemonic
let invalidOpcode (opcode : int) = Printf.printf "opcode %d is invalid!\n" opcode
let invalidAdressing () = Printf.printf "invalid adressing!\n"
(*beri in povisaj PC*)
let fetch (state : state) : char =
let byte = Bytes.get state.memory state.regs.pc in
state.regs.pc <- state.regs.pc + 1;
byte
(*beri za offset in ne povecaj PC*)
let readMem (state : state) (offset : int) : char =
Bytes.get state.memory (state.regs.pc + offset)
(*beri drugi byte ukaza formata 2 in vrni r1 in r2, kot int njunih vrednosti (reg a -> 1, reg x -> 2 ...)*)
let readFormat2Byte2 (state : state) : (int * int) =
let byte2 = Char.code (readMem state 1) in
let highNibble = (byte2 land 0xF0) lsr 4 in (*pridobi prvi nibble*)
let lowNibble = byte2 land 0x0F in (*pridobi drugi nibble*)
(highNibble, lowNibble)
(*preberi byta 1 in 2 in dobi nixbpe bite*)
let getNIXBPE (state : state) : nixbpe =
let byte1 = Char.code (readMem state 0) in
let byte2 = Char.code (readMem state 1) in
{n = (byte1 lsr 1) land 1;
i = byte1 land 1;
x = (byte2 lsr 7) land 1;
b = (byte2 lsr 6) land 1;
p = (byte2 lsr 5) land 1;
e = (byte2 lsr 4) land 1;}
(*execute format 1*)
let executeFormat1 (state : state) (mnemonic : OpcodeTable.mnemonic) : unit =
match mnemonic with
| FIX -> notImplemented "FIX"
| FLOAT -> notImplemented "FLOAT"
| HIO -> notImplemented "HIO"
| NORM -> notImplemented "NORM"
| SIO -> notImplemented "SIO"
| TIO -> notImplemented "TIO"
| _ -> Printf.printf "Mnemonic %s falsely flaged as format 1" (OpcodeTable.string_of_mnemonic mnemonic)
(*execute format 2*)
let executeFormat2 (state: state) (mnemonic : OpcodeTable.mnemonic) : unit =
let (r1, r2) = readFormat2Byte2 state in
match mnemonic with
| ADDR -> notImplemented "ADD" (*when implemented: -> add state r1 r2*)
| CLEAR -> notImplemented "CLEAR"
| COMPR -> notImplemented "F2"
| DIVR -> notImplemented "F2"
| MULR -> notImplemented "F2"
| RMO -> notImplemented "F2"
| SHIFTL -> notImplemented "F2"
| SHIFTR -> notImplemented "F2"
| SUBR -> notImplemented "F2"
| SVC -> notImplemented "F2"
| TIXR -> notImplemented "F2"
|_ -> Printf.printf "Mnemonic %s falsely flaged as format 1" (OpcodeTable.string_of_mnemonic mnemonic)
let executeFormat3 (state : state) (nixbpe : nixbpe) : unit
(*execute format 3*)
let executeFormat3_4 (state : state) (mnemonic : OpcodeTable.mnemonic) : unit =
let nixbpe = getNIXBPE state in
match nixbpe.e with
| 0 -> executeFormat3 state
| 1 -> executeFormat4 state
| _ -> failwith "invalid computation of nxbpe"
(*execute ukaza*)
let execute (state : state) : unit =
let byte1 = readMem state 0 in (*read the 1st byte of the instruction*)
try
let {OpcodeTable.mnemonic; OpcodeTable.format} = Decoder.decoder byte1 in (*determen the format of the instruction from the 1st byte*)
match format with
| F1 -> executeFormat1 state mnemonic
| F2 -> executeFormat2 state mnemonic
| F3_4 -> executeFormat3_4 state mnemonic
with
| Failure msg -> byte1 |> Char.code |> invalidOpcode