(* ------------------------------------------------------------------------ *) (* ARM Machine Code Semantics (A and R profiles) *) (* ============================================= *) (* Operational semantics for ARM *) (* ------------------------------------------------------------------------ *) (* interactive use: app load ["arm_seq_monadTheory", "wordsLib", "intLib", "integer_wordTheory", "stringSimps", "parmonadsyntax"]; *) open HolKernel boolLib bossLib Parse; open wordsTheory wordsLib integer_wordTheory; open arm_coretypesTheory arm_seq_monadTheory; val _ = new_theory "arm_opsem"; (* ------------------------------------------------------------------------ *) val _ = numLib.prefer_num(); val _ = wordsLib.prefer_word(); val _ = set_fixity ">>=" (Infixr 660); val _ = set_fixity "|||" (Infixr 90); val _ = overload_on(">>=", ``seqT``); val _ = overload_on("|||", ``parT``); val _ = temp_overload_on (parmonadsyntax.monad_bind, ``seqT``); val _ = temp_overload_on (parmonadsyntax.monad_par, ``parT``); val _ = temp_overload_on ("return", ``constT``); val _ = overload_on("UNKNOWN", ``ARB:bool``); val _ = overload_on("UNKNOWN", ``ARB:word32``); val _ = overload_on("BITS16_UNKNOWN", ``[ARB;ARB] : word8 list``); val _ = overload_on("BITS32_UNKNOWN", ``[ARB;ARB;ARB;ARB] : word8 list``); val _ = app temp_overload_on [("unit2", ``\(u1:unit,u2:unit). constT ()``), ("unit3", ``\(u1:unit,u2:unit,u3:unit). constT ()``), ("unit4", ``\(u1:unit,u2:unit,u3:unit,u4:unit). constT ()``)]; val _ = temp_overload_on ("ALL", ``(UNIV CROSS UNIV) : (ARMarch # ARMextensions set) set``); val _ = temp_overload_on ("ARCH", ``\s. (s CROSS UNIV) : (ARMarch # ARMextensions set) set``); val _ = temp_overload_on("BadReg", ``\n:word4. (n = 13w) \/ (n = 15w)``); val _ = temp_overload_on("extend", ``\u. if u then w2w else sw2sw``); val _ = temp_overload_on ("ARCH2", ``\enc a. ARCH (if enc = Encoding_Thumb2 then thumb2_support else a)``); (* ------------------------------------------------------------------------ *) val unaligned_support_def = Define` unaligned_support ii = read_info ii >>= (\info. constT (info.unaligned_support))`; val dsp_support_def = Define` dsp_support = COMPL {ARMv4; ARMv4T; ARMv5T}`; val kernel_support_def = Define` kernel_support = {a | (a = ARMv6K) \/ version_number a >= 7}`; val arch_version_def = Define` arch_version ii = seqT (read_arch ii) (constT o version_number)`; val read_reg_literal_def = Define` read_reg_literal ii n = if n = 15w then read_reg ii 15w >>= (\pc. constT (align(pc,4))) else read_reg ii n`; val read_flags_def = Define` read_flags ii = read_cpsr ii >>= (\cpsr. constT (cpsr.N,cpsr.Z,cpsr.C,cpsr.V))`; val write_flags_def = Define` write_flags ii (n,z,c,v) = read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| N := n; Z := z; C := c; V := v |>))`; val read_cflag_def = Define` read_cflag ii = read_flags ii >>= (\(n,z,c,v). constT c)`; val set_q_def = Define` set_q ii = read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with Q := T))`; val read_ge_def = Define` read_ge ii = read_cpsr ii >>= (\cpsr. constT (cpsr.GE))`; val write_ge_def = Define` write_ge ii ge = read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with GE := ge))`; val write_e_def = Define` write_e ii e = read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with E := e))`; val IT_advance_def = Define` IT_advance ii = read_arch ii >>= (\arch. condT (arch IN thumb2_support) (read_cpsr ii >>= (\cpsr. if (cpsr.IT = 0w) \/ cpsr.T then write_cpsr ii (cpsr with IT := ITAdvance cpsr.IT) else errorT "IT_advance: unpredictable")))`; val cpsr_write_by_instr_def = zDefine` cpsr_write_by_instr ii (value:word32, bytemask:word4, affect_execstate:bool) = let value_mode = (4 >< 0) value in (current_mode_is_priviledged ii ||| is_secure ii ||| read_nsacr ii ||| bad_mode ii value_mode) >>= (\(priviledged,is_secure,nsacr,badmode). if bytemask ' 0 /\ priviledged /\ (badmode \/ ~is_secure /\ (value_mode = 0b10110w) \/ ~is_secure /\ (value_mode = 0b10001w) /\ nsacr.RFR) then errorT "cpsr_write_by_instr: unpredictable" else (read_sctlr ii ||| read_scr ii ||| read_cpsr ii) >>= (\(sctlr,scr,cpsr). let cpsr = word_modify (\i b. if 27 <= i /\ i <= 31 /\ bytemask ' 3 \/ 24 <= i /\ i <= 26 /\ bytemask ' 3 /\ affect_execstate \/ 16 <= i /\ i <= 19 /\ bytemask ' 2 \/ 10 <= i /\ i <= 15 /\ bytemask ' 1 /\ affect_execstate \/ (i = 9) /\ bytemask ' 1 \/ (i = 8) /\ bytemask ' 1 /\ priviledged /\ (is_secure \/ scr.AW) \/ (i = 7) /\ bytemask ' 0 /\ priviledged \/ (i = 6) /\ bytemask ' 0 /\ priviledged /\ (is_secure \/ scr.FW) /\ (~sctlr.NMFI \/ ~(value ' 6)) \/ (i = 5) /\ bytemask ' 0 /\ affect_execstate \/ (i < 5) /\ bytemask ' 0 /\ priviledged then value ' i else b) (encode_psr cpsr) in write_cpsr ii (decode_psr cpsr)))`; val spsr_write_by_instr_def = zDefine` spsr_write_by_instr ii (value:word32, bytemask:word4) = (current_mode_is_user_or_system ii ||| bad_mode ii ((4 >< 0) value)) >>= (\(user_or_system,badmode). if user_or_system \/ bytemask ' 0 /\ badmode then errorT "spsr_write_by_instr: unpredictable" else read_spsr ii >>= (\spsr. let spsr = word_modify (\i b. if 24 <= i /\ i <= 31 /\ bytemask ' 3 \/ 16 <= i /\ i <= 19 /\ bytemask ' 2 \/ 8 <= i /\ i <= 15 /\ bytemask ' 1 \/ i <= 7 /\ bytemask ' 0 then value ' i else b) (encode_psr spsr) in write_spsr ii (decode_psr spsr)))`; val integer_zero_divide_trapping_enabled_def = Define` integer_zero_divide_trapping_enabled ii = read_sctlr ii >>= (\sctlr. constT sctlr.DZ)`; (* ------------------------------------------------------------------------ *) val branch_write_pc_def = Define` branch_write_pc ii (address:word32) = current_instr_set ii >>= (\iset. if iset = InstrSet_ARM then arch_version ii >>= (\version. if version < 6 /\ ((1 >< 0) address <> 0w:word2) then errorT "branch_write_pc: unpredictable" else branch_to ii ((31 '' 2) address)) else branch_to ii ((31 '' 1) address))`; val bx_write_pc_def = Define` bx_write_pc ii (address:word32) = current_instr_set ii >>= (\iset. if iset = InstrSet_ThumbEE then if address ' 0 then branch_to ii ((31 '' 1) address) else errorT "bx_write_pc: unpredictable" else if address ' 0 then select_instr_set ii InstrSet_Thumb >>= (\u. branch_to ii ((31 '' 1) address)) else if ~(address ' 1) then select_instr_set ii InstrSet_ARM >>= (\u. branch_to ii address) else (* address<1:0> = '10' *) errorT "bx_write_pc: unpredictable")`; val load_write_pc_def = Define` load_write_pc ii (address:word32) = arch_version ii >>= (\version. if version >= 5 then bx_write_pc ii address else branch_write_pc ii address)`; val alu_write_pc_def = Define` alu_write_pc ii (address:word32) = (arch_version ii ||| current_instr_set ii) >>= (\(version,iset). if version >= 7 /\ (iset = InstrSet_ARM) then bx_write_pc ii address else branch_write_pc ii address)`; (* ------------------------------------------------------------------------ *) val decode_imm_shift_def = Define` decode_imm_shift (type:word2, imm5:word5) = case type of 0b00w => (SRType_LSL, w2n imm5) | 0b01w => (SRType_LSR, if imm5 = 0w then 32 else w2n imm5) | 0b10w => (SRType_ASR, if imm5 = 0w then 32 else w2n imm5) | 0b11w => if imm5 = 0w then (SRType_RRX, 1) else (SRType_ROR, w2n imm5)`; val decode_reg_shift_def = Define` decode_reg_shift (type:word2) = case type of 0b00w => SRType_LSL | 0b01w => SRType_LSR | 0b10w => SRType_ASR | 0b11w => SRType_ROR`; val shift_c_def = Define` shift_c (value:'a word, type:SRType, amount:num, carry_in:bool) = if (type = SRType_RRX) /\ (amount <> 1) then errorT "shift_c: RRX amount not 1" else constT (if amount = 0 then (value, carry_in) else (case type of SRType_LSL => LSL_C (value, amount) | SRType_LSR => LSR_C (value, amount) | SRType_ASR => ASR_C (value, amount) | SRType_ROR => ROR_C (value, amount) | SRType_RRX => RRX_C (value, carry_in)))`; val shift_def = Define` shift (value:'a word, type:SRType, amount:num, carry_in:bool) = (shift_c (value, type, amount, carry_in)) >>= (\r. constT (FST r))`; val arm_expand_imm_c_def = Define` arm_expand_imm_c (imm12:word12, carry_in:bool) = shift_c ((7 >< 0) imm12 : word32, SRType_ROR, 2 * w2n ((11 -- 8) imm12), carry_in)`; val arm_expand_imm_def = Define` arm_expand_imm ii (imm12:word12) = read_cflag ii >>= (\c. arm_expand_imm_c (imm12,c) >>= (\(imm32,c). constT imm32))`; val thumb_expand_imm_c_def = Define` thumb_expand_imm_c (imm12:word12, carry_in:bool) : (word32 # bool) M = if (11 -- 10) imm12 = 0b00w then let imm8 = (7 >< 0) imm12 : word8 in case (9 >< 8) imm12 : word2 of 0b00w => constT (w2w imm8, carry_in) | 0b01w => if imm8 = 0w then errorT "thumb_expand_imm_c: unpredictable" else constT (word32 [imm8; 0b00000000w; imm8; 0b00000000w], carry_in) | 0b10w => if imm8 = 0w then errorT "thumb_expand_imm_c: unpredictable" else constT (word32 [0b00000000w; imm8; 0b00000000w; imm8], carry_in) | 0b11w => if imm8 = 0w then errorT "thumb_expand_imm_c: unpredictable" else constT (word32 [imm8; imm8; imm8; imm8], carry_in) else let unrotated_value = (7 :+ T) ((6 >< 0) imm12) in constT (ROR_C (unrotated_value, w2n ((11 -- 7) imm12)))`; (* val thumb_expand_imm_def = Define` thumb_expand_imm ii (imm12:word12) = read_cflag ii >>= (\c. thumb_expand_imm_c (imm12,c) >>= (\(imm32,c). constT imm32))`; *) (* ------------------------------------------------------------------------ *) val address_mode1_def = Define` (address_mode1 ii thumb2 (Mode1_immediate imm12) = read_cflag ii >>= (\c. if thumb2 then thumb_expand_imm_c (imm12,c) else arm_expand_imm_c (imm12,c))) /\ (address_mode1 ii thumb2 (Mode1_register imm5 type rm) = (read_reg ii rm ||| read_cflag ii) >>= (\(rm,c). let (shift_t,shift_n) = decode_imm_shift (type,imm5) in shift_c (rm, shift_t, shift_n, c))) /\ (address_mode1 ii thumb2 (Mode1_register_shifted_register rs type rm) = (read_reg ii rm ||| read_reg ii rs ||| read_cflag ii) >>= (\(rm,rs,c). let shift_t = decode_reg_shift type and shift_n = w2n ((7 -- 0) rs) in shift_c (rm, shift_t, shift_n, c)))`; val address_mode2_def = Define` (address_mode2 ii indx add rn (Mode2_immediate imm12) = let imm32 = w2w imm12 in let offset_addr = if add then rn + imm32 else rn - imm32 in constT (offset_addr, if indx then offset_addr else rn)) /\ (address_mode2 ii indx add rn (Mode2_register imm5 type rm) = (read_reg ii rm ||| read_cflag ii) >>= (\(rm,c). let (shift_t,shift_n) = decode_imm_shift (type,imm5) in shift (rm, shift_t, shift_n, c) >>= (\imm32. let offset_addr = if add then rn + imm32 else rn - imm32 in constT (offset_addr, if indx then offset_addr else rn))))`; val address_mode3_def = Define` (address_mode3 ii indx add rn (Mode3_immediate imm12) = let imm32 = w2w imm12 in let offset_addr = if add then rn + imm32 else rn - imm32 in constT (offset_addr, if indx then offset_addr else rn)) /\ (address_mode3 ii indx add rn (Mode3_register imm2 rm) = (read_reg ii rm ||| read_cflag ii) >>= (\(rm,c). shift (rm, SRType_LSL, w2n imm2, c) >>= (\imm32. let offset_addr = if add then rn + imm32 else rn - imm32 in constT (offset_addr, if indx then offset_addr else rn))))`; val address_mode5_def = Define` address_mode5 indx add rn (imm8:word8) = let imm32 : word32 = (w2w imm8) << 2 in let offset_addr = if add then rn + imm32 else rn - imm32 in constT (offset_addr, if indx then offset_addr else rn)`; (* ------------------------------------------------------------------------ *) val data_processing_alu_def = Define` data_processing_alu (opc:word4) (a:word32) b c = case opc of 0b0000w => ( a && b , ARB, ARB) (* AND *) | 0b0001w => ( a ?? b , ARB, ARB) (* EOR *) | 0b0010w => add_with_carry( a,~b, T) (* SUB *) | 0b0011w => add_with_carry(~a, b, T) (* RSB *) | 0b0100w => add_with_carry( a, b, F) (* ADD *) | 0b0101w => add_with_carry( a, b, c) (* ADC *) | 0b0110w => add_with_carry( a,~b, c) (* SBC *) | 0b0111w => add_with_carry(~a, b, c) (* RSC *) | 0b1000w => ( a && b , ARB , ARB) (* TST *) | 0b1001w => ( a ?? b , ARB , ARB) (* TEQ *) | 0b1010w => add_with_carry( a,~b, T) (* CMP *) | 0b1011w => add_with_carry( a, b, F) (* CMN *) | 0b1100w => ( a || b , ARB , ARB) (* ORR *) | 0b1101w => ( b , ARB , ARB) (* MOV *) | 0b1110w => ( a && ~b , ARB , ARB) (* BIC *) | _ => ( a || ~b , ARB , ARB)`; (* MVN/ORN *) val data_processing_thumb2_unpredictable_def = Define` (data_processing_thumb2_unpredictable (Data_Processing opc setflags n d (Mode1_immediate imm12)) = case opc of 0b0000w => (* AND *) (d = 13w) \/ (d = 15w) /\ ~setflags \/ BadReg n | 0b0001w => (* EOR *) (d = 13w) \/ (d = 15w) /\ ~setflags \/ BadReg n | 0b0010w => (* SUB *) (if n = 13w then (d = 15w) /\ ~setflags else (d = 13w) \/ (d = 15w) /\ ~setflags \/ (n = 15w)) | 0b0100w => (* ADD *) if n = 13w then (d = 15w) /\ ~setflags else (d = 13w) \/ (d = 15w) /\ ~setflags \/ (n = 15w) | 0b0111w => T (* RSC *) | 0b1000w => BadReg n (* TST *) | 0b1001w => BadReg n (* TEQ *) | 0b1010w => n = 15w (* CMP *) | 0b1011w => n = 15w (* CMN *) | 0b1101w => BadReg d (* MOV *) | 0b1111w => BadReg d \/ (n = 13w) (* MVN/ORN *) | _ => (* RSB,ADC,SBC,ORR,BIC *) BadReg d \/ BadReg n) /\ (data_processing_thumb2_unpredictable (Data_Processing opc setflags n d (Mode1_register imm5 typ m)) = case opc of 0b0000w => (* AND *) (d = 13w) \/ (d = 15w) /\ ~setflags \/ BadReg n | 0b0001w => (* EOR *) (d = 13w) \/ (d = 15w) /\ ~setflags \/ BadReg n | 0b0010w => (* SUB *) if n = 13w then (d = 13w) /\ (typ <> 0w \/ w2n imm5 > 3) \/ (d = 15w) \/ BadReg m else (d = 13w) \/ (d = 15w) /\ ~setflags \/ (n = 15w) \/ BadReg m | 0b0100w => (* ADD *) if n = 13w then (d = 13w) /\ (typ <> 0w \/ w2n imm5 > 3) \/ (d = 15w) \/ BadReg m else (d = 13w) \/ (d = 15w) /\ ~setflags \/ (n = 15w) \/ BadReg m | 0b0111w => T (* RSC *) | 0b1000w => BadReg n \/ BadReg m (* TST *) | 0b1001w => BadReg n \/ BadReg m (* TEQ *) | 0b1010w => (n = 15w) \/ BadReg m (* CMP *) | 0b1011w => (n = 15w) \/ BadReg m (* CMN *) | 0b1101w => (* MOV *) if setflags then BadReg d \/ BadReg m else (d = 15w) \/ (m = 15w) \/ (d = 13w) /\ (m = 13w) | 0b1111w => BadReg d \/ (n = 13w) \/ BadReg m (* MVN/ORN *) | _ => (* RSB,ADC,SBC,ORR,BIC *) BadReg d \/ BadReg n \/ BadReg m) /\ (data_processing_thumb2_unpredictable (Data_Processing opc setflags n d (Mode1_register_shifted_register s typ m)) = opc <> 0b1101w \/ BadReg d \/ BadReg s \/ BadReg m)`; val _ = temp_overload_on ("top_half", ``( 31 >< 16 ) : word32 -> word16``); val _ = temp_overload_on ("bot_half", ``( 15 >< 0 ) : word32 -> word16``); val signed_parallel_add_sub_16_def = Define` signed_parallel_add_sub_16 op2 rn rm = let bn = SInt (bot_half rn) and bm = SInt (bot_half rm) and tn = SInt (top_half rn) and tm = SInt (top_half rm) in case op2 of Parallel_add_16 => (bn + bm, tn + tm) | Parallel_add_sub_exchange => (bn - tm, tn + bm) | Parallel_sub_add_exchange => (bn + tm, tn - bm) | Parallel_sub_16 => (bn - bm, tn - tm)`; val signed_normal_add_sub_16_def = Define` signed_normal_add_sub_16 op2 rn rm : word32 # word4 option = let (r1,r2) = signed_parallel_add_sub_16 op2 rn rm in let ge1 = if r1 >= 0i then 0b11w else 0b00w : word2 and ge2 = if r2 >= 0i then 0b11w else 0b00w : word2 in ((i2w r2 : word16) @@ (i2w r1 : word16), SOME (ge2 @@ ge1))`; val signed_saturating_add_sub_16_def = Define` signed_saturating_add_sub_16 op2 rn rm : word32 # word4 option = let (r1,r2) = signed_parallel_add_sub_16 op2 rn rm in ((signed_sat (r2,16) : word16) @@ (signed_sat (r1,16) : word16), NONE)`; val signed_halving_add_sub_16_def = Define` signed_halving_add_sub_16 op2 rn rm : word32 # word4 option = let (r1,r2) = signed_parallel_add_sub_16 op2 rn rm in ((i2w (r2 / 2) : word16) @@ (i2w (r1 / 2) : word16), NONE)`; val signed_parallel_add_sub_8_def = Define` signed_parallel_add_sub_8 op2 rn rm = let n = MAP SInt (bytes (rn,4)) and m = MAP SInt (bytes (rm,4)) in case op2 of Parallel_add_8 => MAP (UNCURRY $+) (ZIP (n,m)) | Parallel_sub_8 => MAP (UNCURRY $-) (ZIP (n,m))`; val signed_normal_add_sub_8_def = Define` signed_normal_add_sub_8 op2 rn rm : word32 # word4 option = let r = signed_parallel_add_sub_8 op2 rn rm in let ge = FCP i. EL i r >= 0i in (word32 (MAP i2w r), SOME ge)`; val signed_saturating_add_sub_8_def = Define` signed_saturating_add_sub_8 op2 rn rm : word32 # word4 option = (word32 (MAP (\i. signed_sat (i,8)) (signed_parallel_add_sub_8 op2 rn rm)), NONE)`; val signed_halving_add_sub_8_def = Define` signed_halving_add_sub_8 op2 rn rm : word32 # word4 option = (word32 (MAP (\i. i2w (i / 2)) (signed_parallel_add_sub_8 op2 rn rm)), NONE)`; val unsigned_parallel_add_sub_16_def = Define` unsigned_parallel_add_sub_16 op2 rn rm = let bn = UInt (bot_half rn) and bm = UInt (bot_half rm) and tn = UInt (top_half rn) and tm = UInt (top_half rm) in case op2 of Parallel_add_16 => (bn + bm, tn + tm) | Parallel_add_sub_exchange => (bn - tm, tn + bm) | Parallel_sub_add_exchange => (bn + tm, tn - bm) | Parallel_sub_16 => (bn - bm, tn - tm)`; val unsigned_normal_add_sub_16_def = Define` unsigned_normal_add_sub_16 op2 rn rm : word32 # word4 option = let (r1,r2) = unsigned_parallel_add_sub_16 op2 rn rm in let (ge1:word2,ge2:word2) = case op2 of Parallel_add_16 => (if r1 >= 0x10000i then 0b11w else 0b00w, if r2 >= 0x10000i then 0b11w else 0b00w) | Parallel_add_sub_exchange => (if r1 >= 0i then 0b11w else 0b00w, if r2 >= 0x10000i then 0b11w else 0b00w) | Parallel_sub_add_exchange => (if r1 >= 0x10000i then 0b11w else 0b00w, if r2 >= 0i then 0b11w else 0b00w) | Parallel_sub_16 => (if r1 >= 0i then 0b11w else 0b00w, if r2 >= 0i then 0b11w else 0b00w) in ((i2w r2 : word16) @@ (i2w r1 : word16), SOME (ge2 @@ ge1))`; val unsigned_saturating_add_sub_16_def = Define` unsigned_saturating_add_sub_16 op2 rn rm : word32 # word4 option = let (r1,r2) = unsigned_parallel_add_sub_16 op2 rn rm in ((unsigned_sat (r2,16) : word16) @@ (unsigned_sat (r1,16) : word16), NONE)`; val unsigned_halving_add_sub_16_def = Define` unsigned_halving_add_sub_16 op2 rn rm : word32 # word4 option = let (r1,r2) = unsigned_parallel_add_sub_16 op2 rn rm in ((i2w (r2 / 2) : word16) @@ (i2w (r1 / 2) : word16), NONE)`; val unsigned_parallel_add_sub_8_def = Define` unsigned_parallel_add_sub_8 op2 rn rm = let n = MAP UInt (bytes (rn,4)) and m = MAP UInt (bytes (rm,4)) in case op2 of Parallel_add_8 => MAP (UNCURRY $+) (ZIP (n,m)) | Parallel_sub_8 => MAP (UNCURRY $-) (ZIP (n,m))`; val unsigned_normal_add_sub_8_def = Define` unsigned_normal_add_sub_8 op2 rn rm : word32 # word4 option = let r = unsigned_parallel_add_sub_8 op2 rn rm and ge_lim = case op2 of Parallel_add_8 => 0x100i | Parallel_sub_8 => 0i in let ge:word4 = FCP i. EL i r >= ge_lim in (word32 (MAP i2w r), SOME ge)`; val unsigned_saturating_add_sub_8_def = Define` unsigned_saturating_add_sub_8 op2 rn rm : word32 # word4 option = (word32 (MAP (\i. unsigned_sat (i,8)) (unsigned_parallel_add_sub_8 op2 rn rm)), NONE)`; val unsigned_halving_add_sub_8_def = Define` unsigned_halving_add_sub_8 op2 rn rm : word32 # word4 option = (word32 (MAP (\i. i2w (i / 2)) (unsigned_parallel_add_sub_8 op2 rn rm)), NONE)`; val parallel_add_sub_def = Define` parallel_add_sub u (op1,op2) rn rm = case (u,op1,op2) of (F,Parallel_normal,Parallel_add_8) => signed_normal_add_sub_8 op2 rn rm | (F,Parallel_normal,Parallel_sub_8) => signed_normal_add_sub_8 op2 rn rm | (F,Parallel_normal,_) => signed_normal_add_sub_16 op2 rn rm | (F,Parallel_saturating,Parallel_add_8) => signed_saturating_add_sub_8 op2 rn rm | (F,Parallel_saturating,Parallel_sub_8) => signed_saturating_add_sub_8 op2 rn rm | (F,Parallel_saturating,_) => signed_saturating_add_sub_16 op2 rn rm | (F,Parallel_halving,Parallel_add_8) => signed_halving_add_sub_8 op2 rn rm | (F,Parallel_halving,Parallel_sub_8) => signed_halving_add_sub_8 op2 rn rm | (F,Parallel_halving,_) => signed_halving_add_sub_16 op2 rn rm | (T,Parallel_normal,Parallel_add_8) => unsigned_normal_add_sub_8 op2 rn rm | (T,Parallel_normal,Parallel_sub_8) => unsigned_normal_add_sub_8 op2 rn rm | (T,Parallel_normal,_) => unsigned_normal_add_sub_16 op2 rn rm | (T,Parallel_saturating,Parallel_add_8) => unsigned_saturating_add_sub_8 op2 rn rm | (T,Parallel_saturating,Parallel_sub_8) => unsigned_saturating_add_sub_8 op2 rn rm | (T,Parallel_saturating,_) => unsigned_saturating_add_sub_16 op2 rn rm | (T,Parallel_halving,Parallel_add_8) => unsigned_halving_add_sub_8 op2 rn rm | (T,Parallel_halving,Parallel_sub_8) => unsigned_halving_add_sub_8 op2 rn rm | (T,Parallel_halving,_) => unsigned_halving_add_sub_16 op2 rn rm`; (* ------------------------------------------------------------------------ *) val barrier_option_def = Define` barrier_option (option:word4) = case option of 0b0010w => (MBReqDomain_OuterShareable, MBReqTypes_Writes) | 0b0011w => (MBReqDomain_OuterShareable, MBReqTypes_All) | 0b0110w => (MBReqDomain_Nonshareable, MBReqTypes_Writes) | 0b0111w => (MBReqDomain_Nonshareable, MBReqTypes_All) | 0b1010w => (MBReqDomain_InnerShareable, MBReqTypes_Writes) | 0b1011w => (MBReqDomain_InnerShareable, MBReqTypes_All) | 0b1110w => (MBReqDomain_FullSystem, MBReqTypes_Writes) | _ => (MBReqDomain_FullSystem, MBReqTypes_All)`; (* ------------------------------------------------------------------------ *) val exc_vector_base_def = Define` exc_vector_base ii : word32 M = read_sctlr ii >>= (\sctlr. if sctlr.V then constT 0xFFFF0000w else (have_security_ext ii >>= (\have_security_exta. if have_security_exta then read_vbar ii else constT 0w)))`; val take_reset_def = Define` take_reset ii = (exc_vector_base ii ||| have_security_ext ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(ExcVectorBase,have_security_exta,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10011w)) >>= (\(u1:unit,u2:unit). ((read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 0w)) >>= unit2))`; val take_undef_instr_exception_def = Define` take_undef_instr_exception ii = (read_reg ii 15w ||| exc_vector_base ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,ExcVectorBase,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b11011w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc - 2w else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 4w)) >>= unit4))`; val take_svc_exception_def = Define` take_svc_exception ii = IT_advance ii >>= (\u:unit. (read_reg ii 15w ||| exc_vector_base ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,ExcVectorBase,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10011w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc - 2w else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 8w)) >>= unit4)))`; val take_smc_exception_def = Define` take_smc_exception ii = IT_advance ii >>= (\u:unit. (read_reg ii 15w ||| read_mvbar ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,mvbar,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10110w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; F := T; A := T; IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (mvbar + 8w)) >>= unit4)))`; (* For now assume trap_to_monitor is false, i.e. no external aborts *) val take_prefetch_abort_exception_def = Define` take_prefetch_abort_exception ii = (read_reg ii 15w ||| exc_vector_base ii ||| have_security_ext ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,ExcVectorBase,have_security_exta,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10111w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; A := ((~have_security_exta \/ ~scr.NS \/ scr.AW) \/ cpsr.A); IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 12w)) >>= unit4))`; val take_data_abort_exception_def = Define` take_data_abort_exception ii = (read_reg ii 15w ||| exc_vector_base ii ||| have_security_ext ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,ExcVectorBase,have_security_exta,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10111w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; A := ((~have_security_exta \/ ~scr.NS \/ scr.AW) \/ cpsr.A); IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 16w)) >>= unit4))`; val take_irq_exception_def = Define` take_irq_exception ii = (read_reg ii 15w ||| exc_vector_base ii ||| have_security_ext ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,ExcVectorBase,have_security_exta,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10010w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; A := ((~have_security_exta \/ ~scr.NS \/ scr.AW) \/ cpsr.A); IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 24w)) >>= unit4))`; val take_fiq_exception_def = Define` take_fiq_exception ii = (read_reg ii 15w ||| exc_vector_base ii ||| have_security_ext ii ||| read_cpsr ii ||| read_scr ii ||| read_sctlr ii) >>= (\(pc,ExcVectorBase,have_security_exta,cpsr,scr,sctlr). (condT (cpsr.M = 0b10110w) (write_scr ii (scr with NS := F)) ||| write_cpsr ii (cpsr with M := 0b10001w)) >>= (\(u1:unit,u2:unit). (write_spsr ii cpsr ||| write_reg ii 14w (if cpsr.T then pc else pc - 4w) ||| (read_cpsr ii >>= (\cpsr. write_cpsr ii (cpsr with <| I := T; F := ((~have_security_exta \/ ~scr.NS \/ scr.AW) \/ cpsr.F); A := ((~have_security_exta \/ ~scr.NS \/ scr.AW) \/ cpsr.A); IT := 0b00000000w; J := F; T := sctlr.TE; E := sctlr.EE |>))) ||| branch_to ii (ExcVectorBase + 28w)) >>= unit4))`; (* ------------------------------------------------------------------------ *) val null_check_if_thumbee_def = Define` null_check_if_thumbEE ii n (f:unit M) = current_instr_set ii >>= (\iset. if iset = InstrSet_ThumbEE then read_reg ii n >>= (\rn. if n = 15w then if align (rn, 4) = 0w then errorT ("null_check_if_thumbEE PC: unpredictable") else f else if n = 13w then if rn = 0w then errorT ("null_check_if_thumbEE SP: unpredictable") else f else if rn = 0w then (read_reg ii 15w ||| read_cpsr ii ||| read_teehbr ii) >>= (\(pc,cpsr,teehbr). (write_reg ii 14w ((0 :+ T) pc) ||| write_cpsr ii (cpsr with IT := 0w)) >>= (\(u1:unit, u2:unit). branch_write_pc ii (teehbr - 4w))) else f) else f)`; val run_instruction_def = Define` run_instruction ii s n defined unpredictable c = read_info ii >>= (\info. if (info.arch,info.extensions) NOTIN defined then take_undef_instr_exception ii else if unpredictable (version_number info.arch) then errorT (s ++ ": unpredictable") else if IS_SOME n then null_check_if_thumbEE ii (THE n) c else c)`; val null_check_instruction_def = Define` null_check_instruction ii s n defined unpredictable c = run_instruction ii s (SOME n) defined unpredictable c`; val instruction_def = Define` instruction ii s defined unpredictable c = run_instruction ii s NONE defined unpredictable c`; val instructions = ref ([] : (string * thm) list); fun iDefine t = let val thm = zDefine t val name = (fst o dest_const o fst o strip_comb o lhs o concl o SPEC_ALL) thm val _ = instructions := (name,thm) :: !instructions in thm end; (* ........................................................................ T,A: B