(* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) type t = Common.op_code let is_m_op (op : t) = match op with | COPY (R M, _) | COPY (_, M) | VOID_M -> true | _ -> false let get_m_type (op : t) = match op with | COPY (_, M) -> `SEND | COPY (R M, _) -> `RECEIVE | VOID_M -> `VOID_M | TEST_MRD -> `TEST_MRD | _ -> raise Exit let regInstruction name r = Printf.sprintf "%s %s" name (Register.show r) let rnInstruction name rn = Printf.sprintf "%s %s" name (Register.show_r_n rn) let labelInstruction name label = Printf.sprintf "%s %s" name label let srcDestInstruction name src dest = let left = Register.show_r_n src in let right = Register.show dest in Printf.sprintf "%s %s %s" name left right let mathInstruction name src i dest = let left = Register.show_r_n src in let right = Register.show_r_n i in Printf.sprintf "%s %s %s %s" name left right (Register.show dest) let testInstruction name left func right = let left = Register.show_r_n left in let right = Register.show_r_n right in Printf.sprintf "%s %s %s %s" name left func right let show (op : t) : string = match op with | NOOP -> "NOOP" | COPY (src, dest) -> srcDestInstruction "COPY" src dest | ADDI (src, i, dest) -> mathInstruction "ADDI" src i dest | SUBI (src, i, dest) -> mathInstruction "SUBI" src i dest | MULI (src, i, dest) -> mathInstruction "MULI" src i dest | DIVI (src, i, dest) -> mathInstruction "DIVI" src i dest | MODI (src, i, dest) -> mathInstruction "MODI" src i dest | SWIZ (src, i, dest) -> mathInstruction "SWIZ" src i dest | MARK label -> labelInstruction "MARK" label | JUMP label -> labelInstruction "JUMP" label | TJMP label -> labelInstruction "TJMP" label | FJMP label -> labelInstruction "FJMP" label | TEST_EQ (left, right) -> testInstruction "TEST" left "=" right | TEST_LT (left, right) -> testInstruction "TEST" left "<" right | TEST_GT (left, right) -> testInstruction "TEST" left ">" right | HALT -> "HALT" | REPL label -> labelInstruction "REPL" label | LINK dest -> rnInstruction "LINK" dest | HOST dest -> regInstruction "HOST" dest | MODE -> "MODE" | VOID_M -> "VOID M" | TEST_MRD -> "TEST MRD" | MAKE -> "MAKE" | GRAB file -> rnInstruction "GRAB" file | FILE dest -> regInstruction "FILE" dest | SEEK value -> rnInstruction "SEEK" value | VOID_F -> "VOID F" | DROP -> "DROP" | WIPE -> "WIPE" | TEST_EOF -> "TEST EOF" let pp ppf op = Format.fprintf ppf "%s" (show op) let equal (op1 : t) (op2 : t) : bool = match (op1, op2) with | NOOP, NOOP -> true | NOOP, _ -> false | COPY (rn1, t1), COPY (rn2, t2) -> Register.equal_r_n rn1 rn2 && Register.equal t1 t2 | COPY _, _ -> false | ADDI (src1, i1, dest1), ADDI (src2, i2, dest2) | SUBI (src1, i1, dest1), SUBI (src2, i2, dest2) | MULI (src1, i1, dest1), MULI (src2, i2, dest2) | DIVI (src1, i1, dest1), DIVI (src2, i2, dest2) | MODI (src1, i1, dest1), MODI (src2, i2, dest2) | SWIZ (src1, i1, dest1), SWIZ (src2, i2, dest2) -> Register.equal_r_n src1 src2 && Register.equal_r_n i1 i2 && Register.equal dest1 dest2 | DIVI _, _ | ADDI _, _ | SUBI _, _ | MULI _, _ | MODI _, _ | SWIZ _, _ -> false | MARK l1, MARK l2 | JUMP l1, JUMP l2 | TJMP l1, TJMP l2 | FJMP l1, FJMP l2 -> String.equal l1 l2 | MARK _, _ | JUMP _, _ | TJMP _, _ | FJMP _, _ -> false | TEST_EQ (l1, r1), TEST_EQ (l2, r2) | TEST_LT (l1, r1), TEST_LT (l2, r2) | TEST_GT (l1, r1), TEST_GT (l2, r2) -> Register.equal_r_n l1 l2 && Register.equal_r_n r1 r2 | TEST_EQ _, _ | TEST_LT _, _ | TEST_GT _, _ -> false | REPL l1, REPL l2 -> String.equal l1 l2 | REPL _, _ -> false | HALT, HALT -> true | HALT, _ -> false | LINK dest1, LINK dest2 -> Register.equal_r_n dest1 dest2 | LINK _, _ -> false | HOST r1, HOST r2 -> Register.equal r1 r2 | HOST _, _ -> false | MODE, MODE | VOID_M, VOID_M | TEST_MRD, TEST_MRD -> true | MODE, _ | VOID_M, _ | TEST_MRD, _ -> false | MAKE, MAKE -> true | MAKE, _ -> false | GRAB f1, GRAB f2 -> Register.equal_r_n f1 f2 | GRAB _, _ -> false | FILE dest1, FILE dest2 -> Register.equal dest1 dest2 | FILE _, _ -> false | SEEK v1, SEEK v2 -> Register.equal_r_n v1 v2 | SEEK _, _ -> false | VOID_F, VOID_F | DROP, DROP | WIPE, WIPE | TEST_EOF, TEST_EOF -> true | VOID_F, _ | DROP, _ | WIPE, _ | TEST_EOF, _ -> false