include "ASM/ASM.ma". include "ASM/BitVectorTrie.ma". include "ASM/Arithmetic.ma". include "ASM/Fetch.ma". include "ASM/Status.ma". definition assembly_preinstruction ≝ λA: Type[0]. λaddr_of: A → Byte. (* relative *) λpre: preinstruction A. match pre with [ ADD addr1 addr2 ⇒ match addr2 return λx. bool_to_Prop (is_in ? [[registr;direct;indirect;data]] x) → ? with [ REGISTER r ⇒ λ_.[ ([[false;false;true;false;true]]) @@ r ] | DIRECT b1 ⇒ λ_.[ ([[false;false;true;false;false;true;false;true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[false;false;true;false;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[false;false;true;false;false;true;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | ADDC addr1 addr2 ⇒ match addr2 return λx. bool_to_Prop (is_in ? [[registr;direct;indirect;data]] x) → ? with [ REGISTER r ⇒ λ_.[ ([[false;false;true;true;true]]) @@ r ] | DIRECT b1 ⇒ λ_.[ ([[false;false;true;true;false;true;false;true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[false;false;true;true;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[false;false;true;true;false;true;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | ANL addrs ⇒ match addrs with [ inl addrs ⇒ match addrs with [ inl addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[registr;direct;indirect;data]] x) → ? with [ REGISTER r ⇒ λ_.[ ([[false;true;false;true;true]]) @@ r ] | DIRECT b1 ⇒ λ_.[ ([[false;true;false;true;false;true;false;true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[false;true;false;true;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[false;true;false;true;false;true;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in let b1 ≝ match addr1 return λx. bool_to_Prop (is_in ? [[direct]] x) → ? with [ DIRECT b1 ⇒ λ_.b1 | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) in match addr2 return λx. bool_to_Prop (is_in ? [[acc_a;data]] x) → ? with [ ACC_A ⇒ λ_.[ ([[false;true;false;true;false;false;true;false]]) ; b1 ] | DATA b2 ⇒ λ_. [ ([[false;true;false;true;false;false;true;true]]) ; b1 ; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) ] | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[bit_addr;n_bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_.[ ([[true;false;false;false;false;false;true;false]]) ; b1 ] | N_BIT_ADDR b1 ⇒ λ_. [ ([[true;false;true;true;false;false;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] | CLR addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[acc_a;carry;bit_addr]] x) → ? with [ ACC_A ⇒ λ_. [ ([[true; true; true; false; false; true; false; false]]) ] | CARRY ⇒ λ_. [ ([[true; true; false; false; false; false; true; true]]) ] | BIT_ADDR b1 ⇒ λ_. [ ([[true; true; false; false; false; false; true; false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | CPL addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[acc_a;carry;bit_addr]] x) → ? with [ ACC_A ⇒ λ_. [ ([[true; true; true; true; false; true; false; false]]) ] | CARRY ⇒ λ_. [ ([[true; false; true; true; false; false; true; true]]) ] | BIT_ADDR b1 ⇒ λ_. [ ([[true; false; true; true; false; false; true; false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | DA addr ⇒ [ ([[true; true; false; true; false; true; false; false]]) ] | DEC addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[acc_a;registr;direct;indirect]] x) → ? with [ ACC_A ⇒ λ_. [ ([[false; false; false; true; false; true; false; false]]) ] | REGISTER r ⇒ λ_. [ ([[false; false; false; true; true]]) @@ r ] | DIRECT b1 ⇒ λ_. [ ([[false; false; false; true; false; true; false; true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[false; false; false; true; false; true; true; i1]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | DJNZ addr1 addr2 ⇒ let b2 ≝ addr_of addr2 in match addr1 return λx. bool_to_Prop (is_in ? [[registr;direct]] x) → ? with [ REGISTER r ⇒ λ_. [ ([[true; true; false; true; true]]) @@ r ; b2 ] | DIRECT b1 ⇒ λ_. [ ([[true; true; false; true; false; true; false; true]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) | JC addr ⇒ let b1 ≝ addr_of addr in [ ([[false; true; false; false; false; false; false; false]]); b1 ] | JNC addr ⇒ let b1 ≝ addr_of addr in [ ([[false; true; false; true; false; false; false; false]]); b1 ] | JZ addr ⇒ let b1 ≝ addr_of addr in [ ([[false; true; true; false; false; false; false; false]]); b1 ] | JNZ addr ⇒ let b1 ≝ addr_of addr in [ ([[false; true; true; true; false; false; false; false]]); b1 ] | JB addr1 addr2 ⇒ let b2 ≝ addr_of addr2 in match addr1 return λx. bool_to_Prop (is_in ? [[bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_. [ ([[false; false; true; false; false; false; false; false]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) | JNB addr1 addr2 ⇒ let b2 ≝ addr_of addr2 in match addr1 return λx. bool_to_Prop (is_in ? [[bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_. [ ([[false; false; true; true; false; false; false; false]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) | JBC addr1 addr2 ⇒ let b2 ≝ addr_of addr2 in match addr1 return λx. bool_to_Prop (is_in ? [[bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_. [ ([[false; false; false; true; false; false; false; false]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) | CJNE addrs addr3 ⇒ let b3 ≝ addr_of addr3 in match addrs with [ inl addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[direct;data]] x) → ? with [ DIRECT b1 ⇒ λ_. [ ([[true; false; true; true; false; true; false; true]]); b1; b3 ] | DATA b1 ⇒ λ_. [ ([[true; false; true; true; false; true; false; false]]); b1; b3 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in let b2 ≝ match addr2 return λx. bool_to_Prop (is_in ? [[data]] x) → ? with [ DATA b2 ⇒ λ_. b2 | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) in match addr1 return λx. bool_to_Prop (is_in ? [[registr;indirect]] x) → list Byte with [ REGISTER r ⇒ λ_. [ ([[true; false; true; true; true]]) @@ r; b2; b3 ] | INDIRECT i1 ⇒ λ_. [ ([[true; false; true; true; false; true; true; i1]]); b2; b3 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) ] | DIV addr1 addr2 ⇒ [ ([[true;false;false;false;false;true;false;false]]) ] | INC addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[acc_a;registr;direct;indirect;dptr]] x) → ? with [ ACC_A ⇒ λ_. [ ([[false;false;false;false;false;true;false;false]]) ] | REGISTER r ⇒ λ_. [ ([[false;false;false;false;true]]) @@ r ] | DIRECT b1 ⇒ λ_. [ ([[false; false; false; false; false; true; false; true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[false; false; false; false; false; true; true; i1]]) ] | DPTR ⇒ λ_. [ ([[true;false;true;false;false;false;true;true]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | MOV addrs ⇒ match addrs with [ inl addrs ⇒ match addrs with [ inl addrs ⇒ match addrs with [ inl addrs ⇒ match addrs with [ inl addrs ⇒ match addrs with [ inl addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[registr;direct;indirect;data]] x) → ? with [ REGISTER r ⇒ λ_.[ ([[true;true;true;false;true]]) @@ r ] | DIRECT b1 ⇒ λ_.[ ([[true;true;true;false;false;true;false;true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[true;true;true;false;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[false;true;true;true;false;true;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr1 return λx. bool_to_Prop (is_in ? [[registr;indirect]] x) → ? with [ REGISTER r ⇒ λ_. match addr2 return λx. bool_to_Prop (is_in ? [[acc_a;direct;data]] x) → ? with [ ACC_A ⇒ λ_.[ ([[true;true;true;true;true]]) @@ r ] | DIRECT b1 ⇒ λ_.[ ([[true;false;true;false;true]]) @@ r; b1 ] | DATA b1 ⇒ λ_. [ ([[false;true;true;true;true]]) @@ r; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | INDIRECT i1 ⇒ λ_. match addr2 return λx. bool_to_Prop (is_in ? [[acc_a;direct;data]] x) → ? with [ ACC_A ⇒ λ_.[ ([[true;true;true;true;false;true;true;i1]]) ] | DIRECT b1 ⇒ λ_.[ ([[true;false;true;false;false;true;true;i1]]); b1 ] | DATA b1 ⇒ λ_. [ ([[false;true;true;true;false;true;true;i1]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1)] | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in let b1 ≝ match addr1 return λx. bool_to_Prop (is_in ? [[direct]] x) → ? with [ DIRECT b1 ⇒ λ_. b1 | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) in match addr2 return λx. bool_to_Prop (is_in ? [[acc_a;registr;direct;indirect;data]] x) → ? with [ ACC_A ⇒ λ_.[ ([[true;true;true;true;false;true;false;true]]); b1] | REGISTER r ⇒ λ_.[ ([[true;false;false;false;true]]) @@ r; b1 ] | DIRECT b2 ⇒ λ_.[ ([[true;false;false;false;false;true;false;true]]); b1; b2 ] | INDIRECT i1 ⇒ λ_. [ ([[true;false;false;false;false;true;true;i1]]); b1 ] | DATA b2 ⇒ λ_. [ ([[false;true;true;true;false;true;false;true]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[data16]] x) → ? with [ DATA16 w ⇒ λ_. let 〈b1,b2〉 ≝ split ? 8 8 w in [ ([[true;false;false;true;false;false;false;false]]); b1; b2] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_. [ ([[true;false;true;false;false;false;true;false]]); b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr1 return λx. bool_to_Prop (is_in ? [[bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_. [ ([[true;false;false;true;false;false;true;false]]); b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1)] | MOVX addrs ⇒ match addrs with [ inl addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[ext_indirect;ext_indirect_dptr]] x) → ? with [ EXT_INDIRECT i1 ⇒ λ_. [ ([[true;true;true;false;false;false;true;i1]]) ] | EXT_INDIRECT_DPTR ⇒ λ_. [ ([[true;true;true;false;false;false;false;false]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr1 return λx. bool_to_Prop (is_in ? [[ext_indirect;ext_indirect_dptr]] x) → ? with [ EXT_INDIRECT i1 ⇒ λ_. [ ([[true;true;true;true;false;false;true;i1]]) ] | EXT_INDIRECT_DPTR ⇒ λ_. [ ([[true;true;true;true;false;false;false;false]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1)] | MUL addr1 addr2 ⇒ [ ([[true;false;true;false;false;true;false;false]]) ] | NOP ⇒ [ ([[false;false;false;false;false;false;false;false]]) ] | ORL addrs ⇒ match addrs with [ inl addrs ⇒ match addrs with [ inl addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[registr;data;direct;indirect]] x) → ? with [ REGISTER r ⇒ λ_.[ ([[false;true;false;false;true]]) @@ r ] | DIRECT b1 ⇒ λ_.[ ([[false;true;false;false;false;true;false;true]]); b1 ] | INDIRECT i1 ⇒ λ_. [ ([[false;true;false;false;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[false;true;false;false;false;true;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in let b1 ≝ match addr1 return λx. bool_to_Prop (is_in ? [[direct]] x) → ? with [ DIRECT b1 ⇒ λ_. b1 | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) in match addr2 return λx. bool_to_Prop (is_in ? [[acc_a;data]] x) → ? with [ ACC_A ⇒ λ_. [ ([[false;true;false;false;false;false;true;false]]); b1 ] | DATA b2 ⇒ λ_. [ ([[false;true;false;false;false;false;true;true]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[bit_addr;n_bit_addr]] x) → ? with [ BIT_ADDR b1 ⇒ λ_. [ ([[false;true;true;true;false;false;true;false]]); b1 ] | N_BIT_ADDR b1 ⇒ λ_. [ ([[true;false;true;false;false;false;false;false]]); b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] | POP addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[direct]] x) → ? with [ DIRECT b1 ⇒ λ_. [ ([[true;true;false;true;false;false;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | PUSH addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[direct]] x) → ? with [ DIRECT b1 ⇒ λ_. [ ([[true;true;false;false;false;false;false;false]]) ; b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | RET ⇒ [ ([[false;false;true;false;false;false;true;false]]) ] | RETI ⇒ [ ([[false;false;true;true;false;false;true;false]]) ] | RL addr ⇒ [ ([[false;false;true;false;false;false;true;true]]) ] | RLC addr ⇒ [ ([[false;false;true;true;false;false;true;true]]) ] | RR addr ⇒ [ ([[false;false;false;false;false;false;true;true]]) ] | RRC addr ⇒ [ ([[false;false;false;true;false;false;true;true]]) ] | SETB addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[carry;bit_addr]] x) → ? with [ CARRY ⇒ λ_. [ ([[true;true;false;true;false;false;true;true]]) ] | BIT_ADDR b1 ⇒ λ_. [ ([[true;true;false;true;false;false;true;false]]); b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | SUBB addr1 addr2 ⇒ match addr2 return λx. bool_to_Prop (is_in ? [[registr;direct;indirect;data]] x) → ? with [ REGISTER r ⇒ λ_. [ ([[true;false;false;true;true]]) @@ r ] | DIRECT b1 ⇒ λ_. [ ([[true;false;false;true;false;true;false;true]]); b1] | INDIRECT i1 ⇒ λ_. [ ([[true;false;false;true;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[true;false;false;true;false;true;false;false]]); b1] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | SWAP addr ⇒ [ ([[true;true;false;false;false;true;false;false]]) ] | XCH addr1 addr2 ⇒ match addr2 return λx. bool_to_Prop (is_in ? [[registr;direct;indirect]] x) → ? with [ REGISTER r ⇒ λ_. [ ([[true;true;false;false;true]]) @@ r ] | DIRECT b1 ⇒ λ_. [ ([[true;true;false;false;false;true;false;true]]); b1] | INDIRECT i1 ⇒ λ_. [ ([[true;true;false;false;false;true;true;i1]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | XCHD addr1 addr2 ⇒ match addr2 return λx. bool_to_Prop (is_in ? [[indirect]] x) → ? with [ INDIRECT i1 ⇒ λ_. [ ([[true;true;false;true;false;true;true;i1]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | XRL addrs ⇒ match addrs with [ inl addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in match addr2 return λx. bool_to_Prop (is_in ? [[data;registr;direct;indirect]] x) → ? with [ REGISTER r ⇒ λ_. [ ([[false;true;true;false;true]]) @@ r ] | DIRECT b1 ⇒ λ_. [ ([[false;true;true;false;false;true;false;true]]); b1] | INDIRECT i1 ⇒ λ_. [ ([[false;true;true;false;false;true;true;i1]]) ] | DATA b1 ⇒ λ_. [ ([[false;true;true;false;false;true;false;false]]); b1] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | inr addrs ⇒ let 〈addr1,addr2〉 ≝ addrs in let b1 ≝ match addr1 return λx. bool_to_Prop (is_in ? [[direct]] x) → ? with [ DIRECT b1 ⇒ λ_. b1 | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr1) in match addr2 return λx. bool_to_Prop (is_in ? [[acc_a;data]] x) → ? with [ ACC_A ⇒ λ_. [ ([[false;true;true;false;false;false;true;false]]); b1 ] | DATA b2 ⇒ λ_. [ ([[false;true;true;false;false;false;true;true]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2)] ]. definition assembly1 ≝ λi: instruction. match i with [ ACALL addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[addr11]] x) → ? with [ ADDR11 w ⇒ λ_. let 〈v1,v2〉 ≝ split ? 3 8 w in [ (v1 @@ [[true; false; false; false; true]]) ; v2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | AJMP addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[addr11]] x) → ? with [ ADDR11 w ⇒ λ_. let 〈v1,v2〉 ≝ split ? 3 8 w in [ (v1 @@ [[false; false; false; false; true]]) ; v2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | JMP adptr ⇒ [ ([[false;true;true;true;false;false;true;true]]) ] | LCALL addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[addr16]] x) → ? with [ ADDR16 w ⇒ λ_. let 〈b1,b2〉 ≝ split ? 8 8 w in [ ([[false;false;false;true;false;false;true;false]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | LJMP addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[addr16]] x) → ? with [ ADDR16 w ⇒ λ_. let 〈b1,b2〉 ≝ split ? 8 8 w in [ ([[false;false;false;false;false;false;true;false]]); b1; b2 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | MOVC addr1 addr2 ⇒ match addr2 return λx. bool_to_Prop (is_in ? [[acc_dptr;acc_pc]] x) → ? with [ ACC_DPTR ⇒ λ_. [ ([[true;false;false;true;false;false;true;true]]) ] | ACC_PC ⇒ λ_. [ ([[true;false;false;false;false;false;true;true]]) ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr2) | SJMP addr ⇒ match addr return λx. bool_to_Prop (is_in ? [[relative]] x) → ? with [ RELATIVE b1 ⇒ λ_. [ ([[true;false;false;false;false;false;false;false]]); b1 ] | _ ⇒ λK.match K in False with [ ] ] (subaddressing_modein … addr) | RealInstruction instr ⇒ assembly_preinstruction [[ relative ]] (λx. match x return λs. bool_to_Prop (is_in ? [[ relative ]] s) → ? with [ RELATIVE r ⇒ λ_. r | _ ⇒ λabsd. ⊥ ] (subaddressing_modein … x)) instr ]. cases absd qed. definition is_relative_jump ≝ λi: preinstruction Identifier. match i with [ JC _ ⇒ True | JNC _ ⇒ True | JB _ _ ⇒ True | JNB _ _ ⇒ True | JBC _ _ ⇒ True | JZ _ ⇒ True | JNZ _ ⇒ True | CJNE _ _ ⇒ True | DJNZ _ _ ⇒ True | _ ⇒ False ]. definition pseudo_instruction_is_relative_jump: pseudo_instruction → Prop ≝ λi. match i with [ Instruction j ⇒ is_relative_jump j | _ ⇒ False ]. inductive jump_length: Type[0] ≝ | short_jump: jump_length | medium_jump: jump_length | long_jump: jump_length. axiom jump_expansion_policy: ∀program: pseudo_assembly_program. ∀pc: Word. jump_length. definition expand_relative_jump_internal: (Identifier → Word) → jump_length → Identifier → Word → ([[relative]] → preinstruction [[relative]]) → option (list instruction) ≝ λlookup_labels,jmp_len.λjmp:Identifier.λpc,i. match jmp_len with [ short_jump ⇒ let lookup_address ≝ lookup_labels jmp in let 〈result, flags〉 ≝ sub_16_with_carry pc lookup_address false in let 〈upper, lower〉 ≝ split ? 8 8 result in if eq_bv ? upper (zero 8) then let address ≝ RELATIVE lower in Some ? [ RealInstruction (i address) ] else None ? | medium_jump ⇒ None … | long_jump ⇒ Some ? [ RealInstruction (i (RELATIVE (bitvector_of_nat ? 2))); SJMP (RELATIVE (bitvector_of_nat ? 3)); (* LJMP size? *) LJMP (ADDR16 (lookup_labels jmp)) ] ]. @ I qed. definition expand_relative_jump: (Identifier → Word) → jump_length → Word → preinstruction Identifier → option (list instruction) ≝ λlookup_labels. λjmp_len: jump_length. λpc. λi: preinstruction Identifier. let rel_jmp ≝ RELATIVE (bitvector_of_nat ? 2) in match i with [ JC jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JC ?) | JNC jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JNC ?) | JB baddr jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JB ? baddr) | JZ jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JZ ?) | JNZ jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JNZ ?) | JBC baddr jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JBC ? baddr) | JNB baddr jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (JNB ? baddr) | CJNE addr jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (CJNE ? addr) | DJNZ addr jmp ⇒ expand_relative_jump_internal lookup_labels jmp_len jmp pc (DJNZ ? addr) | ADD arg1 arg2 ⇒ Some ? [ ADD ? arg1 arg2 ] | ADDC arg1 arg2 ⇒ Some ? [ ADDC ? arg1 arg2 ] | SUBB arg1 arg2 ⇒ Some ? [ SUBB ? arg1 arg2 ] | INC arg ⇒ Some ? [ INC ? arg ] | DEC arg ⇒ Some ? [ DEC ? arg ] | MUL arg1 arg2 ⇒ Some ? [ MUL ? arg1 arg2 ] | DIV arg1 arg2 ⇒ Some ? [ DIV ? arg1 arg2 ] | DA arg ⇒ Some ? [ DA ? arg ] | ANL arg ⇒ Some ? [ ANL ? arg ] | ORL arg ⇒ Some ? [ ORL ? arg ] | XRL arg ⇒ Some ? [ XRL ? arg ] | CLR arg ⇒ Some ? [ CLR ? arg ] | CPL arg ⇒ Some ? [ CPL ? arg ] | RL arg ⇒ Some ? [ RL ? arg ] | RR arg ⇒ Some ? [ RR ? arg ] | RLC arg ⇒ Some ? [ RLC ? arg ] | RRC arg ⇒ Some ? [ RRC ? arg ] | SWAP arg ⇒ Some ? [ SWAP ? arg ] | MOV arg ⇒ Some ? [ MOV ? arg ] | MOVX arg ⇒ Some ? [ MOVX ? arg ] | SETB arg ⇒ Some ? [ SETB ? arg ] | PUSH arg ⇒ Some ? [ PUSH ? arg ] | POP arg ⇒ Some ? [ POP ? arg ] | XCH arg1 arg2 ⇒ Some ? [ XCH ? arg1 arg2 ] | XCHD arg1 arg2 ⇒ Some ? [ XCHD ? arg1 arg2 ] | RET ⇒ Some ? [ RET ? ] | RETI ⇒ Some ? [ RETI ? ] | NOP ⇒ Some ? [ RealInstruction (NOP ?) ] ]. definition expand_pseudo_instruction: ? → ? → Word → jump_length → pseudo_instruction → option (list instruction) ≝ λlookup_labels. λlookup_datalabels. λpc. λjmp_len. λi. match i with [ Cost cost ⇒ Some ? [ ] | Comment comment ⇒ Some ? [ ] | Call call ⇒ match jmp_len with [ short_jump ⇒ None ? | medium_jump ⇒ let 〈ignore, address〉 ≝ split ? 5 11 (lookup_labels call) in let 〈fst_5, rest〉 ≝ split ? 5 11 pc in if eq_bv ? ignore fst_5 then let address ≝ ADDR11 address in Some ? ([ ACALL address ]) else None ? | long_jump ⇒ let address ≝ ADDR16 (lookup_labels call) in Some ? [ LCALL address ] ] | Mov d trgt ⇒ let address ≝ DATA16 (lookup_datalabels trgt) in Some ? [ RealInstruction (MOV ? (inl ? ? (inl ? ? (inr ? ? 〈DPTR, address〉))))] | Instruction instr ⇒ expand_relative_jump lookup_labels jmp_len pc instr | Jmp jmp ⇒ match jmp_len with [ short_jump ⇒ let lookup_address ≝ lookup_labels jmp in let 〈result, flags〉 ≝ sub_16_with_carry pc lookup_address false in let 〈upper, lower〉 ≝ split ? 8 8 result in if eq_bv ? upper (zero 8) then let address ≝ RELATIVE lower in Some ? [ SJMP address ] else None ? | medium_jump ⇒ let address ≝ lookup_labels jmp in let 〈fst_5_addr, rest_addr〉 ≝ split ? 5 11 address in let 〈fst_5_pc, rest_pc〉 ≝ split ? 5 11 pc in if eq_bv ? fst_5_addr fst_5_pc then let address ≝ ADDR11 rest_addr in Some ? ([ AJMP address ]) else None ? | long_jump ⇒ let address ≝ ADDR16 (lookup_labels jmp) in Some ? [ LJMP address ] ] ]. @ I qed. definition assembly_1_pseudoinstruction ≝ λprogram. λpc. λlookup_labels. λlookup_datalabels. λi. let expansion ≝ jump_expansion_policy program pc in match expand_pseudo_instruction lookup_labels lookup_datalabels pc expansion i with [ None ⇒ None ? | Some pseudos ⇒ let mapped ≝ map ? ? assembly1 pseudos in let flattened ≝ flatten ? mapped in let len ≝ length ? flattened in Some ? (〈len, flattened〉) ]. definition construct_datalabels ≝ λpreamble. \fst (foldl ((BitVectorTrie Identifier 16) × nat) ? ( λt. λpreamble. let 〈datalabels, addr〉 ≝ t in let 〈name, size〉 ≝ preamble in let addr_16 ≝ bitvector_of_nat 16 addr in 〈insert ? ? name addr_16 datalabels, addr + size〉) 〈(Stub ? ?), 0〉 preamble). definition construct_costs ≝ λprogram. λprogram_counter: nat. λlookup_labels. λlookup_datalabels. λcosts: BitVectorTrie Word 16. λi. match i with [ Cost cost ⇒ let program_counter_bv ≝ bitvector_of_nat ? program_counter in Some ? 〈program_counter, (insert ? ? program_counter_bv cost costs)〉 | _ ⇒ let pc_bv ≝ bitvector_of_nat ? program_counter in let pc_delta_assembled ≝ assembly_1_pseudoinstruction program pc_bv lookup_labels lookup_datalabels i in match pc_delta_assembled with [ None ⇒ None ? | Some pc_delta_assembled ⇒ let 〈pc_delta, assembled〉 ≝ pc_delta_assembled in Some ? 〈pc_delta + program_counter, costs〉 ] ]. definition build_maps ≝ λinstr_list. let result ≝ foldl (option ((BitVectorTrie Word 16) × (nat × (BitVectorTrie Word 16)))) ? (λt. λi. let 〈label, i〉 ≝ i in match t with [ None ⇒ None ? | Some t ⇒ let 〈labels, pc_costs〉 ≝ t in let 〈program_counter, costs〉 ≝ pc_costs in let labels ≝ match label with [ None ⇒ labels | Some label ⇒ let program_counter_bv ≝ bitvector_of_nat ? program_counter in insert ? ? label program_counter_bv labels ] in match construct_costs instr_list program_counter (λx. zero ?) (λx. zero ?) costs i with [ None ⇒ None ? | Some construct ⇒ Some ? 〈labels, construct〉 ] ]) (Some ? 〈(Stub ? ?), 〈0, (Stub ? ?)〉〉) (\snd instr_list) in match result with [ None ⇒ None ? | Some result ⇒ let 〈labels, pc_costs〉 ≝ result in let 〈pc, costs〉 ≝ pc_costs in if gtb pc (2^16) then None ? else Some ? 〈labels, costs〉 ]. definition assembly: pseudo_assembly_program → option (list Byte × (BitVectorTrie Identifier 16)) ≝ λp. let 〈preamble, instr_list〉 ≝ p in match build_maps p with [ None ⇒ None ? | Some labels_costs ⇒ let datalabels ≝ construct_datalabels preamble in let 〈labels,costs〉 ≝ labels_costs in let lookup_labels ≝ λx. lookup ? ? x labels (zero ?) in let lookup_datalabels ≝ λx. lookup ? ? x datalabels (zero ?) in let result ≝ foldr ? ? (λx. λy. match y with [ None ⇒ None ? | Some lst ⇒ let 〈pc, y〉 ≝ lst in let x ≝ assembly_1_pseudoinstruction p pc lookup_labels lookup_datalabels (\snd x) in match x with [ None ⇒ None ? | Some x ⇒ let 〈pc_delta, program〉 ≝ x in let 〈new_pc, flags〉 ≝ add_16_with_carry pc (bitvector_of_nat ? pc_delta) false in Some ? 〈new_pc, (program @ y)〉 ] ]) (Some ? 〈(zero ?), [ ]〉) instr_list in match result with [ None ⇒ None ? | Some result ⇒ Some ? (〈\snd result, costs〉) ] ]. definition assembly_unlabelled_program: assembly_program → option (list Byte × (BitVectorTrie Identifier 16)) ≝ λp. Some ? (〈foldr ? ? (λi,l. assembly1 i @ l) [ ] p, Stub …〉).