228 lines
No EOL
7 KiB
OCaml
228 lines
No EOL
7 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 readR1R2 (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;}
|
|
|
|
|
|
let getAddress (state : state) : int =
|
|
42
|
|
|
|
|
|
(*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"
|
|
|_ -> failwith ("Mnemonic" ^ (OpcodeTable.string_of_mnemonic mnemonic) ^ "falsely flaged as format 1")
|
|
|
|
|
|
|
|
(*execute format 2*)
|
|
let executeFormat2 (state: state) (mnemonic : OpcodeTable.mnemonic) : unit =
|
|
let (r1, r2) = readR1R2 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"
|
|
|_ -> failwith ("Mnemonic" ^ (OpcodeTable.string_of_mnemonic mnemonic) ^ "falsely flaged as format 2")
|
|
|
|
|
|
(*execute Format 3*)
|
|
let executeFormat3 (state : state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit =
|
|
let address = getAddress state in
|
|
match mnemonic with
|
|
| ADD -> notImplemented "ADD3"
|
|
| ADDF -> notImplemented "ADDF4"
|
|
| AND -> notImplemented "AND4"
|
|
| COMP -> notImplemented "COMP4"
|
|
| COMPF -> notImplemented "COMPF4"
|
|
| DIV -> notImplemented "DIV4"
|
|
| MUL -> notImplemented "MUL4"
|
|
| OR -> notImplemented "OR4"
|
|
| SUB -> notImplemented "SUB4"
|
|
| SUBF -> notImplemented "SUBF4"
|
|
| TD -> notImplemented "TD4"
|
|
| WD -> notImplemented "WD4"
|
|
|
|
(* Jump / subroutine *)
|
|
| J -> notImplemented "J4"
|
|
| JEQ -> notImplemented "JEQ4"
|
|
| JGT -> notImplemented "JGT4"
|
|
| JLT -> notImplemented "JLT4"
|
|
| JSUB -> notImplemented "JSUB4"
|
|
| RSUB -> notImplemented "RSUB4"
|
|
|
|
(* Load/store *)
|
|
| LDA -> notImplemented "LDA4"
|
|
| LDB -> notImplemented "LDB4"
|
|
| LDCH -> notImplemented "LDCH4"
|
|
| LDF -> notImplemented "LDF4"
|
|
| LDL -> notImplemented "LDL4"
|
|
| LDS -> notImplemented "LDS4"
|
|
| LDT -> notImplemented "LDT4"
|
|
| LDX -> notImplemented "LDX4"
|
|
| LPS -> notImplemented "LPS4"
|
|
| STA -> notImplemented "STA4"
|
|
| STB -> notImplemented "STB4"
|
|
| STCH -> notImplemented "STCH4"
|
|
| STF -> notImplemented "STF4"
|
|
| STL -> notImplemented "STL4"
|
|
| STS -> notImplemented "STS4"
|
|
| STSW -> notImplemented "STSW4"
|
|
| STT -> notImplemented "STT4"
|
|
| STX -> notImplemented "STX4"
|
|
|
|
(* Control / IO *)
|
|
| TIX -> notImplemented "TIX4"
|
|
|_ -> failwith ("Mnemonic" ^ (OpcodeTable.string_of_mnemonic mnemonic) ^ "falsely flaged as format 3")
|
|
|
|
|
|
let executeFormat4 (state : state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit =
|
|
let address = getAddress state in
|
|
match mnemonic with
|
|
(*aritmetika*)
|
|
| ADD -> notImplemented "ADD4"
|
|
| ADDF -> notImplemented "ADDF4"
|
|
| AND -> notImplemented "AND4"
|
|
| COMP -> notImplemented "COMP4"
|
|
| COMPF -> notImplemented "COMPF4"
|
|
| DIV -> notImplemented "DIV4"
|
|
| MUL -> notImplemented "MUL4"
|
|
| OR -> notImplemented "OR4"
|
|
| SUB -> notImplemented "SUB4"
|
|
| SUBF -> notImplemented "SUBF4"
|
|
| TD -> notImplemented "TD4"
|
|
| WD -> notImplemented "WD4"
|
|
|
|
(* Jump / subroutine *)
|
|
| J -> notImplemented "J4"
|
|
| JEQ -> notImplemented "JEQ4"
|
|
| JGT -> notImplemented "JGT4"
|
|
| JLT -> notImplemented "JLT4"
|
|
| JSUB -> notImplemented "JSUB4"
|
|
| RSUB -> notImplemented "RSUB4"
|
|
|
|
(* Load/store *)
|
|
| LDA -> notImplemented "LDA4"
|
|
| LDB -> notImplemented "LDB4"
|
|
| LDCH -> notImplemented "LDCH4"
|
|
| LDF -> notImplemented "LDF4"
|
|
| LDL -> notImplemented "LDL4"
|
|
| LDS -> notImplemented "LDS4"
|
|
| LDT -> notImplemented "LDT4"
|
|
| LDX -> notImplemented "LDX4"
|
|
| LPS -> notImplemented "LPS4"
|
|
| STA -> notImplemented "STA4"
|
|
| STB -> notImplemented "STB4"
|
|
| STCH -> notImplemented "STCH4"
|
|
| STF -> notImplemented "STF4"
|
|
| STL -> notImplemented "STL4"
|
|
| STS -> notImplemented "STS4"
|
|
| STSW -> notImplemented "STSW4"
|
|
| STT -> notImplemented "STT4"
|
|
| STX -> notImplemented "STX4"
|
|
|
|
(* Control / IO *)
|
|
| TIX -> notImplemented "TIX4"
|
|
|_ -> failwith ("Mnemonic" ^ (OpcodeTable.string_of_mnemonic mnemonic) ^ "falsely flaged as format 4")
|
|
|
|
|
|
|
|
|
|
(*execute format 3_4*)
|
|
let executeFormat3_4 (state : state) (mnemonic : OpcodeTable.mnemonic) : unit =
|
|
let nixbpe = getNIXBPE state in
|
|
match nixbpe.e with
|
|
| 0 -> executeFormat3 state nixbpe mnemonic
|
|
| 1 -> executeFormat4 state nixbpe mnemonic
|
|
| _ -> 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 |