(* These type definitions document the target processor's operators
   and branch conditions. Here, the target processor is the MIPS. *)

(* The MIPS manual explains that some instructions are actual machine
   instructions, while others are pseudo-instructions, which are
   expanded away by the assembler. Do we need to be aware of the

   Ignoring the distinction is interesting. There are several
   processors in the MIPS family, and the distinction between actual
   instructions and pseudo-instructions might vary with the
   processor. For instance, a future member of the MIPS family might
   implement more instructions in hardware than its predecessors.

   On the other hand, ignoring the distinction means that we cannot
   use the hardware register [$at], which is reserved by the assembler
   for translating some pseudo-instructions into actual instructions.

   Our approach is to follow standard practice and to exploit
   pseudo-instructions when desired. This means that we cannot use
   register [$at]. *)

(* Immediate constants, used in the definition of some operators. They
   must fit in 16 bits. *)

type immediate16 =

(* Offsets, used as part of addressing modes. They are measured in
   bytes and must fit in 16 bits. *)

type offset =

(* Unary (integer arithmetic) operators. *)

type unop =
  | UOpAddi of immediate16
  | UOpSlli of immediate16 (* shift left logical *)
  | UOpSlti of immediate16 (* set on less than immediate *)

(* Binary (integer arithmetic or integer comparison) operators. Among
   the comparison operators, only [OpLt] corresponds to a MIPS binary
   comparison instruction, namely [slt]. All others correspond to
   pseudo-instructions. They are exploited because they are
   convenient. *)

type binop =
  | OpAdd
  | OpSub
  | OpMul
  | OpDiv
  | OpLt                                       
  | OpLe
  | OpGt
  | OpGe
  | OpEq
  | OpNe 

(* Unary branch conditions. *)

type uncon =

    (* Greater than or equal to zero. *)

  | UConGez

    (* Greater than zero. *)

  | UConGtz

    (* Less than or equal to zero. *)

  | UConLez

    (* Less than zero. *)

  | UConLtz

(* Binary branch conditions. *)

and bincon =

    (* Equal. *)

  | ConEq

    (* Not equal. *)

  | ConNe