Theory X86_InstructionSemantics

(*  Title:       X86 instruction semantics and basic block symbolic execution
    Authors:     Freek Verbeek, Abhijith Bharadwaj, Joshua Bockenek, Ian Roessle, Timmy Weerwag, Binoy Ravindran
    Year:        2020
    Maintainer:  Freek Verbeek (freek@vt.edu)
*)

section "Instruction Semantics"

theory X86_InstructionSemantics
  imports State
begin

text ‹A datatype for storing instructions. Note that we add a special kind of meta-instruction, called
      ExternalFunc. A call to an external function can manually be mapped to a manually supplied state 
      transformation function.›
datatype I = 
    Instr string "Operand option" "Operand option" "Operand option" "64 word"
  | ExternalFunc "state  state"

text ‹A datatype for the result of floating point comparisons.›
datatype FP_Order = FP_Unordered | FP_GT | FP_LT | FP_EQ


abbreviation "instr_next i  case i of (Instr _ _ _ _ a')  a'"

locale unknowns =
  fixes unknown_addsd     :: "64 word  64 word  64 word"
    and unknown_subsd     :: "64 word  64 word  64 word"
    and unknown_mulsd     :: "64 word  64 word  64 word"
    and unknown_divsd     :: "64 word  64 word  64 word"
    and unknown_ucomisd   :: "64 word  64 word  FP_Order"
    and unknown_semantics :: "I  state  state"
    and unknown_flags     :: "string  string  bool" 
begin

text ‹
  The semantics below are intended to be overapproximative and incomplete.
  This is achieved using locale ``unknowns''.
  Any place where semantics is \emph{not} modelled, it is mapped to a universally quantified uninterpreted function
  from that locale. We do not make use of @{const undefined}, since that could be used to prove that the semantics
  of two undefined behaviors are equivalent. 
  For example:
  \begin{itemize}
  \item Only a subset of instructions has semantics. In case of an unknown instruction $i$,
        the function @{term semantics} below will result in @{term "unknown_semantics i"}.
  \item Not all flags have been defined. In case a flag is read whose semantics is not defined below,
        the read will resolve to @{term "unknown_flags i f"}. Note that if the semantics of an instruction do
        not set flags, an overapproximative semantics such as below imply that the instruction indeed
        does not modify flags. In order words, if we were uncertain we would assign unknown values to flags.
  \item Not all operations have been defined. For example, floating points operations have no executable
        semantics, but are mapped to uninterpreted functions such as @{term unknown_addsd}.
  \end{itemize}
›



text ‹Moves›

definition semantics_MOV :: "Operand  Operand  state  state"
  where "semantics_MOV op1 op2 σ 
          let src = operand_read σ op2 in
             operand_write op1 src σ"

abbreviation MOV
  where "MOV op1 op2  Instr ''mov'' (Some op1) (Some op2) None"

abbreviation MOVABS
  where "MOVABS op1 op2  Instr ''movabs'' (Some op1) (Some op2) None"

abbreviation MOVAPS
  where "MOVAPS op1 op2  Instr ''movaps'' (Some op1) (Some op2) None"

abbreviation MOVZX
  where "MOVZX op1 op2  Instr ''movzx'' (Some op1) (Some op2) None"

abbreviation MOVDQU
  where "MOVDQU op1 op2  Instr ''movdqu'' (Some op1) (Some op2) None"

definition semantics_MOVD :: "Operand  Operand  state  state"
  where "semantics_MOVD op1 op2 σ 
          let src = ucast(operand_read σ op2)::32word in
             operand_write op1 (ucast src) σ"

abbreviation MOVD
  where "MOVD op1 op2  Instr ''movd'' (Some op1) (Some op2) None"

fun isXMM :: "Operand  bool"
  where "isXMM (Reg r) = (take 3 r = ''xmm'')"
  | "isXMM _ = False"

definition semantics_MOVSD :: "Operand  Operand  state  state"
  where "semantics_MOVSD op1 op2 σ 
    if isXMM op1  isXMM op2 then
      let src = 0,64operand_read σ op2;
          dst = 64,128operand_read σ op1 in
             operand_write op1 (overwrite 0 64 dst src) σ
     else
      let src = 0,64operand_read σ op2 in
         operand_write op1 src σ"

abbreviation MOVSD
  where "MOVSD op1 op2  Instr ''movsd'' (Some op1) (Some op2) None"

abbreviation MOVQ
  where "MOVQ op1 op2  Instr ''movq'' (Some op1) (Some op2) None"


text ‹ lea/push/pop/call/ret/leave ›

definition semantics_LEA :: "Operand  Operand  state  state"
  where "semantics_LEA op1 op2 σ 
          case op2 of Mem si offset base index scale 
            operand_write op1 (ucast (resolve_address σ offset base index scale)) σ"

abbreviation LEA
  where "LEA op1 op2  Instr ''lea'' (Some op1) (Some op2) None"

definition semantics_PUSH :: "Operand  state  state"
  where "semantics_PUSH op1 σ 
          let src = operand_read σ op1;
              si  = operand_size op1;
              rsp = ucast (ucast(reg_read σ ''rsp'') - of_nat si :: 64 word) in
             operand_write (QWORD PTR [''rsp'']1) src (operand_write (Reg ''rsp'') rsp σ)"

abbreviation PUSH
  where "PUSH op1  Instr ''push'' (Some op1) None None"

definition semantics_POP :: "Operand  state  state"
  where "semantics_POP op1 σ 
          let si  = operand_size op1;
              src = operand_read σ (QWORD PTR [''rsp'']1);
              rsp = ucast (ucast(reg_read σ ''rsp'') + of_nat si::64 word) in
             operand_write op1 src (operand_write (Reg ''rsp'') rsp σ)"

abbreviation POP
  where "POP op1  Instr ''pop'' (Some op1) None None"

definition semantics_CALL :: "Operand  state  state"
  where "semantics_CALL op1 σ 
        let src = ucast (operand_read σ op1) in
           (state_update (setRip src) o semantics_PUSH (Reg ''rip'')) σ"

definition semantics_RET :: "state  state"
  where "semantics_RET σ 
          let a   = ucast (operand_read σ (QWORD PTR [''rsp'']1));
              rsp = ucast (reg_read σ ''rsp'') + 8 :: 64 word in
             (state_update (setRip a) o operand_write (Reg ''rsp'') (ucast rsp)) σ"

abbreviation RET
  where "RET  Instr ''ret'' None None None"

definition semantics_LEAVE :: "state  state"
  where "semantics_LEAVE  semantics_POP (Reg ''rbp'') o semantics_MOV (Reg ''rsp'') (Reg ''rbp'')"

abbreviation LEAVE
  where "LEAVE op1  Instr ''pop'' (Some op1) None None"

text ‹Generic operators ›

definition unop :: "('a ::len word  'a::len word)  
                     ('a::len word   string  bool) 
                      Operand  state  state"
  where "unop f g op1 σ 
          let si  = operand_size op1;
              dst = ucast (operand_read σ op1)::'a::len word in
             operand_write op1 (ucast (f dst)) (σ with [setFlags (g dst)])"

definition binop :: "('a::len word  'a ::len word  'a::len word) 
                     ('a::len word  'a::len word   string  bool) 
                      Operand  Operand  state  state"
  where "binop f g op1 op2 σ 
          let dst = ucast (operand_read σ op1)::'a::len word;
              src = ucast (operand_read σ op2)::'a::len word in
             operand_write op1 (ucast (f dst src)) (σ with [setFlags (g dst src)])"

definition unop_no_flags :: "('a ::len word  'a::len word)  Operand  state  state"
  where "unop_no_flags f op1 σ 
          let dst = ucast (operand_read σ op1)::'a::len word in
             operand_write op1 (ucast (f dst)) σ"

definition binop_flags :: "('a::len word  'a::len word   string  bool) 
                      Operand  Operand  state  state"
  where "binop_flags g op1 op2 σ 
          let si  = operand_size op1;
              dst = ucast (operand_read σ op1)::'a::len word;
              src = ucast (operand_read σ op2)::'a::len word in
            σ with [setFlags (g dst src)]"

definition binop_no_flags :: "('a::len word  'a ::len word  'a::len word) 
                      Operand  Operand  state  state"
  where "binop_no_flags f op1 op2 σ 
          let si  = operand_size op1;
              dst = ucast (operand_read σ op1)::'a::len word;
              src = ucast (operand_read σ op2)::'a::len word in
            operand_write op1 (ucast (f dst src)) σ"

definition binop_XMM :: "(64 word  64 word  64 word)  Operand  Operand  state  state"
  where "binop_XMM f op1 op2 σ 
          let dst = ucast (operand_read σ op1)::64word;
              src = ucast (operand_read σ op2)::64word in
            operand_write op1 (ucast (overwrite 0 64 dst (f dst src))) σ"

text ‹Arithmetic›

definition ADD_flags :: "'a::len word  'a::len word  string  bool"
  where "ADD_flags w0 w1 flag  case flag of
    ''zf''  w0 + w1 = 0
  | ''cf''  unat w0 + unat w1  2^(LENGTH('a))
  | ''of''  (w0 <s 0  w1 <s 0)  ¬(w0 <s 0  w0+w1 <s 0)
  | ''sf''  w0 + w1 <s 0
  | f       unknown_flags ''ADD'' f"

definition semantics_ADD :: "Operand  Operand  state  state"
  where "semantics_ADD op1  
           if operand_size op1 = 32 then binop ((+)::256 word  _  _) ADD_flags op1
      else if operand_size op1 = 16 then binop ((+)::128 word  _  _) ADD_flags op1
      else if operand_size op1 = 8  then binop ((+)::64  word  _  _) ADD_flags op1
      else if operand_size op1 = 4  then binop ((+)::32  word  _  _) ADD_flags op1
      else if operand_size op1 = 2  then binop ((+)::16  word  _  _) ADD_flags op1
      else if operand_size op1 = 1  then binop ((+)::8   word  _  _) ADD_flags op1
      else undefined"

abbreviation ADD
  where "ADD op1 op2  Instr ''add'' (Some op1) (Some op2) None"


definition INC_flags :: "256 word  ('a::len word  string  bool)"
  where "INC_flags cf w0 flag  case flag of
    ''zf''  w0 + 1 = 0
  | ''cf''  cf  0
  | ''of''  0 <=s w0  w0+1 <s 0
  | ''sf''  w0 + 1 <s 0
  | f       unknown_flags ''INC'' f"

definition semantics_INC :: "Operand  state  state" 
  where "semantics_INC op1 σ  
    let cf = flag_read σ ''cf'' in
           if operand_size op1 = 32 then unop ((+) (1::256 word)) (INC_flags cf) op1 σ
      else if operand_size op1 = 16 then unop ((+) (1::128 word)) (INC_flags cf) op1 σ
      else if operand_size op1 = 8  then unop ((+) (1::64  word)) (INC_flags cf) op1 σ
      else if operand_size op1 = 4  then unop ((+) (1::32  word)) (INC_flags cf) op1 σ
      else if operand_size op1 = 2  then unop ((+) (1::16  word)) (INC_flags cf) op1 σ
      else if operand_size op1 = 1  then unop ((+) (1::8   word)) (INC_flags cf) op1 σ
      else undefined"

abbreviation INC
  where "INC op1  Instr ''inc'' (Some op1) None None"

definition DEC_flags :: "256 word  ('a::len word  string  bool)"
  where "DEC_flags cf w0 flag  case flag of
    ''zf''  w0 = 1
  | ''cf''  cf  0
  | ''of''  w0 <s 0  0 <=s w0 - 1
  | ''sf''  w0 - 1 <s 0
  | f       unknown_flags ''DEC'' f"

definition semantics_DEC :: "Operand  state  state" 
  where "semantics_DEC op1 σ  
    let cf = flag_read σ ''cf'' in
           if operand_size op1 = 32 then unop (λ w . w - 1::256 word) (DEC_flags cf) op1 σ
      else if operand_size op1 = 16 then unop (λ w . w - 1::128 word) (DEC_flags cf) op1 σ
      else if operand_size op1 = 8  then unop (λ w . w - 1::64  word) (DEC_flags cf) op1 σ
      else if operand_size op1 = 4  then unop (λ w . w - 1::32  word) (DEC_flags cf) op1 σ
      else if operand_size op1 = 2  then unop (λ w . w - 1::16  word) (DEC_flags cf) op1 σ
      else if operand_size op1 = 1  then unop (λ w . w - 1::8   word) (DEC_flags cf) op1 σ
      else undefined"

abbreviation DEC
  where "DEC op1  Instr ''dec'' (Some op1) None None"

definition NEG_flags :: "('a::len word  string  bool)"
  where "NEG_flags w0 flag  case flag of
    ''zf''  w0 = 0
  | ''cf''  w0  0
  | ''sf''  - w0 <s 0
  | ''of''  msb (- w0)  msb w0
  | f       unknown_flags ''NEG'' f"


definition semantics_NEG :: "Operand  state  state" 
  where "semantics_NEG op1 σ  
           if operand_size op1 = 32 then unop (λ w0 . - (w0::256 word)) NEG_flags op1 σ
      else if operand_size op1 = 16 then unop (λ w0 . - (w0::128 word)) NEG_flags op1 σ
      else if operand_size op1 = 8  then unop (λ w0 . - (w0::64  word)) NEG_flags op1 σ
      else if operand_size op1 = 4  then unop (λ w0 . - (w0::32  word)) NEG_flags op1 σ
      else if operand_size op1 = 2  then unop (λ w0 . - (w0::16  word)) NEG_flags op1 σ
      else if operand_size op1 = 1  then unop (λ w0 . - (w0::8   word)) NEG_flags op1 σ
      else undefined"

abbreviation NEG
  where "NEG op1  Instr ''neg'' (Some op1) None None"

definition SUB_flags :: "'a::len word  'a::len word  string   bool"
  where "SUB_flags w0 w1 flag  case flag of
    ''zf''  w0 = w1
  | ''cf''  w0 < w1
  | ''sf''  w0 - w1 <s 0
  | ''of''  (msb w0  msb w1)  (msb (w0 - w1) = msb w1)
  | f       unknown_flags ''SUB'' f"

definition semantics_SUB :: "Operand  Operand  state  state"
  where "semantics_SUB op1  
           if operand_size op1 = 32 then binop ((-)::256 word  _  _) SUB_flags op1
      else if operand_size op1 = 16 then binop ((-)::128 word  _  _) SUB_flags op1
      else if operand_size op1 = 8  then binop ((-)::64  word  _  _) SUB_flags op1
      else if operand_size op1 = 4  then binop ((-)::32  word  _  _) SUB_flags op1
      else if operand_size op1 = 2  then binop ((-)::16  word  _  _) SUB_flags op1
      else if operand_size op1 = 1  then binop ((-)::8   word  _  _) SUB_flags op1
      else undefined"

abbreviation SUB
  where "SUB op1 op2  Instr ''sub'' (Some op1) (Some op2) None"

definition sbb :: "'b::len word  'a::len word  'a word  'a word"
  where "sbb cf dst src  dst - (src + ucast cf)"

definition SBB_flags :: "'b::len word  'a::len word  'a::len word  string   bool"
  where "SBB_flags cf dst src flag  case flag of
    ''zf''  sbb cf dst src = 0
  | ''cf''  dst < src + ucast cf
  | ''sf''  sbb cf dst src <s 0
  | ''of''  (msb dst  msb (src + ucast cf))  (msb (sbb cf dst src) = msb (src + ucast cf))
  | f       unknown_flags ''SBB'' f"

definition semantics_SBB :: "Operand  Operand  state  state"
  where "semantics_SBB op1 op2 σ  
    let cf = flag_read σ ''cf'' in
           if operand_size op1 = 32 then binop (sbb cf::256 word  _  _) (SBB_flags cf) op1 op2 σ
      else if operand_size op1 = 16 then binop (sbb cf::128 word  _  _) (SBB_flags cf) op1 op2 σ
      else if operand_size op1 = 8  then binop (sbb cf::64  word  _  _) (SBB_flags cf) op1 op2 σ
      else if operand_size op1 = 4  then binop (sbb cf::32  word  _  _) (SBB_flags cf) op1 op2 σ
      else if operand_size op1 = 2  then binop (sbb cf::16  word  _  _) (SBB_flags cf) op1 op2 σ
      else if operand_size op1 = 1  then binop (sbb cf::8   word  _  _) (SBB_flags cf) op1 op2 σ
      else undefined"

abbreviation SBB
  where "SBB op1 op2  Instr ''sbb'' (Some op1) (Some op2) None"

definition adc :: "'b::len word  'a::len word  'a word  'a word"
  where "adc cf dst src  dst + (src + ucast cf)"

definition ADC_flags :: "'b::len word  'a::len word  'a::len word  string   bool"
  where "ADC_flags cf dst src flag  case flag of
    ''zf''  adc cf dst src = 0
  | ''cf''  unat dst + unat src + unat cf  2^(LENGTH('a))
  | ''of''  (dst <s 0  src + ucast cf <s 0)  ¬(dst <s 0  adc cf dst src <s 0)
  | ''sf''  adc cf dst src <s 0
  | f       unknown_flags ''ADC'' f"


definition semantics_ADC :: "Operand  Operand  state  state"
  where "semantics_ADC op1 op2 σ  
    let cf = flag_read σ ''cf'' in
           if operand_size op1 = 32 then binop (adc cf::256 word  _  _) (ADC_flags cf) op1 op2 σ
      else if operand_size op1 = 16 then binop (adc cf::128 word  _  _) (ADC_flags cf) op1 op2 σ
      else if operand_size op1 = 8  then binop (adc cf::64  word  _  _) (ADC_flags cf) op1 op2 σ
      else if operand_size op1 = 4  then binop (adc cf::32  word  _  _) (ADC_flags cf) op1 op2 σ
      else if operand_size op1 = 2  then binop (adc cf::16  word  _  _) (ADC_flags cf) op1 op2 σ
      else if operand_size op1 = 1  then binop (adc cf::8   word  _  _) (ADC_flags cf) op1 op2 σ
      else undefined"

abbreviation ADC
  where "ADC op1 op2  Instr ''adc'' (Some op1) (Some op2) None"


definition write_MUL_result :: "string  string  'a::len word  _  state  state"
  where "write_MUL_result rh rl result flgs σ  
        let si = LENGTH('a) div 2 in
          operand_write (Reg rh) (ucast (si,2*siresult))
            (operand_write (Reg rl) (ucast (0,siresult))
              (σ with [setFlags flgs]))"

definition MUL_flags :: "'a::len word  string  bool"
  where "MUL_flags result flag  case flag of
        ''cf''  (LENGTH('a) div 2,LENGTH('a)result)  0
      | ''of''  (LENGTH('a) div 2,LENGTH('a)result)  0
      | f       unknown_flags ''MUL'' f"


definition IMUL_flags :: "'a::len word  string  bool"
  where "IMUL_flags result flag  case flag of
        ''cf''  (LENGTH('a) div 2,LENGTH('a)result)  (if result !! (LENGTH('a) div 2 - 1) then 2^(LENGTH('a) div 2)-1 else 0)
      | ''of''  (LENGTH('a) div 2,LENGTH('a)result)  (if result !! (LENGTH('a) div 2 - 1) then 2^(LENGTH('a) div 2)-1 else 0)
      | f       unknown_flags ''IMUL'' f"


(*
  Assumes LENGTH('a) is twice the size of the operands, e.g.:
    unop_MUL TYPE(16) True ''al'' (Reg ''r15b'') σ
*)
definition unop_MUL :: "'a::len itself  bool  string  Operand  state  state"
  where "unop_MUL _ signd op1_reg op2 σ 
          let cast = (if signd then scast else ucast);
              dst  = cast (operand_read σ (Reg op1_reg))::'a::len word;
              src  = cast (operand_read σ op2)::'a::len word;
              prod = dst * src;
              flgs = (if signd then IMUL_flags else MUL_flags) prod in
            if LENGTH('a) = 16 then
              write_MUL_result ''ah'' op1_reg prod flgs σ
            else if LENGTH('a) = 32 then
              write_MUL_result ''dx'' op1_reg prod flgs σ
            else if LENGTH('a) = 64 then
              write_MUL_result ''edx'' op1_reg  prod flgs σ
            else if LENGTH('a) = 128 then
              write_MUL_result ''rdx'' op1_reg prod flgs σ
            else
              undefined"

definition semantics_MUL :: "Operand  state  state"
  where "semantics_MUL op2  
           if operand_size op2 = 8 then unop_MUL TYPE(128) False ''rax'' op2
      else if operand_size op2 = 4 then unop_MUL TYPE(64)  False ''eax'' op2
      else if operand_size op2 = 2 then unop_MUL TYPE(32)  False ''ax''  op2
      else if operand_size op2 = 1 then unop_MUL TYPE(16)  False ''al''  op2
      else undefined"

abbreviation MUL
  where "MUL op1  Instr ''mul'' (Some op1) None None"

definition semantics_IMUL1 :: "Operand  state  state"
  where "semantics_IMUL1 op2  
           if operand_size op2 = 8 then unop_MUL TYPE(128) True ''rax'' op2
      else if operand_size op2 = 4 then unop_MUL TYPE(64)  True ''eax'' op2
      else if operand_size op2 = 2 then unop_MUL TYPE(32)  True ''ax''  op2
      else if operand_size op2 = 1 then unop_MUL TYPE(16)  True ''al''  op2
      else undefined"

abbreviation IMUL1
  where "IMUL1 op1  Instr ''imul'' (Some op1) None None"

definition ternop_IMUL :: "'a::len itself  Operand  Operand  Operand  state  state"
  where "ternop_IMUL _ op1 op2 op3 σ 
          let src1 = scast (operand_read σ op2)::'a::len word;
              src2 = scast (operand_read σ op3)::'a::len word;
              prod = src1 * src2;
              flgs = IMUL_flags prod in
            (operand_write op1 (ucast (0,LENGTH('a) div 2prod))
                (σ with [setFlags flgs]))"

definition semantics_IMUL2 :: "Operand  Operand  state  state"
  where "semantics_IMUL2 op1 op2  
           if operand_size op1 = 8 then ternop_IMUL TYPE(128) op1 op1 op2
      else if operand_size op1 = 4 then ternop_IMUL TYPE(64)  op1 op1 op2
      else if operand_size op1 = 2 then ternop_IMUL TYPE(32)  op1 op1 op2
      else if operand_size op1 = 1 then ternop_IMUL TYPE(16)  op1 op1 op2
      else undefined"

abbreviation IMUL2
  where "IMUL2 op1 op2  Instr ''imul'' (Some op1) (Some op2) None"

definition semantics_IMUL3 :: "Operand  Operand  Operand  state  state"
  where "semantics_IMUL3 op1 op2 op3  
           if operand_size op1 = 8 then ternop_IMUL TYPE(128) op1 op2 op3
      else if operand_size op1 = 4 then ternop_IMUL TYPE(64)  op1 op2 op3
      else if operand_size op1 = 2 then ternop_IMUL TYPE(32)  op1 op2 op3
      else if operand_size op1 = 1 then ternop_IMUL TYPE(16)  op1 op2 op3
      else undefined"

abbreviation IMUL3
  where "IMUL3 op1 op2 op3  Instr ''imul'' (Some op1) (Some op2) (Some op3)"

definition SHL_flags :: "nat  ('a::len word  string  bool)"
  where "SHL_flags n dst flag  case flag of
        ''cf''  dst !! (LENGTH('a) - n) 
      | ''of''  dst !! (LENGTH('a) - n - 1)  dst !! (LENGTH('a) - n)
      | ''zf''  (dst << n) = 0
      | ''sf''  dst !! (LENGTH('a) - n - 1)
      | f       unknown_flags ''SHL'' f"

definition semantics_SHL :: "Operand  Operand  state  state" 
  where "semantics_SHL op1 op2 σ  
    let src = unat (operand_read σ op2) in
           if operand_size op1 = 32 then unop (λ w . w << src::256 word) (SHL_flags src) op1 σ
      else if operand_size op1 = 16 then unop (λ w . w << src::128 word) (SHL_flags src) op1 σ
      else if operand_size op1 = 8  then unop (λ w . w << src::64  word) (SHL_flags src) op1 σ
      else if operand_size op1 = 4  then unop (λ w . w << src::32  word) (SHL_flags src) op1 σ
      else if operand_size op1 = 2  then unop (λ w . w << src::16  word) (SHL_flags src) op1 σ
      else if operand_size op1 = 1  then unop (λ w . w << src::8   word) (SHL_flags src) op1 σ
      else undefined"

abbreviation SHL
  where "SHL op1 op2  Instr ''shl'' (Some op1) (Some op2) None"

abbreviation SAL
  where "SAL op1 op2  Instr ''sal'' (Some op1) (Some op2) None"

definition SHR_flags :: "nat  ('a::len word  string  bool)"
  where "SHR_flags n dst flag  case flag of
        ''cf''  dst !! (n - 1) 
      | ''of''  msb dst
      | ''zf''  (dst >> n) = 0
      | f       unknown_flags ''SHR'' f"

definition semantics_SHR :: "Operand  Operand  state  state" 
  where "semantics_SHR op1 op2 σ  
    let src = unat (operand_read σ op2) in
           if operand_size op1 = 32 then unop (λ w . w >> src::256 word) (SHR_flags src) op1 σ
      else if operand_size op1 = 16 then unop (λ w . w >> src::128 word) (SHR_flags src) op1 σ
      else if operand_size op1 = 8  then unop (λ w . w >> src::64  word) (SHR_flags src) op1 σ
      else if operand_size op1 = 4  then unop (λ w . w >> src::32  word) (SHR_flags src) op1 σ
      else if operand_size op1 = 2  then unop (λ w . w >> src::16  word) (SHR_flags src) op1 σ
      else if operand_size op1 = 1  then unop (λ w . w >> src::8   word) (SHR_flags src) op1 σ
      else undefined"

abbreviation SHR
  where "SHR op1 op2  Instr ''shr'' (Some op1) (Some op2) None"

definition SAR_flags :: "nat  ('a::len word  string  bool)"
  where "SAR_flags n dst flag  case flag of
        ''cf''  dst !! (n - 1) 
      | ''of''  False
      | ''zf''  (dst >>> n) = 0
      | f       unknown_flags ''SAR'' f"


definition semantics_SAR :: "Operand  Operand  state  state" 
  where "semantics_SAR op1 op2 σ  
    let src = unat (operand_read σ op2) in
           if operand_size op1 = 32 then unop (λ w . w >>> src::256 word) (SAR_flags src) op1 σ
      else if operand_size op1 = 16 then unop (λ w . w >>> src::128 word) (SAR_flags src) op1 σ
      else if operand_size op1 = 8  then unop (λ w . w >>> src::64  word) (SAR_flags src) op1 σ
      else if operand_size op1 = 4  then unop (λ w . w >>> src::32  word) (SAR_flags src) op1 σ
      else if operand_size op1 = 2  then unop (λ w . w >>> src::16  word) (SAR_flags src) op1 σ
      else if operand_size op1 = 1  then unop (λ w . w >>> src::8   word) (SAR_flags src) op1 σ
      else undefined"

abbreviation SAR
  where "SAR op1 op2  Instr ''sar'' (Some op1) (Some op2) None"


definition shld :: "'b::len itself  nat  'a::len word  'a word  'a word"
  where "shld _ n dst src 
    let dstsrc  = (ucast dst << LENGTH('a)) OR (ucast src :: 'b word);
        shifted = LENGTH('a),LENGTH('a)*2(dstsrc << n) in
      ucast shifted"

definition SHLD_flags :: "'b::len itself  nat  ('a::len word  'a::len word  string  bool)"
  where "SHLD_flags b n src dst flag  case flag of
        ''cf''  dst !! (LENGTH('a) - n) 
      | ''of''  dst !! (LENGTH('a) - n - 1)  dst !! (LENGTH('a) - n)
      | ''zf''  shld b n dst src = 0
      | ''sf''  dst !! (LENGTH('a) - n - 1) ― ‹msb (shld n dst src)›
      | f       unknown_flags ''SHLD'' f"

definition semantics_SHLD :: "Operand  Operand  Operand  state  state"
  where "semantics_SHLD op1 op2 op3 σ  
    let src2 = unat (operand_read σ op3) in
           if operand_size op1 = 32 then binop (shld (TYPE(512)) src2 ::256 word  _  _) (SHLD_flags (TYPE(512)) src2) op1 op2 σ
      else if operand_size op1 = 16 then binop (shld (TYPE(256)) src2 ::128 word  _  _) (SHLD_flags (TYPE(256)) src2) op1 op2 σ
      else if operand_size op1 = 8  then binop (shld (TYPE(128)) src2 ::64  word  _  _) (SHLD_flags (TYPE(128)) src2) op1 op2 σ
      else if operand_size op1 = 4  then binop (shld (TYPE(64))  src2 ::32  word  _  _) (SHLD_flags (TYPE(64))  src2) op1 op2 σ
      else if operand_size op1 = 2  then binop (shld (TYPE(32))  src2 ::16  word  _  _) (SHLD_flags (TYPE(32))  src2) op1 op2 σ
      else if operand_size op1 = 1  then binop (shld (TYPE(16))  src2 ::8   word  _  _) (SHLD_flags (TYPE(16))  src2) op1 op2 σ
      else undefined"



definition ROL_flags :: "nat  ('a::len word  string  bool)" (*TODO check for unaffected flags *)
  where "ROL_flags n dst flag  case flag of
        ''cf''  dst !! (LENGTH('a) - n) 
      | ''of''  dst !! (LENGTH('a) - n - 1)  dst !! (LENGTH('a) - n)
      | f       unknown_flags ''ROL'' f"

definition semantics_ROL :: "Operand  Operand  state  state" 
  where "semantics_ROL op1 op2 σ  
    let src = unat (operand_read σ op2) in
           if operand_size op1 = 32 then unop (word_rotl src::256 word_) (ROL_flags src) op1 σ
      else if operand_size op1 = 16 then unop (word_rotl src::128 word_) (ROL_flags src) op1 σ
      else if operand_size op1 = 8  then unop (word_rotl src::64  word_) (ROL_flags src) op1 σ
      else if operand_size op1 = 4  then unop (word_rotl src::32  word_) (ROL_flags src) op1 σ
      else if operand_size op1 = 2  then unop (word_rotl src::16  word_) (ROL_flags src) op1 σ
      else if operand_size op1 = 1  then unop (word_rotl src::8   word_) (ROL_flags src) op1 σ
      else undefined"

abbreviation ROL
  where "ROL op1 op2  Instr ''rol'' (Some op1) (Some op2) None"

definition ROR_flags :: "nat  ('a::len word  string  bool)"
  where "ROR_flags n dst flag  case flag of
        ''cf''  dst !! (n - 1) 
      | ''of''  msb (word_rotr n dst)  (word_rotr n dst !! (LENGTH('a)-2))
      | f       unknown_flags ''ROR'' f"

definition semantics_ROR :: "Operand  Operand  state  state" 
  where "semantics_ROR op1 op2 σ  
    let src = unat (operand_read σ op2) in
           if operand_size op1 = 32 then unop (word_rotr src::256 word_) (ROR_flags src) op1 σ
      else if operand_size op1 = 16 then unop (word_rotr src::128 word_) (ROR_flags src) op1 σ
      else if operand_size op1 = 8  then unop (word_rotr src::64  word_) (ROR_flags src) op1 σ
      else if operand_size op1 = 4  then unop (word_rotr src::32  word_) (ROR_flags src) op1 σ
      else if operand_size op1 = 2  then unop (word_rotr src::16  word_) (ROR_flags src) op1 σ
      else if operand_size op1 = 1  then unop (word_rotr src::8   word_) (ROR_flags src) op1 σ
      else undefined"

abbreviation ROR
  where "ROR op1 op2  Instr ''ror'' (Some op1) (Some op2) None"

text ‹ flag-related ›

definition semantics_CMP :: "Operand  Operand  state  state"
  where "semantics_CMP op1  
           if operand_size op1 = 32 then binop_flags (SUB_flags::256 word  _  _  _) op1
      else if operand_size op1 = 16 then binop_flags (SUB_flags::128 word  _  _  _) op1
      else if operand_size op1 = 8  then binop_flags (SUB_flags::64  word  _  _  _) op1
      else if operand_size op1 = 4  then binop_flags (SUB_flags::32  word  _  _  _) op1
      else if operand_size op1 = 2  then binop_flags (SUB_flags::16  word  _  _  _) op1
      else if operand_size op1 = 1  then binop_flags (SUB_flags::8   word  _  _  _) op1
      else undefined"

abbreviation CMP
  where "CMP op1 op2  Instr ''cmp'' (Some op1) (Some op2) None"

definition logic_flags :: "('a::len word  'a::len word  'a::len word)  'a::len word  'a::len word  string   bool"
  where "logic_flags logic_op w0 w1 flag  case flag of
    ''zf''  logic_op w0 w1 = 0
  | ''cf''  False
  | ''of''  False
  | ''sf''  msb (logic_op w0 w1)
  | f       unknown_flags ''logic'' f"

definition semantics_TEST :: "Operand  Operand  state  state"
  where "semantics_TEST op1  
           if operand_size op1 = 32 then binop_flags (logic_flags ((AND)::256 word  _  _)) op1
      else if operand_size op1 = 16 then binop_flags (logic_flags ((AND)::128 word  _  _)) op1
      else if operand_size op1 = 8  then binop_flags (logic_flags ((AND)::64  word  _  _)) op1
      else if operand_size op1 = 4  then binop_flags (logic_flags ((AND)::32  word  _  _)) op1
      else if operand_size op1 = 2  then binop_flags (logic_flags ((AND)::16  word  _  _)) op1
      else if operand_size op1 = 1  then binop_flags (logic_flags ((AND)::8   word  _  _)) op1
      else undefined"

abbreviation TEST
  where "TEST op1 op2  Instr ''test'' (Some op1) (Some op2) None"


text ‹ sign extension ›
definition mov_sign_extension :: "('a::len) itself  ('b::len) itself  Operand  Operand  state  state"
  where "mov_sign_extension _ _ op1 op2 σ 
          let src = ucast (operand_read σ op2)::'b word in
             operand_write op1 (ucast (scast src::'a word)) σ"

definition semantics_MOVSXD :: "Operand  Operand  state  state"
  where "semantics_MOVSXD op1 op2 
      if (operand_size op1, operand_size op2) = (8,4) then
         mov_sign_extension (TYPE(64)) (TYPE(32)) op1 op2
      else if (operand_size op1, operand_size op2) = (8,2) then
         mov_sign_extension (TYPE(64)) (TYPE(16)) op1 op2
      else if (operand_size op1, operand_size op2) = (8,1) then
         mov_sign_extension (TYPE(64)) (TYPE(8)) op1 op2
      else if (operand_size op1, operand_size op2) = (4,2) then
         mov_sign_extension (TYPE(32)) (TYPE(16)) op1 op2
      else if (operand_size op1, operand_size op2) = (4,1) then
         mov_sign_extension (TYPE(32)) (TYPE(8)) op1 op2
      else if (operand_size op1, operand_size op2) = (2,1) then
         mov_sign_extension (TYPE(16)) (TYPE(8)) op1 op2
      else
        undefined"

abbreviation MOVSXD
  where "MOVSXD op1 op2  Instr ''movsxd'' (Some op1) (Some op2) None"

abbreviation MOVSX
  where "MOVSX op1 op2  Instr ''movsx'' (Some op1) (Some op2) None"

definition semantics_CDQE :: "state  state"
  where "semantics_CDQE  semantics_MOVSXD (Reg ''rax'') (Reg ''eax'')"

abbreviation CDQE
  where "CDQE  Instr ''cdqe'' None None None"

definition semantics_CDQ :: "state  state"
  where "semantics_CDQ σ 
          let src = ucast (operand_read σ (Reg ''eax'')) :: 32 word in
             operand_write (Reg ''edx'') (ucast (32,64(scast src::64 word))) σ"

abbreviation CDQ
  where "CDQ  Instr ''cdq'' None None None"

definition semantics_CQO :: "state  state"
  where "semantics_CQO σ 
          let src = ucast (operand_read σ (Reg ''rax'')) :: 64 word in
             operand_write (Reg ''rdx'') (ucast (64,128(scast src::128 word))) σ"

abbreviation CQO
  where "CQO  Instr ''cqo'' None None None"


text ‹logic›
definition semantics_AND :: "Operand  Operand  state  state"
  where "semantics_AND op1 op2 σ  
           if operand_size op1 = 32 then binop ((AND)::256 word  _  _) (logic_flags ((AND)::256 word  _  _)) op1 op2 σ
      else if operand_size op1 = 16 then binop ((AND)::128 word  _  _) (logic_flags ((AND)::128 word  _  _)) op1 op2 σ
      else if operand_size op1 = 8  then binop ((AND)::64  word  _  _) (logic_flags ((AND)::64  word  _  _)) op1 op2 σ
      else if operand_size op1 = 4  then binop ((AND)::32  word  _  _) (logic_flags ((AND)::32  word  _  _)) op1 op2 σ
      else if operand_size op1 = 2  then binop ((AND)::16  word  _  _) (logic_flags ((AND)::16  word  _  _)) op1 op2 σ
      else if operand_size op1 = 1  then binop ((AND)::8   word  _  _) (logic_flags ((AND)::8   word  _  _)) op1 op2 σ
      else undefined"

abbreviation AND'
  where "AND' op1 op2  Instr ''and'' (Some op1) (Some op2) None"

definition semantics_OR :: "Operand  Operand  state  state"
  where "semantics_OR op1 op2 σ  
           if operand_size op1 = 32 then binop ((OR)::256 word  _  _) (logic_flags ((OR)::256 word  _  _)) op1 op2 σ
      else if operand_size op1 = 16 then binop ((OR)::128 word  _  _) (logic_flags ((OR)::128 word  _  _)) op1 op2 σ
      else if operand_size op1 = 8  then binop ((OR)::64  word  _  _) (logic_flags ((OR)::64  word  _  _)) op1 op2 σ
      else if operand_size op1 = 4  then binop ((OR)::32  word  _  _) (logic_flags ((OR)::32  word  _  _)) op1 op2 σ
      else if operand_size op1 = 2  then binop ((OR)::16  word  _  _) (logic_flags ((OR)::16  word  _  _)) op1 op2 σ
      else if operand_size op1 = 1  then binop ((OR)::8   word  _  _) (logic_flags ((OR)::8   word  _  _)) op1 op2 σ
      else undefined"

abbreviation OR'
  where "OR' op1 op2  Instr ''or'' (Some op1) (Some op2) None"

definition semantics_XOR :: "Operand  Operand  state  state"
  where "semantics_XOR op1 op2 σ  
           if operand_size op1 = 32 then binop ((XOR)::256 word  _  _) (logic_flags ((XOR)::256 word  _  _)) op1 op2 σ
      else if operand_size op1 = 16 then binop ((XOR)::128 word  _  _) (logic_flags ((XOR)::128 word  _  _)) op1 op2 σ
      else if operand_size op1 = 8  then binop ((XOR)::64  word  _  _) (logic_flags ((XOR)::64  word  _  _)) op1 op2 σ
      else if operand_size op1 = 4  then binop ((XOR)::32  word  _  _) (logic_flags ((XOR)::32  word  _  _)) op1 op2 σ
      else if operand_size op1 = 2  then binop ((XOR)::16  word  _  _) (logic_flags ((XOR)::16  word  _  _)) op1 op2 σ
      else if operand_size op1 = 1  then binop ((XOR)::8   word  _  _) (logic_flags ((XOR)::8   word  _  _)) op1 op2 σ
      else undefined"

abbreviation XOR'
  where "XOR' op1 op2  Instr ''xor'' (Some op1) (Some op2) None"

definition semantics_XORPS :: "Operand  Operand  state  state"
  where "semantics_XORPS op1  
           if operand_size op1 = 32 then binop_no_flags ((XOR)::256 word  _  _) op1
      else if operand_size op1 = 16 then binop_no_flags ((XOR)::128 word  _  _) op1
      else if operand_size op1 = 8  then binop_no_flags ((XOR)::64  word  _  _) op1
      else if operand_size op1 = 4  then binop_no_flags ((XOR)::32  word  _  _) op1
      else if operand_size op1 = 2  then binop_no_flags ((XOR)::16  word  _  _) op1
      else if operand_size op1 = 1  then binop_no_flags ((XOR)::8   word  _  _) op1
      else undefined"

abbreviation XORPS
  where "XORPS op1 op2  Instr ''xorps'' (Some op1) (Some op2) None"

definition semantics_NOT :: "Operand  state  state" 
  where "semantics_NOT op1 σ  
           if operand_size op1 = 32 then unop_no_flags (not::256 word_) op1 σ
      else if operand_size op1 = 16 then unop_no_flags (not::128 word_) op1 σ
      else if operand_size op1 = 8  then unop_no_flags (not::64  word_) op1 σ
      else if operand_size op1 = 4  then unop_no_flags (not::32  word_) op1 σ
      else if operand_size op1 = 2  then unop_no_flags (not::16  word_) op1 σ
      else if operand_size op1 = 1  then unop_no_flags (not::8   word_) op1 σ
      else undefined"

abbreviation NOT'
  where "NOT' op1  Instr ''not'' (Some op1) None None"

text ‹ jumps ›
datatype FlagExpr = Flag string | FE_NOT FlagExpr | FE_AND FlagExpr FlagExpr | FE_OR FlagExpr FlagExpr | FE_EQ FlagExpr FlagExpr

primrec readFlagExpr :: "FlagExpr  state  bool"
  where
    "readFlagExpr (Flag f) σ = (flag_read σ f = 1)"
  | "readFlagExpr (FE_NOT fe) σ = (¬readFlagExpr fe σ)"
  | "readFlagExpr (FE_AND fe0 fe1) σ = (readFlagExpr fe0 σ  readFlagExpr fe1 σ)"
  | "readFlagExpr (FE_OR fe0 fe1) σ = (readFlagExpr fe0 σ  readFlagExpr fe1 σ)"
  | "readFlagExpr (FE_EQ fe0 fe1) σ = (readFlagExpr fe0 σ  readFlagExpr fe1 σ)"

definition semantics_cond_jump :: "FlagExpr  64 word  state  state"
  where "semantics_cond_jump fe a σ 
          let fv = readFlagExpr fe σ in
             if fv then state_update (setRip a) σ else σ"

definition semantics_JMP :: "Operand  state  state"
  where "semantics_JMP op1 σ 
          let a = ucast (operand_read σ op1) in
            state_update (setRip a) σ"

abbreviation JMP
  where "JMP op1  Instr ''jmp'' (Some op1) None None"

definition semantics_JO :: "Operand  state  state"
  where "semantics_JO op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (Flag ''of'') a σ"

abbreviation JO
  where "JO op1  Instr ''jo'' (Some op1) None None"

definition semantics_JNO :: "Operand  state  state"
  where "semantics_JNO op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_NOT (Flag ''of'')) a σ"

abbreviation JNO
  where "JNO op1  Instr ''jno'' (Some op1) None None"

definition semantics_JS :: "Operand  state  state"
  where "semantics_JS op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (Flag ''sf'') a σ"

abbreviation JS
  where "JS op1  Instr ''js'' (Some op1) None None"

definition semantics_JNS :: "Operand  state  state"
  where "semantics_JNS op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_NOT (Flag ''sf'')) a σ"

abbreviation JNS
  where "JNS op1  Instr ''jns'' (Some op1) None None"

definition semantics_JE :: "Operand  state  state"
  where "semantics_JE op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (Flag ''zf'') a σ"

abbreviation JE
  where "JE op1  Instr ''je'' (Some op1) None None"

abbreviation JZ
  where "JZ op1  Instr ''jz'' (Some op1) None None"

definition semantics_JNE :: "Operand  state  state"
  where "semantics_JNE op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_NOT (Flag ''zf'')) a σ"

abbreviation JNE
  where "JNE op1  Instr ''jne'' (Some op1) None None"

abbreviation JNZ
  where "JNZ op1  Instr ''jnz'' (Some op1) None None"

definition semantics_JB :: "Operand  state  state"
  where "semantics_JB op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (Flag ''cf'') a σ"

abbreviation JB
  where "JB op1  Instr ''jb'' (Some op1) None None"

abbreviation JNAE
  where "JNAE op1  Instr ''jnae'' (Some op1) None None"

abbreviation JC
  where "JC op1  Instr ''jc'' (Some op1) None None"

definition semantics_JNB :: "Operand  state  state"
  where "semantics_JNB op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_NOT (Flag ''cf'')) a σ"

abbreviation JNB
  where "JNB op1  Instr ''jnb'' (Some op1) None None"

abbreviation JAE
  where "JAE op1  Instr ''jae'' (Some op1) None None"

abbreviation JNC
  where "JNC op1  Instr ''jnc'' (Some op1) None None"

definition semantics_JBE :: "Operand  state  state"
  where "semantics_JBE op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_OR (Flag ''cf'') (Flag ''zf'')) a σ"

abbreviation JBE
  where "JBE op1  Instr ''jbe'' (Some op1) None None"

abbreviation JNA
  where "JNA op1  Instr ''jna'' (Some op1) None None"

definition semantics_JA :: "Operand  state  state"
  where "semantics_JA op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_AND (FE_NOT (Flag ''cf'')) (FE_NOT (Flag ''zf''))) a σ"

abbreviation JA
  where "JA op1  Instr ''ja'' (Some op1) None None"

abbreviation JNBE
  where "JNBE op1  Instr ''jnbe'' (Some op1) None None"

definition semantics_JL :: "Operand  state  state"
  where "semantics_JL op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_NOT (FE_EQ (Flag ''sf'') (Flag ''of''))) a σ"

abbreviation JL
  where "JL op1  Instr ''jl'' (Some op1) None None"

abbreviation JNGE
  where "JNGE op1  Instr ''jnge'' (Some op1) None None"

definition semantics_JGE :: "Operand  state  state"
  where "semantics_JGE op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_EQ (Flag ''sf'') (Flag ''of'')) a σ"

abbreviation JGE
  where "JGE op1  Instr ''jge'' (Some op1) None None"

abbreviation JNL
  where "JNL op1  Instr ''jnl'' (Some op1) None None"

definition semantics_JLE :: "Operand  state  state"
  where "semantics_JLE op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_OR (Flag ''zf'') (FE_NOT (FE_EQ (Flag ''sf'') (Flag ''of'')))) a σ"

abbreviation JLE
  where "JLE op1  Instr ''jle'' (Some op1) None None"

abbreviation JNG
  where "JNG op1  Instr ''jng'' (Some op1) None None"

definition semantics_JG :: "Operand  state  state"
  where "semantics_JG op1 σ 
          let a = ucast (operand_read σ op1) in
             semantics_cond_jump (FE_AND (FE_NOT (Flag ''zf'')) (FE_EQ (Flag ''sf'') (Flag ''of''))) a σ"

abbreviation JG
  where "JG op1  Instr ''jg'' (Some op1) None None"

abbreviation JNLE
  where "JNLE op1  Instr ''jnle'' (Some op1) None None"


text ‹ setXX ›
definition semantics_setXX :: "FlagExpr  Operand  state  state"
  where "semantics_setXX fe op1 σ 
          let fv = readFlagExpr fe σ in
             operand_write op1 (fromBool fv) σ"

abbreviation semantics_SETO :: "Operand  state  state"
  where "semantics_SETO  semantics_setXX (Flag ''of'')"

abbreviation SETO
  where "SETO op1  Instr ''seto'' (Some op1) None None"

abbreviation semantics_SETNO :: "Operand  state  state"
  where "semantics_SETNO  semantics_setXX (FE_NOT (Flag ''of''))"

abbreviation SETNO
  where "SETNO op1  Instr ''setno'' (Some op1) None None"

abbreviation semantics_SETS :: "Operand  state  state"
  where "semantics_SETS  semantics_setXX (Flag ''sf'')"

abbreviation SETS
  where "SETS op1  Instr ''sets'' (Some op1) None None"

abbreviation semantics_SETNS :: "Operand  state  state"
  where "semantics_SETNS  semantics_setXX (FE_NOT (Flag ''sf''))"

abbreviation SETNS
  where "SETNS op1  Instr ''setns'' (Some op1) None None"

abbreviation semantics_SETE :: "Operand  state  state"
  where "semantics_SETE  semantics_setXX (Flag ''zf'')"

abbreviation SETE
  where "SETE op1  Instr ''sete'' (Some op1) None None"

abbreviation SETZ
  where "SETZ op1  Instr ''setz'' (Some op1) None None"

abbreviation semantics_SETNE :: "Operand  state  state"
  where "semantics_SETNE  semantics_setXX (FE_NOT (Flag ''zf''))"

abbreviation SETNE
  where "SETNE op1  Instr ''setne'' (Some op1) None None"

abbreviation SETNZ
  where "SETNZ op1  Instr ''setnz'' (Some op1) None None"

abbreviation semantics_SETB :: "Operand  state  state"
  where "semantics_SETB  semantics_setXX (Flag ''cf'')"

abbreviation SETB
  where "SETB op1  Instr ''setb'' (Some op1) None None"

abbreviation SETNAE
  where "SETNAE op1  Instr ''setnae'' (Some op1) None None"

abbreviation SETC
  where "SETC op1  Instr ''setc'' (Some op1) None None"

abbreviation semantics_SETNB :: "Operand  state  state"
  where "semantics_SETNB  semantics_setXX (FE_NOT (Flag ''cf''))"

abbreviation SETNB
  where "SETNB op1  Instr ''setnb'' (Some op1) None None"

abbreviation SETAE
  where "SETAE op1  Instr ''setae'' (Some op1) None None"

abbreviation SETNC
  where "SETNC op1  Instr ''setnc'' (Some op1) None None"

abbreviation semantics_SETBE :: "Operand  state  state"
  where "semantics_SETBE  semantics_setXX (FE_OR (Flag ''cf'') (Flag ''zf''))"

abbreviation SETBE
  where "SETBE op1  Instr ''setbe'' (Some op1) None None"

abbreviation SETNA
  where "SETNA op1  Instr ''setna'' (Some op1) None None"

abbreviation semantics_SETA :: "Operand  state  state"
  where "semantics_SETA  semantics_setXX (FE_AND (FE_NOT (Flag ''cf'')) (FE_NOT (Flag ''zf'')))"

abbreviation SETA
  where "SETA op1  Instr ''seta'' (Some op1) None None"

abbreviation SETNBE
  where "SETNBE op1  Instr ''setnbe'' (Some op1) None None"

abbreviation semantics_SETL :: "Operand  state  state"
  where "semantics_SETL  semantics_setXX (FE_NOT (FE_EQ (Flag ''sf'') (Flag ''of'')))"

abbreviation SETL
  where "SETL op1  Instr ''setl'' (Some op1) None None"

abbreviation SETNGE
  where "SETNGE op1  Instr ''setnge'' (Some op1) None None"

abbreviation semantics_SETGE :: "Operand  state  state"
  where "semantics_SETGE  semantics_setXX (FE_EQ (Flag ''sf'') (Flag ''of''))"

abbreviation SETGE
  where "SETGE op1  Instr ''setge'' (Some op1) None None"

abbreviation SETNL
  where "SETNL op1  Instr ''setnl'' (Some op1) None None"

abbreviation semantics_SETLE :: "Operand  state  state"
  where "semantics_SETLE  semantics_setXX (FE_OR (Flag ''zf'') (FE_NOT (FE_EQ (Flag ''sf'') (Flag ''of''))))"

abbreviation SETLE
  where "SETLE op1  Instr ''setle'' (Some op1) None None"

abbreviation SETNG
  where "SETNG op1  Instr ''setng'' (Some op1) None None"

abbreviation semantics_SETG :: "Operand  state  state"
  where "semantics_SETG  semantics_setXX (FE_AND (FE_NOT (Flag ''zf'')) (FE_EQ (Flag ''sf'') (Flag ''of'')))"

abbreviation SETG
  where "SETG op1  Instr ''setg'' (Some op1) None None"

abbreviation SETNLE
  where "SETNLE op1  Instr ''setnle'' (Some op1) None None"


text ‹ conditional moves ›

primrec cmov
  where 
    "cmov True dst src = src"
  | "cmov False dst src = dst"

definition semantics_CMOV :: "FlagExpr  Operand  Operand  state  state"
  where "semantics_CMOV fe op1 op2 σ 
          let fv = readFlagExpr fe σ;
              dst = operand_read σ op1;
              src = operand_read σ op2 in
            operand_write op1 (cmov fv dst src) σ"

abbreviation "semantics_CMOVNE  semantics_CMOV (FE_NOT (Flag ''zf''))"

abbreviation CMOVNE
  where "CMOVNE op1 op2  Instr ''movne'' (Some op1) (Some op2) None"

abbreviation "semantics_CMOVNS  semantics_CMOV (FE_NOT (Flag ''sf''))"

abbreviation CMOVNS
  where "CMOVNS op1 op2  Instr ''movns'' (Some op1) (Some op2) None"


text ‹Floating Point›
definition semantics_ADDSD :: "Operand  Operand  state  state"
  where "semantics_ADDSD  binop_XMM unknown_addsd"

definition semantics_SUBSD :: "Operand  Operand  state  state"
  where "semantics_SUBSD  binop_XMM unknown_subsd"

definition semantics_MULSD :: "Operand  Operand  state  state"
  where "semantics_MULSD  binop_XMM unknown_mulsd"

definition semantics_DIVSD :: "Operand  Operand  state  state"
  where "semantics_DIVSD  binop_XMM unknown_divsd"

definition UCOMISD_flags :: "64 word  64 word  string  bool"
  where "UCOMISD_flags w0 w1 f  
  if f  {''zf'',''pf'',''cf''} then case unknown_ucomisd w0 w1 of
      FP_Unordered  True
    | FP_GT         False
    | FP_LT         f = ''cf''
    | FP_EQ         f = ''zf''
  else
    unknown_flags ''UCOMISD'' f"

definition semantics_UCOMISD :: "Operand  Operand  state  state"
  where "semantics_UCOMISD  binop_flags UCOMISD_flags"


abbreviation ADDSD
  where "ADDSD op1 op2  Instr ''addsd'' (Some op1) (Some op2) None"

abbreviation SUBSD
  where "SUBSD op1 op2  Instr ''subsd'' (Some op1) (Some op2) None"

abbreviation MULSD
  where "MULSD op1 op2  Instr ''mulsd'' (Some op1) (Some op2) None"

abbreviation DIVSD
  where "DIVSD op1 op2  Instr ''divsd'' (Some op1) (Some op2) None"

abbreviation UCOMISD
  where "UCOMISD op1 op2  Instr ''ucomisd'' (Some op1) (Some op2) None"



(* SIMD *)

definition simd_32_128 :: "(32 word  32 word  32 word)  128 word  128 word  128 word" 
  where "simd_32_128 f dst src  
            ((ucast (0,32(f (ucast (96,128dst)) (ucast (96,128src))))) << 96) OR
            ((ucast (0,32(f (ucast (64,96dst))  (ucast (64,96src))))) << 64)  OR
            ((ucast (0,32(f (ucast (32,64dst))  (ucast (32,64src))))) << 32)  OR
             (ucast (0,32(f (ucast (0,32dst))   (ucast (0,32src)))))"

abbreviation semantics_PADDD :: "Operand  Operand  state  state"
  where "semantics_PADDD  binop_no_flags (simd_32_128 (+))"

abbreviation PADDD
  where "PADDD op1 op2  Instr ''paddd'' (Some op1) (Some op2) None"

definition pshufd :: "128 word  8 word  128 word"
  where "pshufd src n  ((0,32(src >> (unat (6,8n)*32))) << 96) OR
                        ((0,32(src >> (unat (4,6n)*32))) << 64) OR
                        ((0,32(src >> (unat (2,4n)*32))) << 32) OR
                        ((0,32(src >> (unat (0,2n)*32))))"

lemmas pshufd_numeral[simp] = pshufd_def[of "numeral n"] for n
lemmas pshufd_0[simp] = pshufd_def[of 0]
lemmas pshufd_1[simp] = pshufd_def[of 1]

definition semantics_PSHUFD :: "Operand  Operand  Operand  state  state"
  where "semantics_PSHUFD op1 op2 op3 σ  
    let src = ucast (operand_read σ op2);
        n   = ucast (operand_read σ op3) in
      operand_write op1 (ucast (pshufd src n)) σ"

abbreviation PSHUFD
  where "PSHUFD op1 op2 op3  Instr ''pshufd'' op1 op2 op3"

definition semantics_PEXTRD :: "Operand  Operand  Operand  state  state"
  where "semantics_PEXTRD op1 op2 op3 σ 
          let src = operand_read σ op2;
              n   = unat (operand_read σ op3) mod 4 in
             operand_write op1 (ucast ((0,32(src >> n*32)))) σ"

abbreviation PEXTRD
  where "PEXTRD op1 op2 op3  Instr ''pextrd'' op1 op2 op3"

definition semantics_PINSRD :: "Operand  Operand  Operand  state  state"
  where "semantics_PINSRD op1 op2 op3 σ 
          let dst = ucast (operand_read σ op1)::128 word;
              src = ucast (operand_read σ op2)::128 word;
              n   = unat (operand_read σ op3) mod 4;
              m   = 0xFFFFFFFF << (n * 32) :: 128 word;
              t   = (src << (n *32)) AND m in
             operand_write op1 (ucast ((dst AND NOT m) OR t)) σ"

abbreviation PINSRD
  where "PINSRD op1 op2 op3  Instr ''pinsrd'' op1 op2 op3"


(* remainder *)



definition bswap :: "32 word  32 word"
  where "bswap w  ((0,8w) << 24) OR ((8,16w) << 16) OR ((16,24w) << 8) OR (24,32w)"

lemmas bswap_numeral[simp] = bswap_def[of "numeral n"] for n
lemmas bswap_0[simp] = bswap_def[of 0]
lemmas bswap_1[simp] = bswap_def[of 1]

definition semantics_BSWAP :: "Operand  state  state"
  where "semantics_BSWAP  unop_no_flags bswap"

abbreviation BSWAP
  where "BSWAP op1  Instr ''bswap'' op1 None None"



definition semantics_NOP :: "state  state"
  where "semantics_NOP  id"

abbreviation NOP0
  where "NOP0  Instr ''nop'' None None None"

abbreviation NOP1
  where "NOP1 op1  Instr ''nop'' (Some op1) None None"

abbreviation NOP2
  where "NOP2 op1 op2  Instr ''nop'' (Some op1) (Some op2) None"

abbreviation NOP3
  where "NOP3 op1 op2 op3  Instr ''nop'' (Some op1) (Some op2) (Some op3)"



definition semantics
  where "semantics i 
  case i of
    (Instr ''mov''     (Some op1) (Some op2) _ _)           semantics_MOV op1 op2
  | (Instr ''movabs''  (Some op1) (Some op2) _ _)           semantics_MOV op1 op2
  | (Instr ''movaps''  (Some op1) (Some op2) _ _)           semantics_MOV op1 op2
  | (Instr ''movdqu''  (Some op1) (Some op2) _ _)           semantics_MOV op1 op2
  | (Instr ''movd''    (Some op1) (Some op2) _ _)           semantics_MOVD op1 op2
  | (Instr ''movzx''   (Some op1) (Some op2) _ _)           semantics_MOV op1 op2
  | (Instr ''movsd''   (Some op1) (Some op2) _ _)           semantics_MOVSD op1 op2
  | (Instr ''movq''    (Some op1) (Some op2) _ _)           semantics_MOVSD op1 op2
  | (Instr ''lea''     (Some op1) (Some op2) _ _)           semantics_LEA op1 op2
  | (Instr ''push''    (Some op1) _          _ _)           semantics_PUSH op1
  | (Instr ''pop''     (Some op1) _          _ _)           semantics_POP op1
  | (Instr ''ret''     _ _ _ _)                             semantics_RET
  | (Instr ''call''    (Some op1) _ _ _)                    semantics_CALL op1
  | (Instr ''leave''   _ _ _ _)                             semantics_LEAVE
  ― ‹arithmetic›                                           
  | (Instr ''add''     (Some op1) (Some op2)  _ _)          semantics_ADD op1 op2
  | (Instr ''inc''     (Some op1) _           _ _)          semantics_INC op1
  | (Instr ''dec''     (Some op1) _           _ _)          semantics_DEC op1
  | (Instr ''neg''     (Some op1) _           _ _)          semantics_NEG op1
  | (Instr ''sub''     (Some op1) (Some op2)  _ _)          semantics_SUB op1 op2
  | (Instr ''sbb''     (Some op1) (Some op2)  _ _)          semantics_SBB op1 op2
  | (Instr ''adc''     (Some op1) (Some op2)  _ _)          semantics_ADC op1 op2
  | (Instr ''mul''     (Some op1) _ _ _)                    semantics_MUL op1 
  | (Instr ''imul''    (Some op1) None _ _)                 semantics_IMUL1 op1 
  | (Instr ''imul''    (Some op1) (Some op2) None _)        semantics_IMUL2 op1 op2
  | (Instr ''imul''    (Some op1) (Some op2) (Some op3) _)  semantics_IMUL3 op1 op2 op3
  | (Instr ''shl''     (Some op1) (Some op2) None _)        semantics_SHL op1 op2
  | (Instr ''sal''     (Some op1) (Some op2) None _)        semantics_SHL op1 op2
  | (Instr ''shr''     (Some op1) (Some op2) None _)        semantics_SHR op1 op2
  | (Instr ''sar''     (Some op1) (Some op2) None _)        semantics_SAR op1 op2
  | (Instr ''shld''    (Some op1) (Some op2) (Some op3) _)  semantics_SHLD op1 op2 op3
  | (Instr ''rol''     (Some op1) (Some op2) None _)        semantics_ROL op1 op2
  | (Instr ''ror''     (Some op1) (Some op2) None _)        semantics_ROR op1 op2
  ― ‹flag-related›
  | (Instr ''cmp''     (Some op1) (Some op2)  _ _)          semantics_CMP op1 op2
  | (Instr ''test''    (Some op1) (Some op2)  _ _)          semantics_TEST op1 op2
  ― ‹sign-extension›                                       
  | (Instr ''movsxd''  (Some op1) (Some op2)  _ _)          semantics_MOVSXD op1 op2
  | (Instr ''movsx''   (Some op1) (Some op2)  _ _)          semantics_MOVSXD op1 op2
  | (Instr ''cdqe''    (Some op1) (Some op2)  _ _)          semantics_CDQE
  | (Instr ''cdq''     (Some op1) (Some op2)  _ _)          semantics_CDQ
  | (Instr ''cqo''     (Some op1) (Some op2)  _ _)          semantics_CQO
  ― ‹logic›
  | (Instr ''and''     (Some op1) (Some op2)  _ _)          semantics_AND op1 op2
  | (Instr ''or''      (Some op1) (Some op2)  _ _)          semantics_OR  op1 op2
  | (Instr ''xor''     (Some op1) (Some op2)  _ _)          semantics_XOR op1 op2
  | (Instr ''xorps''   (Some op1) (Some op2)  _ _)          semantics_XORPS op1 op2
  | (Instr ''not''     (Some op1) _  _ _)                   semantics_NOT op1
  ― ‹jumps›
  | (Instr ''jmp''     (Some op1) None  _ _)                semantics_JMP op1
  | (Instr ''jo''      (Some op1) None  _ _)                semantics_JO op1
  | (Instr ''jno''     (Some op1) None  _ _)                semantics_JNO op1
  | (Instr ''js''      (Some op1) None  _ _)                semantics_JS op1
  | (Instr ''jns''     (Some op1) None  _ _)                semantics_JNS op1
  | (Instr ''je''      (Some op1) None  _ _)                semantics_JE op1
  | (Instr ''jz''      (Some op1) None  _ _)                semantics_JE op1
  | (Instr ''jne''     (Some op1) None  _ _)                semantics_JNE op1
  | (Instr ''jnz''     (Some op1) None  _ _)                semantics_JNE op1
  | (Instr ''jb''      (Some op1) None  _ _)                semantics_JB op1
  | (Instr ''jnae''    (Some op1) None  _ _)                semantics_JB op1
  | (Instr ''jc''      (Some op1) None  _ _)                semantics_JB op1
  | (Instr ''jnb''     (Some op1) None  _ _)                semantics_JNB op1
  | (Instr ''jae''     (Some op1) None  _ _)                semantics_JNB op1
  | (Instr ''jnc''     (Some op1) None  _ _)                semantics_JNB op1
  | (Instr ''jbe''     (Some op1) None  _ _)                semantics_JBE op1
  | (Instr ''jna''     (Some op1) None  _ _)                semantics_JBE op1
  | (Instr ''ja''      (Some op1) None  _ _)                semantics_JA op1
  | (Instr ''jnbe''    (Some op1) None  _ _)                semantics_JA op1
  | (Instr ''jl''      (Some op1) None  _ _)                semantics_JL op1
  | (Instr ''jnge''    (Some op1) None  _ _)                semantics_JL op1
  | (Instr ''jge''     (Some op1) None  _ _)                semantics_JGE op1
  | (Instr ''jnl''     (Some op1) None  _ _)                semantics_JGE op1
  | (Instr ''jle''     (Some op1) None  _ _)                semantics_JLE op1
  | (Instr ''jng''     (Some op1) None  _ _)                semantics_JLE op1
  | (Instr ''jg''      (Some op1) None  _ _)                semantics_JG op1
  | (Instr ''jnle''    (Some op1) None  _ _)                semantics_JG op1
  ― ‹setXX›
  | (Instr ''seto''    (Some op1) None  _ _)                semantics_SETO op1
  | (Instr ''setno''   (Some op1) None  _ _)                semantics_SETNO op1
  | (Instr ''sets''    (Some op1) None  _ _)                semantics_SETS op1
  | (Instr ''setns''   (Some op1) None  _ _)                semantics_SETNS op1
  | (Instr ''sete''    (Some op1) None  _ _)                semantics_SETE op1
  | (Instr ''setz''    (Some op1) None  _ _)                semantics_SETE op1
  | (Instr ''setne''   (Some op1) None  _ _)                semantics_SETNE op1
  | (Instr ''setnz''   (Some op1) None  _ _)                semantics_SETNE op1
  | (Instr ''setb''    (Some op1) None  _ _)                semantics_SETB op1
  | (Instr ''setnae''  (Some op1) None  _ _)                semantics_SETB op1
  | (Instr ''setc''    (Some op1) None  _ _)                semantics_SETB op1
  | (Instr ''setnb''   (Some op1) None  _ _)                semantics_SETNB op1
  | (Instr ''setae''   (Some op1) None  _ _)                semantics_SETNB op1
  | (Instr ''setnc''   (Some op1) None  _ _)                semantics_SETNB op1
  | (Instr ''setbe''   (Some op1) None  _ _)                semantics_SETBE op1
  | (Instr ''setna''   (Some op1) None  _ _)                semantics_SETBE op1
  | (Instr ''seta''    (Some op1) None  _ _)                semantics_SETA op1
  | (Instr ''setnbe''  (Some op1) None  _ _)                semantics_SETA op1
  | (Instr ''setl''    (Some op1) None  _ _)                semantics_SETL op1
  | (Instr ''setnge''  (Some op1) None  _ _)                semantics_SETL op1
  | (Instr ''setge''   (Some op1) None  _ _)                semantics_SETGE op1
  | (Instr ''setnl''   (Some op1) None  _ _)                semantics_SETGE op1
  | (Instr ''setle''   (Some op1) None  _ _)                semantics_SETLE op1
  | (Instr ''setng''   (Some op1) None  _ _)                semantics_SETLE op1
  | (Instr ''setg''    (Some op1) None  _ _)                semantics_SETG op1
  | (Instr ''setnle''  (Some op1) None  _ _)                semantics_SETG op1
  ― ‹conditional moves›
  | (Instr ''cmovne''  (Some op1) (Some op2)  _ _)          semantics_CMOVNE op1 op2
  | (Instr ''cmovns''  (Some op1) (Some op2)  _ _)          semantics_CMOVNS op1 op2
  ― ‹floating point (double)›                                           
  | (Instr ''addsd''   (Some op1) (Some op2)  _ _)          semantics_ADDSD op1 op2
  | (Instr ''subsd''   (Some op1) (Some op2)  _ _)          semantics_SUBSD op1 op2
  | (Instr ''mulsd''   (Some op1) (Some op2)  _ _)          semantics_MULSD op1 op2
  | (Instr ''divsd''   (Some op1) (Some op2)  _ _)          semantics_DIVSD op1 op2
  | (Instr ''ucomisd'' (Some op1) (Some op2)  _ _)          semantics_UCOMISD op1 op2
  ― ‹simd›
  | (Instr ''paddd''   (Some op1) (Some op2) _ _)           semantics_PADDD op1 op2
  | (Instr ''pshufd''  (Some op1) (Some op2) (Some op3) _)  semantics_PSHUFD op1 op2 op3
  | (Instr ''pextrd''  (Some op1) (Some op2) (Some op3) _)  semantics_PEXTRD op1 op2 op3
  | (Instr ''pinsrd''  (Some op1) (Some op2) (Some op3) _)  semantics_PINSRD op1 op2 op3
  ― ‹remainder›
  | (Instr ''nop''     _ _ _ _)                             semantics_NOP
  | (Instr ''bswap''   (Some op1) _ _ _)                    semantics_BSWAP op1
  ― ‹external function›
  | (ExternalFunc f)  f
  | i  unknown_semantics i"


text ‹A step function. In X86. the RIP register is incremented before the instruction is executed.
      This is important, e.g., when RIP is used in a jump address.›
definition step :: "I  state  state" 
  where "step i σ  
    let σ' = σ with [setRip (instr_next i)] in
      semantics i σ'"


text ‹All simplification rules used during symbolic execution.›
lemmas semantics_simps = 
      Let_def unop_def unop_no_flags_def binop_def binop_flags_def binop_no_flags_def binop_XMM_def
      semantics_def mov_sign_extension_def simd_32_128_def
      write_MUL_result_def unop_MUL_def ternop_IMUL_def sbb_def adc_def shld_def

      semantics_MOV_def semantics_MOVSD_def semantics_MOVD_def semantics_CMOV_def
      semantics_LEA_def semantics_PUSH_def semantics_POP_def
      semantics_RET_def semantics_CALL_def semantics_LEAVE_def
      semantics_ADD_def semantics_INC_def semantics_DEC_def semantics_NEG_def semantics_SUB_def
      semantics_SBB_def semantics_ADC_def
      semantics_MUL_def semantics_IMUL1_def semantics_IMUL2_def semantics_IMUL3_def
      semantics_SHL_def semantics_SHR_def semantics_SAR_def semantics_SHLD_def
      semantics_ROL_def semantics_ROR_def
      semantics_CMP_def semantics_TEST_def
      semantics_MOVSXD_def semantics_CDQE_def semantics_CDQ_def semantics_CQO_def
      semantics_AND_def semantics_OR_def semantics_XOR_def semantics_XORPS_def semantics_NOT_def
      semantics_cond_jump_def semantics_JMP_def
      semantics_JO_def semantics_JNO_def semantics_JS_def semantics_JNS_def
      semantics_JE_def semantics_JNE_def semantics_JB_def semantics_JNB_def
      semantics_JBE_def semantics_JA_def semantics_JL_def semantics_JGE_def 
      semantics_JLE_def semantics_JG_def
      semantics_setXX_def 
      semantics_ADDSD_def semantics_SUBSD_def semantics_MULSD_def semantics_DIVSD_def semantics_UCOMISD_def
      semantics_NOP_def semantics_BSWAP_def semantics_PSHUFD_def semantics_PEXTRD_def semantics_PINSRD_def

      SUB_flags_def ADD_flags_def INC_flags_def DEC_flags_def NEG_flags_def MUL_flags_def IMUL_flags_def
      SHL_flags_def SHR_flags_def SAR_flags_def SHLD_flags_def logic_flags_def UCOMISD_flags_def


end
end