working on ass3, todo pc, nixbpe

This commit is contained in:
Jaka Furlan 2025-12-14 23:31:52 +01:00
parent 6261d9fe37
commit beabcde7db
15 changed files with 412 additions and 194 deletions

View file

@ -3,8 +3,9 @@ open Simtab
open SemanticAnalyzer
open Encoder
open Instruction
open OpcodeTable
let drugiPrehod (ifl : lineSemantic list) (simtab : symtab) (lenProg : int) : string list =
let drugiPrehod (ifl : lineSemantic list) (simtab : symtab) (opcodeTab : opcodeTab) (lenProg : int) : string list =
let prviUkaz, ostaliUkazi =
match ifl with
| [] -> failwith "empty code"
@ -41,29 +42,35 @@ let drugiPrehod (ifl : lineSemantic list) (simtab : symtab) (lenProg : int) : st
| [] -> loop xs objectCodeList newStartAddress []
| _ -> loop xs (newTextLine :: objectCodeList) newStartAddress []
end
| BYTE ->
let operand = match x.mnem with | MnemonicSd s -> s | _ -> failwith "narobe mnemType za BYTE" in
let opcode = create_opcode_byte operand in
(*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*)
if List.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*)
let newTextLine = instructionList_to_objectCode (List.rev (opcode :: instructionList)) newStartAddress in (*naredimo novo T vrstico*)
loop xs (newTextLine :: objectCodeList) newStartAddress []
else
loop xs objectCodeList newStartAddress (opcode :: instructionList)
| WORD ->
let operand = match x.mnem with | MnemonicSd s -> s | _ -> failwith "narobe mnemType za WORD" in
let opcode = create_opcode_word operand in
(*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*)
if List.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*)
let newTextLine = instructionList_to_objectCode (List.rev (opcode :: instructionList)) newStartAddress in (*naredimo novo T vrstico*)
loop xs (newTextLine :: objectCodeList) newStartAddress []
else
loop xs objectCodeList newStartAddress (opcode :: instructionList)
| _ -> (*if not comment or reserve*)
(*if simbol na mestu opeanda*)
let isSymbol, symbol = operand_is_symbol x.mnem in
if isSymbol then
begin
let locSimbola = find_symbol tab symbol in
let opcode = create_opcode_symbol x.opcode locSimbola in
(*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*)
if String.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*)
let newTextLine = instructionList_to_objectCode (List.rev instructionList) newStartAddress in (*naredimo novo T vrstico*)
loop xs (newTextLine :: objectCodeList) newStartAddress []
else
loop xs objectCodeList newStartAddress (opcode :: instructionList)
end
else
let opcode = create_opcode x.opcode x.mnem in (*symbol je tukaj kar stevilska vrednost/register*)
(*TODO dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*)
begin
if String.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*)
let newTextLine = instructionList_to_objectCode (List.rev instructionList) newStartAddress in (*naredimo novo T vrstico*)
loop xs (newTextLine :: objectCodeList) newStartAddress []
else
loop xs objectCodeList newStartAddress (opcode :: instructionList)
end
match operand_is_symbol x with
| None -> loop xs objectCodeList newStartAddress instructionList (*None -> ta ukaz se ne zapiše, ga skipamo*)
| Some (_, operand, formatLen) ->
let opcode = create_opcode simtab opcodeTab x.opcode operand formatLen x.loc in
(*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*)
if List.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*)
let newTextLine = instructionList_to_objectCode (List.rev (opcode :: instructionList)) newStartAddress in (*naredimo novo T vrstico*)
loop xs (newTextLine :: objectCodeList) newStartAddress []
else
loop xs objectCodeList newStartAddress (opcode :: instructionList)
in loop ostaliUkazi objectCodeList startAddr instructionList
in loop ostaliUkazi objectCodeList start instructionList

View file

@ -1,10 +1,3 @@
(library
(name zbirnik)
(libraries str)
(modules parser
simtab
semanticAnalyzer
prehodPrvi
encoder
drugiPrehod
instruction))
(libraries str))

View file

@ -7,17 +7,17 @@ let getZaglavjeAndStart (prviUkaz : lineSemantic) (lenProg : int) : string list
| None -> "MOJPROG" (*default ime*)
| Some s -> if String.length s > 6 then "MOJPROG" else String.make (6 - String.length s) '0' ^ s (*paddamo z 0 če je < 6*)
in
let startAddr = match prviUkaz.mnem with
let startAddrString, startAddrInt = match prviUkaz.mnem with
| MnemonicDn s -> (*preverimo ali je pravilne dolzine in naredimo string dolzine 6*)
let n = int_of_string s in
if n < 0 || n > 0xFFFFFF then
invalid_arg "getZaglavje: zacetni naslov out of range"
else
Printf.sprintf "%06X" n
(Printf.sprintf "%06X" n), n
| _ -> failwith "getZaglavje: invalid mnemonic_type"
in
let lenObjectCode = Printf.sprintf "%06X" lenProg in
["H" ^ name ^ startAddr ^ lenObjectCode], int_of_string startAddr (*vrnemo concatiniran string in startAddr*)
["H" ^ name ^ startAddrString ^ lenObjectCode], startAddrInt(*vrnemo concatiniran string in startAddr*)
(*vrne T vrstico*)

View file

@ -2,31 +2,143 @@
(*sem spada izbira nacina naslavljanja, dolocanje ali je operand simbol itd..*)
open SemanticAnalyzer
open Simtab
open OpcodeTable
type operand =
| R of register
| RR of register * register
| RN of register * int (*register in število*)
| N of int (*številski operand*)
| S of string (*simbol*)
| None
let string_is_symbol (s : string) : bool * string =
let string_is_symbol (s : string) : bool * operand =
try
let _ = int_of_string s in
true, ""
with Failure _ -> false, s
let n = int_of_string s in
false, N n
with Failure _ -> true, S s
(*preveri ali je operand iz mnemonic_type simbol ali stevilo*)
let operand_is_symbol (operand : mnemonic_type) : bool * string = (*vrne isSymbol in symbol*)
let operand_is_symbol (x : lineSemantic) : (bool * operand * int) option = (*vrne isSymbol, operand in dolzino ukaza, ali none, če ukaza/direktive ne bomo zapisali v T file*)
match x.mnem with
| MnemonicD -> None
| MnemonicDn s -> let (issym, operand) = string_is_symbol s in Some (issym, operand, x.len)
| MnemonicF1 -> Some (false, None, x.len)
| MnemonicF2n n -> Some (false, N n, x.len)
| MnemonicF2r r1 -> Some (false, R r1, x.len)
| MnemonicF2rn (r1, n) -> Some (false, RN (r1, n), x.len)
| MnemonicF2rr (r1, r2) -> Some (false, RR (r1, r2), x.len)
| MnemonicF3 -> Some (false, None, x.len)
| MnemonicF3m s -> let (issym, operand) = string_is_symbol s in Some (issym, operand, x.len)
| MnemonicF4m s -> let (issym, operand) = string_is_symbol s in Some (issym, operand, x.len)
| MnemonicSd s -> let (issym, operand) = string_is_symbol s in Some (issym, operand, x.len)
| MnemonicSn _ -> None(*RESW in RESB že drugje obdelamo*)
| COMMENT -> None (*Comment ze obdelamo drugje*)
(*helper funkcija za registre*)
let int_of_reg (reg : register) : int =
match reg with
| A -> 0
| X -> 1
| L -> 2
| B -> 3
| S -> 4
| T -> 5
| F -> 6
| PC -> 8
| SW -> 9
(*helper funkcija*)
let int_to_hex_width (width : int) (n : int) : string =
let s = Printf.sprintf "%X" n in
let len = String.length s in
if len >= width then s
else String.make (width - len) '0' ^ s
let char_to_hex c =
Printf.sprintf "%02X" (Char.code c)
(*naredi binaren zapis F1 oz string nibblov celotnega ukaza*)
let get_bin_instruction_F1 (opcode : int) : string =
int_to_hex_width 2 opcode
(*naredi binaren zapis F2 oz string nibblov celotnega ukaza*)
let get_bin_instruction_F2 (opcode : int) (operand : operand) : string =
match operand with
| MnemonicD -> false, ""
| MnemonicDn s -> string_is_symbol s
| MnemonicF1 -> false, ""
| MnemonicF2n _ -> false, ""
| MnemonicF2r _ -> false, ""
| MnemonicF2rn (_, _) -> false, ""
| MnemonicF2rr (_, _) -> false, ""
| MnemonicF3 -> false, ""
| MnemonicF3m s -> string_is_symbol s
| MnemonicF4m s -> string_is_symbol s
| MnemonicSd s -> string_is_symbol s
| MnemonicSn _ -> false, ""
| COMMENT -> false, ""
| RR (r1, r2) -> (int_to_hex_width 2 opcode) ^ (int_to_hex_width 1 (int_of_reg r1)) ^ (int_to_hex_width 1 (int_of_reg r2))
| RN (r1, n) -> (int_to_hex_width 2 opcode) ^ (int_to_hex_width 1 (int_of_reg r1)) ^ (int_to_hex_width 1 n)
| R r1 -> (int_to_hex_width 2 opcode) ^ (int_to_hex_width 1 (int_of_reg r1)) ^ (int_to_hex_width 1 0) (*r2 -> 0*)
| N n -> (int_to_hex_width 2 opcode) ^ (int_to_hex_width 1 n) ^ (int_to_hex_width 1 0)
| _ -> failwith "invalid operand type for F2 instruction"
let get_bin_instruction_F3 (opcode : int) (simtab : symtab) (operand : operand) (_ : int option) : string =
match operand with
| None -> (int_to_hex_width 2 opcode) ^ (int_to_hex_width 4 0) (*RSUB damo z disp = 0*)
| N n -> (*todo dodaj n_i*) (int_to_hex_width 2 opcode) ^ (*todo add xbpe*) (int_to_hex_width 1 0) ^ (int_to_hex_width 3 n)
| S s -> let operand = Hashtbl.find simtab s in (int_to_hex_width 2 opcode) ^ (int_to_hex_width 1 0) ^ (int_to_hex_width 3 operand)
| _ -> ""
let get_bin_instruction_F4 (opcode : int) (simtab : symtab) (operand : operand) (_ : int option) : string =
match operand with
| None -> (int_to_hex_width 2 opcode) ^ (int_to_hex_width 6 0) (*RSUB damo z disp = 0*)
| N n -> (*todo dodaj n_i*) (int_to_hex_width 2 opcode) ^ (*todo add xbpe*) (int_to_hex_width 1 0) ^ (int_to_hex_width 5 n)
| S s -> let operand = Hashtbl.find simtab s in (int_to_hex_width 2 opcode) ^ (int_to_hex_width 1 0) ^ (int_to_hex_width 5 operand)
| _ -> ""
let create_opcode (simtab : symtab) (opcodeTab : opcodeTab) (opcode : mnemonic) (operand : operand) (formatLen : int) (loc : int option) : string =
(*izberi nacin naslavljanja in naredi string ukaza*)
match formatLen with
| 1 -> get_bin_instruction_F1 (find_opcode opcodeTab opcode)
| 2 -> get_bin_instruction_F2 (find_opcode opcodeTab opcode) operand
| 3 -> get_bin_instruction_F3 (find_opcode opcodeTab opcode) simtab operand loc
| 4 -> get_bin_instruction_F4 (find_opcode opcodeTab opcode) simtab operand loc
| _ -> failwith "invalid formatLen"
(*opcode BYTE direktive*)
let create_opcode_byte (operand : string) : string =
if String.length operand < 3 then
failwith "Invalid BYTE operand, use X'...' or C'...'!"
else
match operand.[0] with
| 'C' ->
(* e.g., C'EOF' *)
let content = String.sub operand 2 (String.length operand - 3) in
let len = String.length content in
if len <> 1 then failwith "BYTE C'...' has to have a operand of length 1 inside hte '...' brackets!" else
String.concat "" (List.init (String.length content) (fun i -> char_to_hex content.[i]))
| 'X' ->
(* e.g., X'F1' *)
let hex = String.sub operand 2 (String.length operand - 3) in
if String.length hex >= 6 then
failwith "WORD X'...' has to have a operand of length <= 6 inside hte '...' brackets!"
else String.make (2 - String.length hex) '0' ^ hex
| _ ->
let n = int_of_string operand in
Printf.sprintf "%02X" n
let create_opcode_word (operand : string) : string =
if String.length operand = 0 then
failwith "Invalid WORD operand use X'...' or C'...'!"
else
match operand.[0] with
| 'C' ->
(* WORD as C'...' *)
let content = String.sub operand 2 (String.length operand - 3) in
let len = String.length content in
if len <> 3 then failwith "WORD C'...' has to have a operand of length 3 inside hte '...' brackets!" else
let hex = String.concat "" (List.init len (fun i -> char_to_hex content.[i])) in
(* pad to 6 hex digits for WORD *)
if String.length hex >= 6 then hex else String.make (6 - String.length hex) '0' ^ hex
| 'X' ->
(* WORD as X'...' *)
let hex = String.sub operand 2 (String.length operand - 3) in
if String.length hex >= 6 then
failwith "WORD X'...' has to have a operand of length <= 6 inside hte '...' brackets!"
else String.make (6 - String.length hex) '0' ^ hex
| _ ->
(* numeric constant *)
let n = int_of_string operand in
Printf.sprintf "%06X" n
let create_opcode_symbol (opcode : mnemonic) (locSimbola : int) : string =
(*izberi nacin naslavljanja in naredi string ukaza*)

View file

@ -0,0 +1,77 @@
open SemanticAnalyzer
type opcodeTab = (mnemonic, int) Hashtbl.t
let find_opcode (tab : opcodeTab) (mnemonic : mnemonic) : int =
try
Hashtbl.find tab mnemonic
with
| Not_found -> failwith (Printf.sprintf "[OpcodeTable] Mnemonic not found: '%s'." (string_of_mnemonic mnemonic) )
let get_opcode_table () : opcodeTab=
let opcode_table : (mnemonic, int) Hashtbl.t = Hashtbl.create 128 in
let add mnemonic opcode =
Hashtbl.add opcode_table mnemonic opcode
in
(* Format 1 *)
add FIX 0xC4;
add FLOAT 0xC0;
add HIO 0xC8;
add NORM 0xC1;
add SIO 0xF0;
add TIO 0xF8;
(* Format 2 *)
add ADDR 0x90;
add CLEAR 0xB4;
add COMPR 0xA0;
add DIVR 0x9C;
add MULR 0x98;
add RMO 0xAC;
add SHIFTL 0xA4;
add SHIFTR 0xA8;
add SUBR 0x94;
add SVC 0xB0;
add TIXR 0xB8;
(* Format 3 / 4 *)
add ADD 0x18;
add ADDF 0x58;
add AND 0x40;
add COMP 0x28;
add COMPF 0x88;
add DIV 0x24;
add J 0x3C;
add JEQ 0x30;
add JGT 0x34;
add JLT 0x38;
add JSUB 0x48;
add LDA 0x00;
add LDB 0x68;
add LDCH 0x50;
add LDF 0x70;
add LDL 0x08;
add LDS 0x6C;
add LDT 0x74;
add LDX 0x04;
add LPS 0xD0;
add MUL 0x20;
add OR 0x44;
add RD 0xD8;
add RSUB 0x4C;
add STA 0x0C;
add STB 0x78;
add STCH 0x54;
add STF 0x80;
add STL 0x14;
add STS 0x7C;
add STSW 0xE8;
add STT 0x84;
add STX 0x10;
add SUB 0x1C;
add SUBF 0x5C;
add TD 0xE0;
add TIX 0x2C;
add WD 0xDC;
opcode_table

View file

@ -117,6 +117,9 @@ type lineSemantic = {
ext : bool; (*za razlikovanje med F3 in F4*)
opcode : mnemonic;
mnem : mnemonic_type;
x : bool; (*ali imamo X naslavljanje*)
n : bool;
i : bool;
comment : string option;
len : int; (*dolžina, pove za koliko moramo povečati locctr*)
mutable loc : int option; (* assigned in pass1 *)
@ -130,78 +133,30 @@ let getMnem (opcode : string) : mnemonic * bool =
let o =
match opcode with
(* ------------------- Format 1 instructions ------------------- *)
| "FIX" -> FIX
| "FLOAT" -> FLOAT
| "HIO" -> HIO
| "NORM" -> NORM
| "SIO" -> SIO
| "TIO" -> TIO
| "FIX" -> FIX | "FLOAT" -> FLOAT | "HIO" -> HIO
| "NORM" -> NORM | "SIO" -> SIO | "TIO" -> TIO
(* ------------------- Format 2 instructions ------------------- *)
| "ADDR" -> ADDR
| "CLEAR" -> CLEAR
| "COMPR" -> COMPR
| "DIVR" -> DIVR
| "MULR" -> MULR
| "RMO" -> RMO
| "SHIFTL" -> SHIFTL
| "SHIFTR" -> SHIFTR
| "SUBR" -> SUBR
| "SVC" -> SVC
| "TIXR" -> TIXR
| "ADDR" -> ADDR | "CLEAR" -> CLEAR | "COMPR" -> COMPR | "DIVR" -> DIVR
| "MULR" -> MULR | "RMO" -> RMO | "SHIFTL" -> SHIFTL | "SHIFTR" -> SHIFTR
| "SUBR" -> SUBR | "SVC" -> SVC | "TIXR" -> TIXR
(* ------------------- Format 3/4 instructions ------------------- *)
| "ADD" -> ADD
| "ADDF" -> ADDF
| "AND" -> AND
| "COMP" -> COMP
| "COMPF" -> COMPF
| "DIV" -> DIV
| "J" -> J
| "JEQ" -> JEQ
| "JGT" -> JGT
| "JLT" -> JLT
| "JSUB" -> JSUB
| "LDA" -> LDA
| "LDB" -> LDB
| "LDCH" -> LDCH
| "LDF" -> LDF
| "LDL" -> LDL
| "LDS" -> LDS
| "LDT" -> LDT
| "LDX" -> LDX
| "LPS" -> LPS
| "MUL" -> MUL
| "OR" -> OR
| "RD" -> RD
| "RSUB" -> RSUB
| "STA" -> STA
| "STB" -> STB
| "STCH" -> STCH
| "STF" -> STF
| "STL" -> STL
| "STS" -> STS
| "STSW" -> STSW
| "STT" -> STT
| "STX" -> STX
| "SUB" -> SUB
| "SUBF" -> SUBF
| "TD" -> TD
| "TIX" -> TIX
| "WD" -> WD
| "ADD" -> ADD | "ADDF" -> ADDF | "AND" -> AND | "COMP" -> COMP
| "COMPF" -> COMPF | "DIV" -> DIV | "J" -> J | "JEQ" -> JEQ
| "JGT" -> JGT | "JLT" -> JLT | "JSUB" -> JSUB | "LDA" -> LDA
| "LDB" -> LDB | "LDCH" -> LDCH | "LDF" -> LDF | "LDL" -> LDL
| "LDS" -> LDS | "LDT" -> LDT | "LDX" -> LDX | "LPS" -> LPS
| "MUL" -> MUL | "OR" -> OR | "RD" -> RD | "RSUB" -> RSUB | "STA" -> STA
| "STB" -> STB | "STCH" -> STCH | "STF" -> STF | "STL" -> STL | "STS" -> STS
| "STSW" -> STSW | "STT" -> STT | "STX" -> STX | "SUB" -> SUB
| "SUBF" -> SUBF | "TD" -> TD | "TIX" -> TIX | "WD" -> WD
(* ------------------- SIC/XE Directives ------------------- *)
| "START" -> START
| "END" -> END
| "ORG" -> ORG
| "EQU" -> EQU
| "BASE" -> BASE
| "NOBASE" -> NOBASE
| "LTORG" -> LTORG
| "RESW" -> RESW
| "RESB" -> RESB
| "WORD" -> WORD
| "BYTE" -> BYTE
| "START" -> START | "END" -> END | "ORG" -> ORG
| "EQU" -> EQU | "BASE" -> BASE | "NOBASE" -> NOBASE
| "LTORG" -> LTORG | "RESW" -> RESW | "RESB" -> RESB
| "WORD" -> WORD | "BYTE" -> BYTE
(*comment*)
| "COMMENT" -> COMMENT
@ -281,6 +236,7 @@ let getMnemType (opcode : mnemonic) (ext : bool) (operand : string list) : mnemo
| _, _ -> failwith (Printf.sprintf "Invalid operands for opcode %s: %d operands"
(string_of_mnemonic opcode) (List.length operand))
(*vrni dolzino ukaza*)
let getLen (mnemType : mnemonic_type) (mnem : mnemonic) : int =
match mnemType with
(* ----------- directives with no memory ----------- *)
@ -316,11 +272,48 @@ let getLen (mnemType : mnemonic_type) (mnem : mnemonic) : int =
| _ -> failwith "Narobe mnemoic glede na mnemType"
end
(*preveri ali imaš X naslavljanje*)
let has_index (ops : string list) : bool * string list = (*vrne bool x in operande brez X*)
match ops with
| [lst; x] when String.uppercase_ascii x = "X" -> true, [lst] (*predpostavimo da se X pojavi na drugem mestu in nikoli na tretjem*)
| _ -> false, ops
(*dobi n in i bita in operande brez # ali @*)
let get_ni_bits (operands : string list) : bool * bool * string list =
match operands with
| [] ->
(true, true, [])
| op :: rest ->
if String.length op = 0 then
(true, true, operands)
else
match op.[0] with
| '#' ->
let stripped =String.sub op 1 (String.length op - 1) in
(false, true, stripped :: rest)
| '@' ->
let stripped = String.sub op 1 (String.length op - 1) in
(true, false, stripped :: rest)
| _ ->
(true, true, operands)
let checkLineSemantic (line : line) : lineSemantic =
let mnem, ext = getMnem line.opcode in
let mnemType = getMnemType mnem ext line.operand in
let x, ops = has_index line.operand in
let n, i, ops = get_ni_bits ops in
let mnemType = getMnemType mnem ext ops in
let dolzina = getLen mnemType mnem in
{line_no = line.line_no; label = line.label; ext = ext; opcode = mnem; mnem = mnemType; comment = line.comment; len = dolzina; loc = line.loc}
{ line_no = line.line_no;
label = line.label;
ext = ext;
opcode = mnem;
mnem = mnemType;
x = x;
n = n;
i = i;
comment = line.comment;
len = dolzina;
loc = line.loc}
let checkLineSemanticOfCode (code : line list) : lineSemantic list =
List.map (checkLineSemantic) code

View file

@ -11,5 +11,8 @@ let add_symbol (tab : symtab) (label : string) (addr : int) =
else
Hashtbl.add tab label addr
let find_symbol (tab : symtab) (label : string) : int =
Hashtbl.find tab label
let find_symbol (tab : symtab) (label : string) : int =
try
Hashtbl.find tab label
with
| Not_found -> failwith (Printf.sprintf "[SimTab] Symbol not found: '%s'." label)