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