(*naloga instruction modula je ustvarjanje instructionLista, torej vsebine T zapisa*) (*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 * operand = try 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 (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 | 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