summaryrefslogtreecommitdiff
path: root/aarch64_small/gen
diff options
context:
space:
mode:
authorChristopher Pulte2019-02-12 10:25:15 +0000
committerChristopher Pulte2019-02-12 10:25:15 +0000
commitb847a472a1f853d783d1af5f8eb033b97f33be5b (patch)
treefc095d2a48ea79ca0ca30a757f578f1973074b4f /aarch64_small/gen
parentc43a026cdbcca769096e46d4515db2fd566cbb33 (diff)
checking in in-progress translation of Shaked's handwritten sail1 ARM model to sail2
Diffstat (limited to 'aarch64_small/gen')
-rw-r--r--aarch64_small/gen/ast.hgen44
-rw-r--r--aarch64_small/gen/fold.hgen44
-rw-r--r--aarch64_small/gen/herdtools_ast_to_shallow_ast.hgen335
-rw-r--r--aarch64_small/gen/herdtools_types_to_shallow_types.hgen153
-rw-r--r--aarch64_small/gen/lexer.hgen309
-rw-r--r--aarch64_small/gen/map.hgen44
-rw-r--r--aarch64_small/gen/parser.hgen1403
-rw-r--r--aarch64_small/gen/pretty.hgen393
-rw-r--r--aarch64_small/gen/regs_out_in.hgen155
-rw-r--r--aarch64_small/gen/sail_trans_out.hgen326
-rw-r--r--aarch64_small/gen/shallow_ast_to_herdtools_ast.hgen326
-rw-r--r--aarch64_small/gen/shallow_types_to_herdtools_types.hgen154
-rw-r--r--aarch64_small/gen/token_types.hgen85
-rw-r--r--aarch64_small/gen/tokens.hgen78
-rw-r--r--aarch64_small/gen/trans_sail.hgen379
-rw-r--r--aarch64_small/gen/types.hgen90
-rw-r--r--aarch64_small/gen/types_sail_trans_out.hgen189
-rw-r--r--aarch64_small/gen/types_trans_sail.hgen119
18 files changed, 4626 insertions, 0 deletions
diff --git a/aarch64_small/gen/ast.hgen b/aarch64_small/gen/ast.hgen
new file mode 100644
index 00000000..60f130d7
--- /dev/null
+++ b/aarch64_small/gen/ast.hgen
@@ -0,0 +1,44 @@
+ | `AArch64TMStart of inst_reg (* t *)
+ | `AArch64TMCommit
+ | `AArch64TMAbort of boolean*bit5 (* retry,reason *)
+ | `AArch64TMTest
+
+ | `AArch64ImplementationDefinedTestBeginEnd of boolean (* isEnd *)
+ | `AArch64ImplementationDefinedStopFetching
+ | `AArch64ImplementationDefinedThreadStart
+ | `AArch64AddSubCarry of inst_reg*inst_reg*inst_reg*reg_size*boolean*boolean (* d,n,m,datasize,sub_op,setflags *)
+ | `AArch64AddSubExtendRegister of inst_reg*inst_reg*inst_reg*reg_size*boolean*boolean*extendType*range0_7 (* d,n,m,datasize,sub_op,setflags,extend_type,shift *)
+ | `AArch64AddSubShiftedRegister of inst_reg*inst_reg*inst_reg*reg_size*boolean*boolean*shiftType*range0_63 (* d,n,m,datasize,sub_op,setflags,shift_type,shift_amount *)
+ | `AArch64AddSubImmediate of inst_reg*inst_reg*reg_size*boolean*boolean*reg_size_bits (* d,n,datasize,sub_op,setflags,imm *)
+ | `AArch64Address of inst_reg*boolean*bit64 (* d,page,imm *)
+ | `AArch64LogicalImmediate of inst_reg*inst_reg*reg_size*boolean*logicalOp*reg_size_bits (* d,n,datasize,setflags,op,imm *)
+ | `AArch64LogicalShiftedRegister of inst_reg*inst_reg*inst_reg*reg_size*boolean*logicalOp*shiftType*range0_63*boolean (* d,n,m,datasize,setflags,op,shift_type,shift_amount,invert *)
+ | `AArch64Shift of inst_reg*inst_reg*inst_reg*reg_size*shiftType (* d,n,m,datasize,shift_type *)
+ | `AArch64BranchConditional of bit64*bit4 (* offset,condition *)
+ | `AArch64BranchImmediate of branchType*bit64 (* branch_type,offset *)
+ | `AArch64BitfieldMove of inst_reg*inst_reg*reg_size*boolean*boolean*uinteger*uinteger*reg_size_bits*reg_size_bits (* d,n,datasize,inzero,extend,R,S,wmask,tmask *)
+ | `AArch64BranchRegister of inst_reg*branchType (* n,branch_type *)
+ | `AArch64CompareAndBranch of inst_reg*reg_size*boolean*bit64 (* t,datasize,iszero,offset *)
+ | `AArch64ConditionalCompareImmediate of inst_reg*reg_size*boolean*bit4*bit4*reg_size_bits (* n,datasize,sub_op,condition,flags,imm *)
+ | `AArch64ConditionalCompareRegister of inst_reg*inst_reg*reg_size*boolean*bit4*bit4 (* n,m,datasize,sub_op,condition,flags *)
+ | `AArch64ClearExclusiveMonitor of uinteger (* imm *)
+ | `AArch64CountLeading of inst_reg*inst_reg*reg_size*countOp (* d,n,datasize,opcode *)
+ | `AArch64CRC of inst_reg*inst_reg*inst_reg*data_size*boolean (* d,n,m,size,crc32c *)
+ | `AArch64ConditionalSelect of inst_reg*inst_reg*inst_reg*reg_size*bit4*boolean*boolean (* d,n,m,datasize,condition,else_inv,else_inc *)
+ | `AArch64Barrier of memBarrierOp*mBReqDomain*mBReqTypes (* op,domain,types *)
+ | `AArch64ExtractRegister of inst_reg*inst_reg*inst_reg*reg_size*uinteger (* d,n,m,datasize,lsb *)
+ | `AArch64Hint of systemHintOp (* op *)
+ | `AArch64LoadStoreAcqExc of inst_reg*inst_reg*inst_reg*inst_reg*accType*boolean*boolean*memOp*uinteger*reg_size*data_size (* n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize *)
+ | `AArch64LoadStorePair of boolean*boolean*inst_reg*inst_reg*inst_reg*accType*memOp*boolean*data_size*bit64 (* wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset *)
+ | `AArch64LoadImmediate of inst_reg*inst_reg*accType*memOp*boolean*boolean*boolean*bit64*reg_size*data_size (* n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize *)
+ | `AArch64LoadLiteral of inst_reg*memOp*boolean*uinteger*bit64*data_size (* t,memop,signed,size,offset,datasize *)
+ | `AArch64LoadRegister of inst_reg*inst_reg*inst_reg*accType*memOp*boolean*boolean*boolean*extendType*uinteger*reg_size*data_size (* n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize *)
+ | `AArch64MultiplyAddSub of inst_reg*inst_reg*inst_reg*inst_reg*reg_size*data_size*boolean (* d,n,m,a,destsize,datasize,sub_op *)
+ | `AArch64MoveWide of inst_reg*reg_size*bit16*uinteger*moveWideOp (* d,datasize,imm,pos,opcode *)
+ | `AArch64Reverse of inst_reg*inst_reg*reg_size*revOp (* d,n,datasize,op *)
+ | `AArch64Division of inst_reg*inst_reg*inst_reg*reg_size*boolean (* d,n,m,datasize,unsigned *)
+ | `AArch64MultiplyAddSubLong of inst_reg*inst_reg*inst_reg*inst_reg*reg_size*data_size*boolean*boolean (* d,n,m,a,destsize,datasize,sub_op,unsigned *)
+ | `AArch64MultiplyHigh of inst_reg*inst_reg*inst_reg*inst_reg*reg_size*data_size*boolean (* d,n,m,a,destsize,datasize,unsigned *)
+ | `AArch64TestBitAndBranch of inst_reg*reg_size*uinteger*bit*bit64 (* t,datasize,bit_pos,bit_val,offset *)
+ | `AArch64MoveSystemRegister of inst_reg*uinteger*uinteger*uinteger*uinteger*uinteger*boolean (* t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read *)
+ | `AArch64MoveSystemImmediate of bit4*pSTATEField (* operand,field *)
diff --git a/aarch64_small/gen/fold.hgen b/aarch64_small/gen/fold.hgen
new file mode 100644
index 00000000..4062d8e6
--- /dev/null
+++ b/aarch64_small/gen/fold.hgen
@@ -0,0 +1,44 @@
+| `AArch64TMStart t -> fold_reg t (y_reg, y_sreg)
+| `AArch64TMCommit -> (y_reg, y_sreg)
+| `AArch64TMAbort (retry,reason) -> (y_reg, y_sreg)
+| `AArch64TMTest -> (y_reg, y_sreg)
+
+| `AArch64ImplementationDefinedStopFetching -> (y_reg, y_sreg)
+| `AArch64ImplementationDefinedThreadStart -> (y_reg, y_sreg)
+| `AArch64ImplementationDefinedTestBeginEnd (isEnd) -> (y_reg, y_sreg)
+| `AArch64AddSubCarry (d,n,m,datasize,sub_op,setflags) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64AddSubExtendRegister (d,n,m,datasize,sub_op,setflags,extend_type,shift) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64AddSubShiftedRegister (d,n,m,datasize,sub_op,setflags,shift_type,shift_amount) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64AddSubImmediate (d,n,datasize,sub_op,setflags,imm) -> fold_reg n (fold_reg d (y_reg, y_sreg))
+| `AArch64Address (d,page,imm) -> fold_reg d (y_reg, y_sreg)
+| `AArch64LogicalImmediate (d,n,datasize,setflags,op,imm) -> fold_reg n (fold_reg d (y_reg, y_sreg))
+| `AArch64LogicalShiftedRegister (d,n,m,datasize,setflags,op,shift_type,shift_amount,invert) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64Shift (d,n,m,datasize,shift_type) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64BranchConditional (offset,condition) -> (y_reg, y_sreg)
+| `AArch64BranchImmediate (branch_type,offset) -> (y_reg, y_sreg)
+| `AArch64BitfieldMove (d,n,datasize,inzero,extend,_R,_S,wmask,tmask) -> fold_reg n (fold_reg d (y_reg, y_sreg))
+| `AArch64BranchRegister (n,branch_type) -> fold_reg n (y_reg, y_sreg)
+| `AArch64CompareAndBranch (t,datasize,iszero,offset) -> fold_reg t (y_reg, y_sreg)
+| `AArch64ConditionalCompareImmediate (n,datasize,sub_op,condition,flags,imm) -> fold_reg n (y_reg, y_sreg)
+| `AArch64ConditionalCompareRegister (n,m,datasize,sub_op,condition,flags) -> fold_reg m (fold_reg n (y_reg, y_sreg))
+| `AArch64ClearExclusiveMonitor (imm) -> (y_reg, y_sreg)
+| `AArch64CountLeading (d,n,datasize,opcode) -> fold_reg n (fold_reg d (y_reg, y_sreg))
+| `AArch64CRC (d,n,m,size,crc32c) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64ConditionalSelect (d,n,m,datasize,condition,else_inv,else_inc) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64Barrier (op,domain,types) -> (y_reg, y_sreg)
+| `AArch64ExtractRegister (d,n,m,datasize,lsb) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64Hint (op) -> (y_reg, y_sreg)
+| `AArch64LoadStoreAcqExc (n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) -> fold_reg s (fold_reg t2 (fold_reg t (fold_reg n (y_reg, y_sreg))))
+| `AArch64LoadStorePair (wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset) -> fold_reg t2 (fold_reg t (fold_reg n (y_reg, y_sreg)))
+| `AArch64LoadImmediate (n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize) -> fold_reg t (fold_reg n (y_reg, y_sreg))
+| `AArch64LoadLiteral (t,memop,signed,size,offset,datasize) -> fold_reg t (y_reg, y_sreg)
+| `AArch64LoadRegister (n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize) -> fold_reg m (fold_reg t (fold_reg n (y_reg, y_sreg)))
+| `AArch64MultiplyAddSub (d,n,m,a,destsize,datasize,sub_op) -> fold_reg a (fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg))))
+| `AArch64MoveWide (d,datasize,imm,pos,opcode) -> fold_reg d (y_reg, y_sreg)
+| `AArch64Reverse (d,n,datasize,op) -> fold_reg n (fold_reg d (y_reg, y_sreg))
+| `AArch64Division (d,n,m,datasize,unsigned) -> fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg)))
+| `AArch64MultiplyAddSubLong (d,n,m,a,destsize,datasize,sub_op,unsigned) -> fold_reg a (fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg))))
+| `AArch64MultiplyHigh (d,n,m,a,destsize,datasize,unsigned) -> fold_reg a (fold_reg m (fold_reg n (fold_reg d (y_reg, y_sreg))))
+| `AArch64TestBitAndBranch (t,datasize,bit_pos,bit_val,offset) -> fold_reg t (y_reg, y_sreg)
+| `AArch64MoveSystemRegister (t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read) -> fold_reg t (y_reg, y_sreg)
+| `AArch64MoveSystemImmediate (operand,field) -> (y_reg, y_sreg)
diff --git a/aarch64_small/gen/herdtools_ast_to_shallow_ast.hgen b/aarch64_small/gen/herdtools_ast_to_shallow_ast.hgen
new file mode 100644
index 00000000..6fbb3eb2
--- /dev/null
+++ b/aarch64_small/gen/herdtools_ast_to_shallow_ast.hgen
@@ -0,0 +1,335 @@
+| `AArch64TMStart t -> TMStart (translate_reg "t" t)
+
+| `AArch64TMCommit -> TMCommit
+
+| `AArch64TMAbort (retry,reason) ->
+ TMAbort
+ (translate_boolean "retry" retry,
+ translate_bit5 "reason" reason)
+
+| `AArch64TMTest -> TMTest
+
+| `AArch64ImplementationDefinedStopFetching ->
+ ImplementationDefinedStopFetching
+
+| `AArch64ImplementationDefinedThreadStart ->
+ ImplementationDefinedThreadStart
+
+| `AArch64ImplementationDefinedTestBeginEnd(isEnd) ->
+ ImplementationDefinedTestBeginEnd
+ (translate_boolean "isEnd" isEnd)
+
+| `AArch64AddSubCarry(d,n,m,datasize,sub_op,setflags) ->
+ AddSubCarry
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_boolean "setflags" setflags)
+
+| `AArch64AddSubExtendRegister (d,n,m,datasize,sub_op,setflags,extend_type,shift) ->
+ AddSubExtendRegister
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_boolean "setflags" setflags,
+ translate_extendType "extend_type" extend_type,
+ translate_range0_7 "shift" shift)
+
+| `AArch64AddSubShiftedRegister (d,n,m,datasize,sub_op,setflags,shift_type,shift_amount) ->
+ AddSubShiftedRegister
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_boolean "setflags" setflags,
+ translate_shiftType "shift_type" shift_type,
+ translate_range0_63 "shift_amount" shift_amount)
+
+| `AArch64AddSubImmediate (d,n,datasize,sub_op,setflags,imm) ->
+ AddSubImmediate
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_boolean "setflags" setflags,
+ translate_reg_size_bits "imm" imm)
+
+| `AArch64Address (d,page,imm) ->
+ Address0
+ (translate_reg "d" d,
+ translate_boolean "page" page,
+ translate_bit64 "imm" imm)
+
+| `AArch64LogicalImmediate (d,n,datasize,setflags,op,imm) ->
+ LogicalImmediate
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "setflags" setflags,
+ translate_logicalOp "op" op,
+ translate_reg_size_bits "imm" imm)
+
+| `AArch64LogicalShiftedRegister (d,n,m,datasize,setflags,op,shift_type,shift_amount,invert) ->
+ LogicalShiftedRegister
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "setflags" setflags,
+ translate_logicalOp "op" op,
+ translate_shiftType "shift_type" shift_type,
+ translate_range0_63 "shift_amount" shift_amount,
+ translate_boolean "invert" invert)
+
+| `AArch64Shift (d,n,m,datasize,shift_type) ->
+ Shift
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_shiftType "shift_type" shift_type)
+
+| `AArch64BranchConditional (offset,condition) ->
+ BranchConditional
+ (translate_bit64 "offset" offset,
+ translate_bit4 "condition" condition)
+
+| `AArch64BranchImmediate (branch_type,offset) ->
+ BranchImmediate
+ (translate_branchType "branch_type" branch_type,
+ translate_bit64 "offset" offset)
+
+| `AArch64BitfieldMove (d,n,datasize,inzero,extend,_R,_S,wmask,tmask) ->
+ BitfieldMove
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "inzero" inzero,
+ translate_boolean "extend" extend,
+ translate_uinteger "_R" _R,
+ translate_uinteger "_S" _S,
+ translate_reg_size_bits "wmask" wmask,
+ translate_reg_size_bits "tmask" tmask)
+
+| `AArch64BranchRegister (n,branch_type) ->
+ BranchRegister
+ (translate_reg "n" n,
+ translate_branchType "branch_type" branch_type)
+
+| `AArch64CompareAndBranch (t,datasize,iszero,offset) ->
+ CompareAndBranch
+ (translate_reg "t" t,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "iszero" iszero,
+ translate_bit64 "offset" offset)
+
+| `AArch64ConditionalCompareImmediate (n,datasize,sub_op,condition,flags,imm) ->
+ ConditionalCompareImmediate
+ (translate_reg "n" n,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_bit4 "condition" condition,
+ translate_bit4 "flags" flags,
+ translate_reg_size_bits "imm" imm)
+
+| `AArch64ConditionalCompareRegister (n,m,datasize,sub_op,condition,flags) ->
+ ConditionalCompareRegister
+ (translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_bit4 "condition" condition,
+ translate_bit4 "flags" flags)
+
+| `AArch64ClearExclusiveMonitor (imm) ->
+ ClearExclusiveMonitor
+ (translate_uinteger "imm" imm)
+
+| `AArch64CountLeading (d,n,datasize,opcode) ->
+ CountLeading
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg_size "datasize" datasize,
+ translate_countOp "opcode" opcode)
+
+| `AArch64CRC (d,n,m,size,crc32c) ->
+ CRC
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_data_size "size" size,
+ translate_boolean "crc32c" crc32c)
+
+| `AArch64ConditionalSelect (d,n,m,datasize,condition,else_inv,else_inc) ->
+ ConditionalSelect
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_bit4 "condition" condition,
+ translate_boolean "else_inv" else_inv,
+ translate_boolean "else_inc" else_inc)
+
+| `AArch64Barrier (op,domain,types) ->
+ Barrier3
+ (translate_memBarrierOp "op" op,
+ translate_mBReqDomain "domain" domain,
+ translate_mBReqTypes "types" types)
+
+| `AArch64ExtractRegister (d,n,m,datasize,lsb) ->
+ ExtractRegister
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_uinteger "lsb" lsb)
+
+| `AArch64Hint (op) ->
+ Hint
+ (translate_systemHintOp "op" op)
+
+| `AArch64LoadStoreAcqExc (n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) ->
+ LoadStoreAcqExc
+ (translate_reg "n" n,
+ translate_reg "t" t,
+ translate_reg "t2" t2,
+ translate_reg "s" s,
+ translate_accType "acctype" acctype,
+ translate_boolean "excl" excl,
+ translate_boolean "pair" pair,
+ translate_memOp "memop" memop,
+ translate_uinteger "elsize" elsize,
+ translate_reg_size "regsize" regsize,
+ translate_data_size "datasize" datasize)
+
+| `AArch64LoadStorePair (wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset) ->
+ LoadStorePair
+ (translate_boolean "wback" wback,
+ translate_boolean "postindex" postindex,
+ translate_reg "n" n,
+ translate_reg "t" t,
+ translate_reg "t2" t2,
+ translate_accType "acctype" acctype,
+ translate_memOp "memop" memop,
+ translate_boolean "signed" signed,
+ translate_data_size "datasize" datasize,
+ translate_bit64 "offset" offset)
+
+| `AArch64LoadImmediate (n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize) ->
+ LoadImmediate
+ (translate_reg "n" n,
+ translate_reg "t" t,
+ translate_accType "acctype" acctype,
+ translate_memOp "memop" memop,
+ translate_boolean "signed" signed,
+ translate_boolean "wback" wback,
+ translate_boolean "postindex" postindex,
+ translate_bit64 "offset" offset,
+ translate_reg_size "regsize" regsize,
+ translate_data_size "datasize" datasize)
+
+| `AArch64LoadLiteral (t,memop,signed,size,offset,datasize) ->
+ LoadLiteral
+ (translate_reg "t" t,
+ translate_memOp "memop" memop,
+ translate_boolean "signed" signed,
+ translate_uinteger "size" size,
+ translate_bit64 "offset" offset,
+ translate_data_size "datasize" datasize)
+
+| `AArch64LoadRegister (n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize) ->
+ LoadRegister
+ (translate_reg "n" n,
+ translate_reg "t" t,
+ translate_reg "m" m,
+ translate_accType "acctype" acctype,
+ translate_memOp "memop" memop,
+ translate_boolean "signed" signed,
+ translate_boolean "wback" wback,
+ translate_boolean "postindex" postindex,
+ translate_extendType "extend_type" extend_type,
+ translate_uinteger "shift" shift,
+ translate_reg_size "regsize" regsize,
+ translate_data_size "datasize" datasize)
+
+| `AArch64MultiplyAddSub (d,n,m,a,destsize,datasize,sub_op) ->
+ MultiplyAddSub
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg "a" a,
+ translate_reg_size "destsize" destsize,
+ translate_data_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op)
+
+| `AArch64MoveWide (d,datasize,imm,pos,opcode) ->
+ MoveWide
+ (translate_reg "d" d,
+ translate_reg_size "datasize" datasize,
+ translate_bit16 "imm" imm,
+ translate_uinteger "pos" pos,
+ translate_moveWideOp "opcode" opcode)
+
+| `AArch64Reverse (d,n,datasize,op) ->
+ Reverse
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg_size "datasize" datasize,
+ translate_revOp "op" op)
+
+| `AArch64Division (d,n,m,datasize,unsigned) ->
+ Division
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg_size "datasize" datasize,
+ translate_boolean "unsigned" unsigned)
+
+| `AArch64MultiplyAddSubLong (d,n,m,a,destsize,datasize,sub_op,unsigned) ->
+ MultiplyAddSubLong
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg "a" a,
+ translate_reg_size "destsize" destsize,
+ translate_data_size "datasize" datasize,
+ translate_boolean "sub_op" sub_op,
+ translate_boolean "unsigned" unsigned)
+
+| `AArch64MultiplyHigh (d,n,m,a,destsize,datasize,unsigned) ->
+ MultiplyHigh
+ (translate_reg "d" d,
+ translate_reg "n" n,
+ translate_reg "m" m,
+ translate_reg "a" a,
+ translate_reg_size "destsize" destsize,
+ translate_data_size "datasize" datasize,
+ translate_boolean "unsigned" unsigned)
+
+| `AArch64TestBitAndBranch (t,datasize,bit_pos,bit_val,offset) ->
+ TestBitAndBranch
+ (translate_reg "t" t,
+ translate_reg_size "datasize" datasize,
+ translate_uinteger "bit_pos" bit_pos,
+ translate_bit "bit_val" bit_val,
+ translate_bit64 "offset" offset)
+
+| `AArch64MoveSystemRegister (t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read) ->
+ MoveSystemRegister
+ (translate_reg "t" t,
+ translate_uinteger "sys_op0" sys_op0,
+ translate_uinteger "sys_op1" sys_op1,
+ translate_uinteger "sys_op2" sys_op2,
+ translate_uinteger "sys_crn" sys_crn,
+ translate_uinteger "sys_crm" sys_crm,
+ translate_boolean "read" read)
+
+| `AArch64MoveSystemImmediate (operand,field) ->
+ MoveSystemImmediate
+ (translate_bit4 "operand" operand,
+ translate_pSTATEField "field" field)
diff --git a/aarch64_small/gen/herdtools_types_to_shallow_types.hgen b/aarch64_small/gen/herdtools_types_to_shallow_types.hgen
new file mode 100644
index 00000000..e14a37e3
--- /dev/null
+++ b/aarch64_small/gen/herdtools_types_to_shallow_types.hgen
@@ -0,0 +1,153 @@
+open Sail_values
+
+let is_inc = false
+
+let translate_big_int bits (name : string) value =
+ (name, Range0 (Some bits), IInt.bit_list_of_integer bits value)
+
+let translate_big_bit bits (name:string) value =
+ Sail_values.to_vec0 is_inc (Nat_big_num.of_int bits,value)
+
+let translate_int (size : int) (name:string) value = (Nat_big_num.of_int value)
+
+let translate_bits bits (name:string) value =
+ Sail_values.to_vec0 is_inc (Nat_big_num.of_int bits,Nat_big_num.of_int value)
+
+let translate_bool _ = function
+ | true -> B1
+ | false -> B0
+
+let translate_reg_size name value =
+ match value with
+ | Set32 -> (Nat_big_num.of_int 32)
+ | Set64 -> (Nat_big_num.of_int 64)
+
+let translate_reg name value =
+ (Nat_big_num.of_int (inst_reg_to_int value))
+
+
+let translate_reg_size_bits name value =
+ match value with
+ | R32Bits value -> translate_bits 32 name value
+ | R64Bits value -> translate_big_bit 64 name value
+
+let translate_data_size name value =
+ match value with
+ | DataSize8 -> (Nat_big_num.of_int 8)
+ | DataSize16 -> (Nat_big_num.of_int 16)
+ | DataSize32 -> (Nat_big_num.of_int 32)
+ | DataSize64 -> (Nat_big_num.of_int 64)
+
+let translate_reg_index = translate_int 5
+
+let translate_boolean = translate_bool
+
+let translate_range0_7 = translate_int 3
+
+let translate_range0_63 = translate_int 6
+
+let translate_bit64 = translate_big_bit 64
+
+let translate_bit4 = translate_bits 4
+let translate_bit5 = translate_bits 5
+let translate_bit16 = translate_bits 16
+
+let translate_bit = translate_bool
+
+let translate_range8_64 = translate_int 7
+
+let translate_uinteger = translate_int 63
+
+let translate_extendType _ = function
+ | ExtendType_UXTB -> ArmV8_embed_types.ExtendType_UXTB
+ | ExtendType_UXTH -> ArmV8_embed_types.ExtendType_UXTH
+ | ExtendType_UXTW -> ArmV8_embed_types.ExtendType_UXTW
+ | ExtendType_UXTX -> ArmV8_embed_types.ExtendType_UXTX
+ | ExtendType_SXTB -> ArmV8_embed_types.ExtendType_SXTB
+ | ExtendType_SXTH -> ArmV8_embed_types.ExtendType_SXTH
+ | ExtendType_SXTW -> ArmV8_embed_types.ExtendType_SXTW
+ | ExtendType_SXTX -> ArmV8_embed_types.ExtendType_SXTX
+
+let translate_shiftType _ = function
+ | ShiftType_LSL -> ArmV8_embed_types.ShiftType_LSL
+ | ShiftType_LSR -> ArmV8_embed_types.ShiftType_LSR
+ | ShiftType_ASR -> ArmV8_embed_types.ShiftType_ASR
+ | ShiftType_ROR -> ArmV8_embed_types.ShiftType_ROR
+
+let translate_logicalOp _ = function
+ | LogicalOp_AND -> ArmV8_embed_types.LogicalOp_AND
+ | LogicalOp_EOR -> ArmV8_embed_types.LogicalOp_EOR
+ | LogicalOp_ORR -> ArmV8_embed_types.LogicalOp_ORR
+
+let translate_branchType _ = function
+ | BranchType_CALL -> ArmV8_embed_types.BranchType_CALL
+ | BranchType_ERET -> ArmV8_embed_types.BranchType_ERET
+ | BranchType_DBGEXIT -> ArmV8_embed_types.BranchType_DBGEXIT
+ | BranchType_RET -> ArmV8_embed_types.BranchType_RET
+ | BranchType_JMP -> ArmV8_embed_types.BranchType_JMP
+ | BranchType_EXCEPTION -> ArmV8_embed_types.BranchType_EXCEPTION
+ | BranchType_UNKNOWN -> ArmV8_embed_types.BranchType_UNKNOWN
+
+let translate_countOp _ = function
+ | CountOp_CLZ -> ArmV8_embed_types.CountOp_CLZ
+ | CountOp_CLS -> ArmV8_embed_types.CountOp_CLS
+ | CountOp_CNT -> ArmV8_embed_types.CountOp_CNT
+
+let translate_memBarrierOp _ = function
+ | MemBarrierOp_DSB -> ArmV8_embed_types.MemBarrierOp_DSB
+ | MemBarrierOp_DMB -> ArmV8_embed_types.MemBarrierOp_DMB
+ | MemBarrierOp_ISB -> ArmV8_embed_types.MemBarrierOp_ISB
+
+let translate_mBReqDomain _ = function
+ | MBReqDomain_Nonshareable -> ArmV8_embed_types.MBReqDomain_Nonshareable
+ | MBReqDomain_InnerShareable -> ArmV8_embed_types.MBReqDomain_InnerShareable
+ | MBReqDomain_OuterShareable -> ArmV8_embed_types.MBReqDomain_OuterShareable
+ | MBReqDomain_FullSystem -> ArmV8_embed_types.MBReqDomain_FullSystem
+
+let translate_mBReqTypes _ = function
+ | MBReqTypes_Reads -> ArmV8_embed_types.MBReqTypes_Reads
+ | MBReqTypes_Writes -> ArmV8_embed_types.MBReqTypes_Writes
+ | MBReqTypes_All -> ArmV8_embed_types.MBReqTypes_All
+
+let translate_systemHintOp _ = function
+ | SystemHintOp_NOP -> ArmV8_embed_types.SystemHintOp_NOP
+ | SystemHintOp_YIELD -> ArmV8_embed_types.SystemHintOp_YIELD
+ | SystemHintOp_WFE -> ArmV8_embed_types.SystemHintOp_WFE
+ | SystemHintOp_WFI -> ArmV8_embed_types.SystemHintOp_WFI
+ | SystemHintOp_SEV -> ArmV8_embed_types.SystemHintOp_SEV
+ | SystemHintOp_SEVL -> ArmV8_embed_types.SystemHintOp_SEVL
+
+let translate_accType _ = function
+ | AccType_NORMAL -> ArmV8_embed_types.AccType_NORMAL
+ | AccType_VEC -> ArmV8_embed_types.AccType_VEC
+ | AccType_STREAM -> ArmV8_embed_types.AccType_STREAM
+ | AccType_VECSTREAM -> ArmV8_embed_types.AccType_VECSTREAM
+ | AccType_ATOMIC -> ArmV8_embed_types.AccType_ATOMIC
+ | AccType_ORDERED -> ArmV8_embed_types.AccType_ORDERED
+ | AccType_UNPRIV -> ArmV8_embed_types.AccType_UNPRIV
+ | AccType_IFETCH -> ArmV8_embed_types.AccType_IFETCH
+ | AccType_PTW -> ArmV8_embed_types.AccType_PTW
+ | AccType_DC -> ArmV8_embed_types.AccType_DC
+ | AccType_IC -> ArmV8_embed_types.AccType_IC
+ | AccType_AT -> ArmV8_embed_types.AccType_AT
+
+let translate_memOp _ = function
+ | MemOp_LOAD -> ArmV8_embed_types.MemOp_LOAD
+ | MemOp_STORE -> ArmV8_embed_types.MemOp_STORE
+ | MemOp_PREFETCH -> ArmV8_embed_types.MemOp_PREFETCH
+
+let translate_moveWideOp _ = function
+ | MoveWideOp_N -> ArmV8_embed_types.MoveWideOp_N
+ | MoveWideOp_Z -> ArmV8_embed_types.MoveWideOp_Z
+ | MoveWideOp_K -> ArmV8_embed_types.MoveWideOp_K
+
+let translate_revOp _ = function
+ | RevOp_RBIT -> ArmV8_embed_types.RevOp_RBIT
+ | RevOp_REV16 -> ArmV8_embed_types.RevOp_REV16
+ | RevOp_REV32 -> ArmV8_embed_types.RevOp_REV32
+ | RevOp_REV64 -> ArmV8_embed_types.RevOp_REV64
+
+let translate_pSTATEField _ = function
+ | PSTATEField_DAIFSet -> ArmV8_embed_types.PSTATEField_DAIFSet
+ | PSTATEField_DAIFClr -> ArmV8_embed_types.PSTATEField_DAIFClr
+ | PSTATEField_SP -> ArmV8_embed_types.PSTATEField_SP
diff --git a/aarch64_small/gen/lexer.hgen b/aarch64_small/gen/lexer.hgen
new file mode 100644
index 00000000..6ff24317
--- /dev/null
+++ b/aarch64_small/gen/lexer.hgen
@@ -0,0 +1,309 @@
+(* instructions: *)
+
+ "TSTART" , TSTART {txt="TSTART"} ;
+ "TCOMMIT", TCOMMIT {txt="TCOMMIT"} ;
+ "TABORT" , TABORT {txt="TABORT"} ;
+ "TTEST" , TTEST {txt="TTEST"} ;
+
+ "ADC" , ADCSBC {txt="ADC"; sub_op = false; setflags = false} ;
+ "SBC" , ADCSBC {txt="SBC"; sub_op = true; setflags = false} ;
+ "ADCS" , ADCSBC {txt="ADCS"; sub_op = false; setflags = true} ;
+ "SBCS" , ADCSBC {txt="SBCS"; sub_op = true; setflags = true} ;
+
+ "ADD" , ADDSUB {txt="ADD"; sub_op=false; setflags=false} ;
+ "SUB" , ADDSUB {txt="SUB"; sub_op=true; setflags=false} ;
+ "ADDS" , ADDSUB {txt="ADDS"; sub_op=false; setflags=true} ;
+ "SUBS" , ADDSUB {txt="SUBS"; sub_op=true; setflags=true} ;
+
+ "ADR" , ADR {txt="ADR"; page=false} ;
+ "ADRP" , ADR {txt="ADRP"; page=true} ;
+
+ "AND" , LOGOP {txt="AND"; op = LogicalOp_AND; setflags = false; invert = false} ;
+ "ANDS" , LOGOP {txt="ANDS"; op = LogicalOp_AND; setflags = true; invert = false} ;
+ "EOR" , LOGOP {txt="EOR"; op = LogicalOp_EOR; setflags = false; invert = false} ;
+ "ORR" , LOGOP {txt="ORR"; op = LogicalOp_ORR; setflags = false; invert = false} ;
+ "BIC" , LOGOP {txt="BIC"; op = LogicalOp_AND; setflags = false; invert = true} ;
+ "BICS" , LOGOP {txt="BICS"; op = LogicalOp_AND; setflags = true; invert = true} ;
+ "EON" , LOGOP {txt="EON"; op = LogicalOp_EOR; setflags = false; invert = true} ;
+ "ORN" , LOGOP {txt="ORN"; op = LogicalOp_ORR; setflags = false; invert = true} ;
+
+ "ASRV" , SHIFTOP {txt="ASRV"; shift_type=ShiftType_ASR} ;
+ "LSLV" , SHIFTOP {txt="LSLV"; shift_type=ShiftType_LSL} ;
+ "LSRV" , SHIFTOP {txt="LSRV"; shift_type=ShiftType_LSR} ;
+ "RORV" , SHIFTOP {txt="RORV"; shift_type=ShiftType_ROR} ;
+
+ "B.EQ" , BCOND {txt="B.EQ"; condition=0b0000} ;
+ "B.NE" , BCOND {txt="B.NE"; condition=0b0001} ;
+ "B.CS" , BCOND {txt="B.CS"; condition=0b0010} ;
+ "B.HS" , BCOND {txt="B.CS"; condition=0b0010} ;
+ "B.CC" , BCOND {txt="B.CC"; condition=0b0011} ;
+ "B.LO" , BCOND {txt="B.CC"; condition=0b0011} ;
+ "B.MI" , BCOND {txt="B.MI"; condition=0b0100} ;
+ "B.PL" , BCOND {txt="B.PL"; condition=0b0101} ;
+ "B.VS" , BCOND {txt="B.VS"; condition=0b0110} ;
+ "B.VC" , BCOND {txt="B.VC"; condition=0b0111} ;
+ "B.HI" , BCOND {txt="B.HI"; condition=0b1000} ;
+ "B.LS" , BCOND {txt="B.LS"; condition=0b1001} ;
+ "B.GE" , BCOND {txt="B.GE"; condition=0b1010} ;
+ "B.LT" , BCOND {txt="B.LT"; condition=0b1011} ;
+ "B.GT" , BCOND {txt="B.GT"; condition=0b1100} ;
+ "B.LE" , BCOND {txt="B.LE"; condition=0b1101} ;
+ "B.AL" , BCOND {txt="B.AL"; condition=0b1110} ;
+ "B.NV" , BCOND {txt="B.NV"; condition=0b1111} ; (* ARM: exists only to provide a valid disassembly
+ of the 0b1111 encoding, otherwise its
+ behavior is identical to AL *)
+
+ "B" , B {txt="B"; branch_type=BranchType_JMP} ;
+ "BL" , B {txt="BL"; branch_type=BranchType_CALL} ;
+
+ "BR" , BR {txt="BR"; branch_type=BranchType_JMP} ;
+ "BLR" , BR {txt="BLR"; branch_type=BranchType_CALL} ;
+
+ "CBZ" , CBZ {txt="CBZ"; iszero=true} ;
+ "CBNZ" , CBZ {txt="CBNZ"; iszero=false} ;
+
+ "BFM" , BFM {txt="BFM"; inzero=false; extend=false} ;
+ "SBFM" , BFM {txt="SBFM"; inzero=true; extend=true} ;
+ "UBFM" , BFM {txt="UBFM"; inzero=true; extend=false} ;
+
+ "CCMN" , CCM {txt="CCMN"; sub_op=false} ;
+ "CCMP" , CCM {txt="CCMP"; sub_op=true} ;
+
+ "CMN" , CM {txt="CMN"; sub_op=false} ;
+ "CMP" , CM {txt="CMP"; sub_op=true} ;
+
+ "CLS" , CL {txt="CLS"; opcode=CountOp_CLS} ;
+ "CLZ" , CL {txt="CLZ"; opcode=CountOp_CLZ} ;
+
+ "CRC32B" , CRC {txt="CRC32B"; size = DataSize8; crc32c = false} ;
+ "CRC32H" , CRC {txt="CRC32H"; size = DataSize16; crc32c = false} ;
+ "CRC32W" , CRC {txt="CRC32W"; size = DataSize32; crc32c = false} ;
+ "CRC32CB" , CRC {txt="CRC32CB"; size = DataSize8; crc32c = true} ;
+ "CRC32CH" , CRC {txt="CRC32CH"; size = DataSize16; crc32c = true} ;
+ "CRC32CW" , CRC {txt="CRC32CW"; size = DataSize32; crc32c = true} ;
+
+ "CRC32X" , CRC32X {txt="CRC32X"; crc32c=false} ;
+ "CRC32CX" , CRC32X {txt="CRC32CX"; crc32c=true} ;
+
+ "CSEL" , CSEL {txt="CSEL"; else_inv = false; else_inc = false} ;
+ "CSINC" , CSEL {txt="CSINC"; else_inv = false; else_inc = true} ;
+ "CSINV" , CSEL {txt="CSINV"; else_inv = true; else_inc = false} ;
+ "CSNEG" , CSEL {txt="CSNEG"; else_inv = true; else_inc = true} ;
+
+ "CSET" , CSET {txt="CSET"; else_inv = false; else_inc = true} ;
+ "CSETM" , CSETM {txt="CSETM"; else_inv = true; else_inc = false} ;
+
+ "CINC" , CON {txt="CINC"; else_inv = false; else_inc = true} ;
+ "CINV" , CON {txt="CINV"; else_inv = true; else_inc = false} ;
+ "CNEG" , CON {txt="CNEG"; else_inv = true; else_inc = true} ;
+
+ "DMB" , MEMBARR {txt="DMB"; op=MemBarrierOp_DMB} ;
+ "DSB" , MEMBARR {txt="DSB"; op=MemBarrierOp_DSB} ;
+
+ "LDAR" , LDAXR {txt="LDAR"; acctype=AccType_ORDERED; excl=false; memop=MemOp_LOAD; var32={elsize=32; datasize=DataSize32}; var64=true} ;
+ "LDARB" , LDAXR {txt="LDARB"; acctype=AccType_ORDERED; excl=false; memop=MemOp_LOAD; var32={elsize=8; datasize=DataSize8}; var64=false} ;
+ "LDARH" , LDAXR {txt="LDARH"; acctype=AccType_ORDERED; excl=false; memop=MemOp_LOAD; var32={elsize=16; datasize=DataSize16}; var64=false} ;
+ "LDAXR" , LDAXR {txt="LDAXR"; acctype=AccType_ORDERED; excl=true; memop=MemOp_LOAD; var32={elsize=32; datasize=DataSize32}; var64=true} ;
+ "LDAXRB" , LDAXR {txt="LDAXRB"; acctype=AccType_ORDERED; excl=true; memop=MemOp_LOAD; var32={elsize=8; datasize=DataSize8}; var64=false} ;
+ "LDAXRH" , LDAXR {txt="LDAXRH"; acctype=AccType_ORDERED; excl=true; memop=MemOp_LOAD; var32={elsize=16; datasize=DataSize16}; var64=false} ;
+ "LDXR" , LDAXR {txt="LDXR"; acctype=AccType_ATOMIC; excl=true; memop=MemOp_LOAD; var32={elsize=32; datasize=DataSize32}; var64=true} ;
+ "LDXRB" , LDAXR {txt="LDXRB"; acctype=AccType_ATOMIC; excl=true; memop=MemOp_LOAD; var32={elsize=8; datasize=DataSize8}; var64=false} ;
+ "LDXRH" , LDAXR {txt="LDXRH"; acctype=AccType_ATOMIC; excl=true; memop=MemOp_LOAD; var32={elsize=16; datasize=DataSize16}; var64=false} ;
+ "STLR" , LDAXR {txt="STLR"; acctype=AccType_ORDERED; excl=false; memop=MemOp_STORE; var32={elsize=32; datasize=DataSize32}; var64=true} ;
+ "STLRB" , LDAXR {txt="STLRB"; acctype=AccType_ORDERED; excl=false; memop=MemOp_STORE; var32={elsize=8; datasize=DataSize8}; var64=false} ;
+ "STLRH" , LDAXR {txt="STLRH"; acctype=AccType_ORDERED; excl=false; memop=MemOp_STORE; var32={elsize=16; datasize=DataSize16}; var64=false} ;
+
+ "STLXR" , STLXR {txt="STLXR"; acctype=AccType_ORDERED; var32={elsize=32; datasize=DataSize32}; var64=true} ;
+ "STLXRB" , STLXR {txt="STLXRB"; acctype=AccType_ORDERED; var32={elsize=8; datasize=DataSize8}; var64=false} ;
+ "STLXRH" , STLXR {txt="STLXRH"; acctype=AccType_ORDERED; var32={elsize=16; datasize=DataSize16}; var64=false} ;
+ "STXR" , STLXR {txt="STXR"; acctype=AccType_ATOMIC; var32={elsize=32; datasize=DataSize32}; var64=true} ;
+ "STXRB" , STLXR {txt="STXRB"; acctype=AccType_ATOMIC; var32={elsize=8; datasize=DataSize8}; var64=false} ;
+ "STXRH" , STLXR {txt="STXRH"; acctype=AccType_ATOMIC; var32={elsize=16; datasize=DataSize16}; var64=false} ;
+
+
+ "LDAXP" , LDXP {txt="LDAXP"; acctype=AccType_ORDERED} ;
+ "LDXP" , LDXP {txt="LDXP"; acctype=AccType_ATOMIC} ;
+
+ "STLXP" , STXP {txt="STLXP"; acctype=AccType_ORDERED} ;
+ "STXP" , STXP {txt="STXP"; acctype=AccType_ATOMIC} ;
+
+ "LDR" , LDSTR {txt="LDR"; memop=MemOp_LOAD; signed=false; lit32=true; var32=Some {datasize=DataSize32}; var64=Some {datasize=DataSize64}; lit64=Some {datasize=DataSize64; size=8}} ;
+ "LDRB" , LDSTR {txt="LDRB"; memop=MemOp_LOAD; signed=false; lit32=false; var32=Some {datasize=DataSize8}; var64=None; lit64=None} ;
+ "LDRH" , LDSTR {txt="LDRH"; memop=MemOp_LOAD; signed=false; lit32=false; var32=Some {datasize=DataSize16}; var64=None; lit64=None} ;
+ "LDRSB" , LDSTR {txt="LDRSB"; memop=MemOp_LOAD; signed=true; lit32=false; var32=Some {datasize=DataSize8}; var64=Some {datasize=DataSize8}; lit64=None} ;
+ "LDRSH" , LDSTR {txt="LDRSH"; memop=MemOp_LOAD; signed=true; lit32=false; var32=Some {datasize=DataSize16}; var64=Some {datasize=DataSize16}; lit64=None} ;
+ "LDRSW" , LDSTR {txt="LDRSW"; memop=MemOp_LOAD; signed=true; lit32=false; var32=None; var64=Some {datasize=DataSize32}; lit64=Some {datasize=DataSize32; size=4}} ;
+ "STR" , LDSTR {txt="STR"; memop=MemOp_STORE; signed=false; lit32=false; var32=Some {datasize=DataSize32}; var64=Some {datasize=DataSize64}; lit64=None} ;
+ "STRB" , LDSTR {txt="STRB"; memop=MemOp_STORE; signed=false; lit32=false; var32=Some {datasize=DataSize8}; var64=None; lit64=None} ;
+ "STRH" , LDSTR {txt="STRH"; memop=MemOp_STORE; signed=false; lit32=false; var32=Some {datasize=DataSize16}; var64=None; lit64=None} ;
+
+ "LDTR" , LDSTTUR {txt="LDTR"; memop=MemOp_LOAD; acctype=AccType_UNPRIV; signed=false; off32=Some {datasize=DataSize32}; off64=Some {datasize=DataSize64}} ;
+ "LDTRB" , LDSTTUR {txt="LDTRB"; memop=MemOp_LOAD; acctype=AccType_UNPRIV; signed=false; off32=Some {datasize=DataSize8}; off64=None} ;
+ "LDTRH" , LDSTTUR {txt="LDTRH"; memop=MemOp_LOAD; acctype=AccType_UNPRIV; signed=false; off32=Some {datasize=DataSize16}; off64=None} ;
+ "LDTRSB" , LDSTTUR {txt="LDTRSB"; memop=MemOp_LOAD; acctype=AccType_UNPRIV; signed=true; off32=Some {datasize=DataSize8}; off64=Some {datasize=DataSize8}} ;
+ "LDTRSH" , LDSTTUR {txt="LDTRSH"; memop=MemOp_LOAD; acctype=AccType_UNPRIV; signed=true; off32=Some {datasize=DataSize16}; off64=Some {datasize=DataSize16}} ;
+ "LDTRSW" , LDSTTUR {txt="LDTRSW"; memop=MemOp_LOAD; acctype=AccType_UNPRIV; signed=true; off32=None; off64=Some {datasize=DataSize32}} ;
+ "LDUR" , LDSTTUR {txt="LDUR"; memop=MemOp_LOAD; acctype=AccType_NORMAL; signed=false; off32=Some {datasize=DataSize32}; off64=Some {datasize=DataSize64}} ;
+ "LDURB" , LDSTTUR {txt="LDURB"; memop=MemOp_LOAD; acctype=AccType_NORMAL; signed=false; off32=Some {datasize=DataSize8}; off64=None} ;
+ "LDURH" , LDSTTUR {txt="LDURH"; memop=MemOp_LOAD; acctype=AccType_NORMAL; signed=false; off32=Some {datasize=DataSize16}; off64=None} ;
+ "LDURSB" , LDSTTUR {txt="LDURSB"; memop=MemOp_LOAD; acctype=AccType_NORMAL; signed=true; off32=Some {datasize=DataSize8}; off64=Some {datasize=DataSize8}} ;
+ "LDURSH" , LDSTTUR {txt="LDURSH"; memop=MemOp_LOAD; acctype=AccType_NORMAL; signed=true; off32=Some {datasize=DataSize16}; off64=Some {datasize=DataSize16}} ;
+ "LDURSW" , LDSTTUR {txt="LDURSW"; memop=MemOp_LOAD; acctype=AccType_NORMAL; signed=true; off32=None; off64=Some {datasize=DataSize32}} ;
+ "STTR" , LDSTTUR {txt="STTR"; memop=MemOp_STORE; acctype=AccType_UNPRIV; signed=false; off32=Some {datasize=DataSize32}; off64=Some {datasize=DataSize64}} ;
+ "STTRB" , LDSTTUR {txt="STTRB"; memop=MemOp_STORE; acctype=AccType_UNPRIV; signed=false; off32=Some {datasize=DataSize8}; off64=None} ;
+ "STTRH" , LDSTTUR {txt="STTRH"; memop=MemOp_STORE; acctype=AccType_UNPRIV; signed=false; off32=Some {datasize=DataSize16}; off64=None} ;
+ "STUR" , LDSTTUR {txt="STUR"; memop=MemOp_STORE; acctype=AccType_NORMAL; signed=false; off32=Some {datasize=DataSize32}; off64=Some {datasize=DataSize64}} ;
+ "STURB" , LDSTTUR {txt="STURB"; memop=MemOp_STORE; acctype=AccType_NORMAL; signed=false; off32=Some {datasize=DataSize8}; off64=None} ;
+ "STURH" , LDSTTUR {txt="STURH"; memop=MemOp_STORE; acctype=AccType_NORMAL; signed=false; off32=Some {datasize=DataSize16}; off64=None} ;
+
+ "MADD" , MADDSUB {txt="MADD"; sub_op=false} ;
+ "MSUB" , MADDSUB {txt="MSUB"; sub_op=true} ;
+
+ "MUL" , MUL {txt="MUL"; sub_op=false} ;
+ "MNEG" , MUL {txt="MNEG"; sub_op=true} ;
+
+ "MOVK" , MOVWIDE {txt="MOVK"; opcode=MoveWideOp_K} ;
+ "MOVN" , MOVWIDE {txt="MOVN"; opcode=MoveWideOp_N} ;
+ "MOVZ" , MOVWIDE {txt="MOVZ"; opcode=MoveWideOp_Z} ;
+
+ "NEG" , NEG {txt="NEG"; setflags=false} ;
+ "NEGS" , NEG {txt="NEGS"; setflags=true} ;
+
+ "NGC" , NGC {txt="NGC"; setflags=false} ;
+ "NGCS" , NGC {txt="NGCS"; setflags=true} ;
+
+ "RBIT" , REV {txt="RBIT"; op32=Some RevOp_RBIT; op64=RevOp_RBIT} ;
+ "REV" , REV {txt="REV"; op32=Some RevOp_REV32; op64=RevOp_REV64} ;
+ "REV16" , REV {txt="REV16"; op32=Some RevOp_REV16; op64=RevOp_REV16} ;
+ "REV32" , REV {txt="REV32"; op32=None; op64=RevOp_REV32} ;
+
+ "SDIV" , DIV {txt="SDIV"; unsigned=false} ;
+ "UDIV" , DIV {txt="UDIV"; unsigned=true} ;
+
+ "SMADDL" , MADDSUBL {txt="SMADDL"; sub_op=false; unsigned=false} ;
+ "SMSUBL" , MADDSUBL {txt="SMSUBL"; sub_op=true; unsigned=false} ;
+ "UMADDL" , MADDSUBL {txt="UMADDL"; sub_op=false; unsigned=true} ;
+ "UMSUBL" , MADDSUBL {txt="UMSUBL"; sub_op=true; unsigned=true} ;
+
+ "SMULH" , MULH {txt="SMULH"; unsigned=false} ;
+ "UMULH" , MULH {txt="UMULH"; unsigned=true} ;
+
+ "SMULL" , MULL {txt="SMULL"; unsigned=false} ;
+ "UMULL" , MULL {txt="UMULL"; unsigned=true} ;
+
+ "LDP" , LDSTP {txt="LDP"; memop=MemOp_LOAD} ;
+ "STP" , LDSTP {txt="STP"; memop=MemOp_STORE} ;
+
+ "TBZ" , TBZ {txt="TBZ"; bit_val=false} ;
+ "TBNZ" , TBZ {txt="TBNZ"; bit_val=true} ;
+
+ "SBFIZ" , BFIZ {txt="SBFIZ"; extend=true} ;
+ "UBFIZ" , BFIZ {txt="UBFIZ"; extend=false} ;
+
+ "SBFX" , BFX {txt="SBFX"; extend=true} ;
+ "UBFX" , BFX {txt="UBFX"; extend=false} ;
+
+ "SMNEGL" , MNEGL {txt="SMNEGL"; unsigned=false} ;
+ "UMNEGL" , MNEGL {txt="UMNEGL"; unsigned=true} ;
+
+ "BFI" , BFI {txt="BFI"} ;
+ "BFXIL" , BFXIL {txt="BFXIL"} ;
+ "CLREX" , CLREX {txt="CLREX"} ;
+ "EXTR" , EXTR {txt="EXTR"} ;
+ "HINT" , HINT {txt="HINT"} ;
+ "ISB" , ISB {txt="ISB"} ;
+ "LDPSW" , LDPSW {txt="LDPSW"} ;
+ "MOV" , MOV {txt="MOV"} ;
+ "MVN" , MVN {txt="MVN"} ;
+ "NOP" , NOP {txt="NOP"} ;
+ "PRFM" , PRFM {txt="PRFM"} ;
+ "PRFUM" , PRFUM {txt="PRFUM"} ;
+ "RET" , RET {txt="RET"} ;
+ "TST" , TST {txt="TST"} ;
+ "MRS" , MRS {txt="MRS"} ;
+ "MSR" , MSR {txt="MSR"} ;
+
+
+(*** instructions/operands ***)
+
+ "LSL" , SHIFT {txt="LSL"; shift_type=ShiftType_LSL} ;
+ "LSR" , SHIFT {txt="LSR"; shift_type=ShiftType_LSR} ;
+ "ASR" , SHIFT {txt="ASR"; shift_type=ShiftType_ASR} ;
+ "ROR" , SHIFT {txt="ROR"; shift_type=ShiftType_ROR} ;
+
+ "UXTB" , EXTEND {txt="UXTB"; _type=ExtendType_UXTB; inst=Some {extend=false; imms=7}} ;
+ "UXTH" , EXTEND {txt="UXTH"; _type=ExtendType_UXTH; inst=Some {extend=false; imms=15}} ;
+ "UXTW" , EXTEND {txt="UXTW"; _type=ExtendType_UXTW; inst=None} ;
+ "UXTX" , EXTEND {txt="UXTX"; _type=ExtendType_UXTX; inst=None} ;
+ "SXTB" , EXTEND {txt="SXTB"; _type=ExtendType_SXTB; inst=Some {extend=true; imms=7}} ;
+ "SXTH" , EXTEND {txt="SXTH"; _type=ExtendType_SXTH; inst=Some {extend=true; imms=15}} ;
+ "SXTW" , EXTEND {txt="SXTW"; _type=ExtendType_SXTW; inst=Some {extend=true; imms=31}} ;
+ "SXTX" , EXTEND {txt="SXTX"; _type=ExtendType_SXTX; inst=None} ;
+
+(*** operands: ***)
+
+ "EQ" , COND 0b0000 ;
+ "NE" , COND 0b0001 ;
+ "CS" , COND 0b0010 ;
+ "HS" , COND 0b0010 ;
+ "CC" , COND 0b0011 ;
+ "LO" , COND 0b0011 ;
+ "MI" , COND 0b0100 ;
+ "PL" , COND 0b0101 ;
+ "VS" , COND 0b0110 ;
+ "VC" , COND 0b0111 ;
+ "HI" , COND 0b1000 ;
+ "LS" , COND 0b1001 ;
+ "GE" , COND 0b1010 ;
+ "LT" , COND 0b1011 ;
+ "GT" , COND 0b1100 ;
+ "LE" , COND 0b1101 ;
+ "AL" , COND 0b1110 ;
+ "NV" , COND 0b1111 ; (* ARM: exists only to provide a valid disassembly
+ of the 0b1111 encoding, otherwise its
+ behavior is identical to AL *)
+
+ "OSHLD" , BARROP {domain=MBReqDomain_OuterShareable; types=MBReqTypes_Reads} ;
+ "OSHST" , BARROP {domain=MBReqDomain_OuterShareable; types=MBReqTypes_Writes} ;
+ "OSH" , BARROP {domain=MBReqDomain_OuterShareable; types=MBReqTypes_All} ;
+ "NSHLD" , BARROP {domain=MBReqDomain_Nonshareable; types=MBReqTypes_Reads} ;
+ "NSHST" , BARROP {domain=MBReqDomain_Nonshareable; types=MBReqTypes_Writes} ;
+ "NSH" , BARROP {domain=MBReqDomain_Nonshareable; types=MBReqTypes_All} ;
+ "ISHLD" , BARROP {domain=MBReqDomain_InnerShareable; types=MBReqTypes_Reads} ;
+ "ISHST" , BARROP {domain=MBReqDomain_InnerShareable; types=MBReqTypes_Writes} ;
+ "ISH" , BARROP {domain=MBReqDomain_InnerShareable; types=MBReqTypes_All} ;
+ "LD" , BARROP {domain=MBReqDomain_FullSystem; types=MBReqTypes_Reads} ;
+ "ST" , BARROP {domain=MBReqDomain_FullSystem; types=MBReqTypes_Writes} ;
+ "SY" , BARROP {domain=MBReqDomain_FullSystem; types=MBReqTypes_All} ;
+
+ "PLDL1KEEP" , PRFOP (X (Ireg R0)) ;
+ "PLDL1STRM" , PRFOP (X (Ireg R1)) ;
+ "PLDL2KEEP" , PRFOP (X (Ireg R2)) ;
+ "PLDL2STRM" , PRFOP (X (Ireg R3)) ;
+ "PLDL3KEEP" , PRFOP (X (Ireg R4)) ;
+ "PLDL3STRM" , PRFOP (X (Ireg R5)) ;
+
+ "PLIL1KEEP" , PRFOP (X (Ireg R8)) ;
+ "PLIL1STRM" , PRFOP (X (Ireg R9)) ;
+ "PLIL2KEEP" , PRFOP (X (Ireg R10)) ;
+ "PLIL2STRM" , PRFOP (X (Ireg R11)) ;
+ "PLIL3KEEP" , PRFOP (X (Ireg R12)) ;
+ "PLIL3STRM" , PRFOP (X (Ireg R13)) ;
+
+ "PSTL1KEEP" , PRFOP (X (Ireg R16)) ;
+ "PSTL1STRM" , PRFOP (X (Ireg R17)) ;
+ "PSTL2KEEP" , PRFOP (X (Ireg R18)) ;
+ "PSTL2STRM" , PRFOP (X (Ireg R19)) ;
+ "PSTL3KEEP" , PRFOP (X (Ireg R20)) ;
+ "PSTL3STRM" , PRFOP (X (Ireg R21)) ;
+
+ "NZCV" , SYSREG {sys_op0=0b11; sys_op1=0b011; sys_op2=0b000; sys_crn=0b0100; sys_crm=0b0010} ;
+ "DAIF" , SYSREG {sys_op0=0b11; sys_op1=0b011; sys_op2=0b001; sys_crn=0b0100; sys_crm=0b0010} ;
+ "TPIDR_EL0" , SYSREG {sys_op0=0b11; sys_op1=0b011; sys_op2=0b010; sys_crn=0b1101; sys_crm=0b0000} ;
+ "TPIDR_EL1" , SYSREG {sys_op0=0b11; sys_op1=0b000; sys_op2=0b100; sys_crn=0b1101; sys_crm=0b0000} ;
+ "TPIDR_EL2" , SYSREG {sys_op0=0b11; sys_op1=0b100; sys_op2=0b010; sys_crn=0b1101; sys_crm=0b0000} ;
+ "TPIDR_EL3" , SYSREG {sys_op0=0b11; sys_op1=0b011; sys_op2=0b011; sys_crn=0b1101; sys_crm=0b0000} ;
+
+ "SPSel" , PSTATEFIELD (PSTATEField_SP) ;
+ "DAIFSet" , PSTATEFIELD (PSTATEField_DAIFSet) ;
+ "DAIFClr" , PSTATEFIELD (PSTATEField_DAIFClr) ;
diff --git a/aarch64_small/gen/map.hgen b/aarch64_small/gen/map.hgen
new file mode 100644
index 00000000..62899c91
--- /dev/null
+++ b/aarch64_small/gen/map.hgen
@@ -0,0 +1,44 @@
+| `AArch64TMStart t -> `AArch64TMStart (map_reg t)
+| `AArch64TMCommit -> `AArch64TMCommit
+| `AArch64TMAbort (retry,reason) -> `AArch64TMAbort (retry,reason)
+| `AArch64TMTest -> `AArch64TMTest
+
+| `AArch64ImplementationDefinedStopFetching -> `AArch64ImplementationDefinedStopFetching
+| `AArch64ImplementationDefinedThreadStart -> `AArch64ImplementationDefinedThreadStart
+| `AArch64ImplementationDefinedTestBeginEnd (isEnd) -> `AArch64ImplementationDefinedTestBeginEnd (isEnd)
+| `AArch64AddSubCarry (d,n,m,datasize,sub_op,setflags) -> `AArch64AddSubCarry (map_reg d,map_reg n,map_reg m,datasize,sub_op,setflags)
+| `AArch64AddSubExtendRegister (d,n,m,datasize,sub_op,setflags,extend_type,shift) -> `AArch64AddSubExtendRegister (map_reg d,map_reg n,map_reg m,datasize,sub_op,setflags,extend_type,shift)
+| `AArch64AddSubShiftedRegister (d,n,m,datasize,sub_op,setflags,shift_type,shift_amount) -> `AArch64AddSubShiftedRegister (map_reg d,map_reg n,map_reg m,datasize,sub_op,setflags,shift_type,shift_amount)
+| `AArch64AddSubImmediate (d,n,datasize,sub_op,setflags,imm) -> `AArch64AddSubImmediate (map_reg d,map_reg n,datasize,sub_op,setflags,imm)
+| `AArch64Address (d,page,imm) -> `AArch64Address (map_reg d,page,imm)
+| `AArch64LogicalImmediate (d,n,datasize,setflags,op,imm) -> `AArch64LogicalImmediate (map_reg d,map_reg n,datasize,setflags,op,imm)
+| `AArch64LogicalShiftedRegister (d,n,m,datasize,setflags,op,shift_type,shift_amount,invert) -> `AArch64LogicalShiftedRegister (map_reg d,map_reg n,map_reg m,datasize,setflags,op,shift_type,shift_amount,invert)
+| `AArch64Shift (d,n,m,datasize,shift_type) -> `AArch64Shift (map_reg d,map_reg n,map_reg m,datasize,shift_type)
+| `AArch64BranchConditional (offset,condition) -> `AArch64BranchConditional (offset,condition)
+| `AArch64BranchImmediate (branch_type,offset) -> `AArch64BranchImmediate (branch_type,offset)
+| `AArch64BitfieldMove (d,n,datasize,inzero,extend,_R,_S,wmask,tmask) -> `AArch64BitfieldMove (map_reg d,map_reg n,datasize,inzero,extend,_R,_S,wmask,tmask)
+| `AArch64BranchRegister (n,branch_type) -> `AArch64BranchRegister (map_reg n,branch_type)
+| `AArch64CompareAndBranch (t,datasize,iszero,offset) -> `AArch64CompareAndBranch (map_reg t,datasize,iszero,offset)
+| `AArch64ConditionalCompareImmediate (n,datasize,sub_op,condition,flags,imm) -> `AArch64ConditionalCompareImmediate (map_reg n,datasize,sub_op,condition,flags,imm)
+| `AArch64ConditionalCompareRegister (n,m,datasize,sub_op,condition,flags) -> `AArch64ConditionalCompareRegister (map_reg n,map_reg m,datasize,sub_op,condition,flags)
+| `AArch64ClearExclusiveMonitor (imm) -> `AArch64ClearExclusiveMonitor (imm)
+| `AArch64CountLeading (d,n,datasize,opcode) -> `AArch64CountLeading (map_reg d,map_reg n,datasize,opcode)
+| `AArch64CRC (d,n,m,size,crc32c) -> `AArch64CRC (map_reg d,map_reg n,map_reg m,size,crc32c)
+| `AArch64ConditionalSelect (d,n,m,datasize,condition,else_inv,else_inc) -> `AArch64ConditionalSelect (map_reg d,map_reg n,map_reg m,datasize,condition,else_inv,else_inc)
+| `AArch64Barrier (op,domain,types) -> `AArch64Barrier (op,domain,types)
+| `AArch64ExtractRegister (d,n,m,datasize,lsb) -> `AArch64ExtractRegister (map_reg d,map_reg n,map_reg m,datasize,lsb)
+| `AArch64Hint (op) -> `AArch64Hint (op)
+| `AArch64LoadStoreAcqExc (n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) -> `AArch64LoadStoreAcqExc (map_reg n,map_reg t,map_reg t2,map_reg s,acctype,excl,pair,memop,elsize,regsize,datasize)
+| `AArch64LoadStorePair (wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset) -> `AArch64LoadStorePair (wback,postindex,map_reg n,map_reg t,map_reg t2,acctype,memop,signed,datasize,offset)
+| `AArch64LoadImmediate (n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize) -> `AArch64LoadImmediate (map_reg n,map_reg t,acctype,memop,signed,wback,postindex,offset,regsize,datasize)
+| `AArch64LoadLiteral (t,memop,signed,size,offset,datasize) -> `AArch64LoadLiteral (map_reg t,memop,signed,size,offset,datasize)
+| `AArch64LoadRegister (n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize) -> `AArch64LoadRegister (map_reg n,map_reg t,map_reg m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize)
+| `AArch64MultiplyAddSub (d,n,m,a,destsize,datasize,sub_op) -> `AArch64MultiplyAddSub (map_reg d,map_reg n,map_reg m,map_reg a,destsize,datasize,sub_op)
+| `AArch64MoveWide (d,datasize,imm,pos,opcode) -> `AArch64MoveWide (map_reg d,datasize,imm,pos,opcode)
+| `AArch64Reverse (d,n,datasize,op) -> `AArch64Reverse (map_reg d,map_reg n,datasize,op)
+| `AArch64Division (d,n,m,datasize,unsigned) -> `AArch64Division (map_reg d,map_reg n,map_reg m,datasize,unsigned)
+| `AArch64MultiplyAddSubLong (d,n,m,a,destsize,datasize,sub_op,unsigned) -> `AArch64MultiplyAddSubLong (map_reg d,map_reg n,map_reg m,map_reg a,destsize,datasize,sub_op,unsigned)
+| `AArch64MultiplyHigh (d,n,m,a,destsize,datasize,unsigned) -> `AArch64MultiplyHigh (map_reg d,map_reg n,map_reg m,map_reg a,destsize,datasize,unsigned)
+| `AArch64TestBitAndBranch (t,datasize,bit_pos,bit_val,offset) -> `AArch64TestBitAndBranch (map_reg t,datasize,bit_pos,bit_val,offset)
+| `AArch64MoveSystemRegister (t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read) -> `AArch64MoveSystemRegister (map_reg t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read)
+| `AArch64MoveSystemImmediate (operand,field) -> `AArch64MoveSystemImmediate (operand,field)
diff --git a/aarch64_small/gen/parser.hgen b/aarch64_small/gen/parser.hgen
new file mode 100644
index 00000000..53fc1c8f
--- /dev/null
+++ b/aarch64_small/gen/parser.hgen
@@ -0,0 +1,1403 @@
+ /* TSTART */
+ | TSTART xreg
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xt>")
+ else `AArch64TMStart $2 }
+
+ /* TCOMMIT */
+ | TCOMMIT
+ { `AArch64TMCommit }
+
+ /* TABORT */
+ | TABORT imm
+ { if not (iskbituimm 6 $2) then error_arg "<imm> must be in the range 0 to 63"
+ else `AArch64TMAbort (($2 lsr 5) <> 0, $2 mod 32) }
+
+ /* TTEST */
+ | TTEST
+ {`AArch64TMTest}
+
+ | ADCSBC wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64AddSubCarry ($2,$4,$6,Set32,$1.sub_op,$1.setflags) }
+ | ADCSBC xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64AddSubCarry ($2,$4,$6,Set64,$1.sub_op,$1.setflags) }
+
+ /* ADC/ADCS/SBC/SBCS */
+
+ | ADCSBC wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64AddSubCarry ($2,$4,$6,Set32,$1.sub_op,$1.setflags) }
+ | ADCSBC xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64AddSubCarry ($2,$4,$6,Set64,$1.sub_op,$1.setflags) }
+
+ /* ADD/SUB/ADDS/SUBS (extended register), and when noted (shifted register) */
+
+ | ADDSUB wreg COMMA wreg COMMA wreg
+ { (* ambiguous with (shifted register) *)
+ if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then
+ error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then
+ error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set32,$1.sub_op,$1.setflags,ExtendType_UXTW,0) }
+ | ADDSUB wreg COMMA wreg COMMA wreg COMMA EXTEND
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then
+ error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then
+ error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set32,$1.sub_op,$1.setflags,$8._type,0) }
+ | ADDSUB wreg COMMA wreg COMMA wreg COMMA SHIFT
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if (not $1.setflags) && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not ($8.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set32,$1.sub_op,$1.setflags,ExtendType_UXTW,0) }
+ | ADDSUB wreg COMMA wreg COMMA wreg COMMA EXTEND imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not (0 <= $9 && $9 <= 4) then error_arg "<amount> must be in the range 0 to 4"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set32,$1.sub_op,$1.setflags,$8._type,$9) }
+ | ADDSUB wreg COMMA wreg COMMA wreg COMMA SHIFT imm
+ { if (issp $2 || issp $4) then
+ begin
+ (* (extended register) *)
+ if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not ($8.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else if not (0 <= $9 && $9 <= 4) then error_arg "<amount> must be in the range 0 to 4"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set32,$1.sub_op,$1.setflags,ExtendType_UXTW,$9)
+ end
+ else
+ begin
+ (* (shifted register) *)
+ if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>{, <shift> #<amount>}")
+ else if $8.shift_type = ShiftType_ROR then error_arg "<shift> must be one of LSL,LSR,ASR"
+ else if not (0 <= $9 && $9 <= 31) then error_arg "<amount> must be in the range 0 to 31"
+ else `AArch64AddSubShiftedRegister ($2,$4,$6,Set32,$1.sub_op,$1.setflags,$8.shift_type,$9)
+ end }
+
+ | ADDSUB xreg COMMA xreg COMMA xreg
+ { (* ambiguous with (shifted register) *)
+ if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,ExtendType_UXTX,0) }
+ | ADDSUB xreg COMMA xreg COMMA wreg COMMA EXTEND
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if $8._type = ExtendType_UXTX || $8._type = ExtendType_SXTX then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,$8._type,0) }
+ | ADDSUB xreg COMMA xreg COMMA wreg COMMA SHIFT
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($8.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,ExtendType_UXTX,0) }
+ | ADDSUB xreg COMMA xreg COMMA wreg COMMA EXTEND imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not (0 <= $9 && $9 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else if $8._type = ExtendType_UXTX || $8._type = ExtendType_SXTX then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,$8._type,$9) }
+ | ADDSUB xreg COMMA xreg COMMA wreg COMMA SHIFT imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($8.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else if not (0 <= $9 && $9 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,ExtendType_UXTX,$9) }
+ | ADDSUB xreg COMMA xreg COMMA xreg COMMA EXTEND
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($8._type = ExtendType_UXTX || $8._type = ExtendType_SXTX) then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,$8._type,0) }
+ | ADDSUB xreg COMMA xreg COMMA xreg COMMA SHIFT
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($8.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,ExtendType_UXTX,0) }
+ | ADDSUB xreg COMMA xreg COMMA xreg COMMA EXTEND imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not (0 <= $9 && $9 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else if not ($8._type = ExtendType_UXTX || $8._type = ExtendType_SXTX) then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,$8._type,$9) }
+ | ADDSUB xreg COMMA xreg COMMA xreg COMMA SHIFT imm
+ { if (issp $2 || issp $4) then
+ begin
+ (* (extended register) *)
+ if $1.setflags && not (isregzr $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($8.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else if not (0 <= $9 && $9 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else `AArch64AddSubExtendRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,ExtendType_UXTX,$9)
+ end
+ else
+ begin
+ (* (shifted register) *)
+ if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>{, <shift> #<amount>}")
+ else if $8.shift_type = ShiftType_ROR then error_arg "<shift> must be one of LSL,LSR,ASR"
+ else if not (0 <= $9 && $9 <= 63) then error_arg "<amount> must be in the range 0 to 63"
+ else `AArch64AddSubShiftedRegister ($2,$4,$6,Set64,$1.sub_op,$1.setflags,$8.shift_type,$9)
+ end }
+
+ /* ADD/SUB/ADDS/SUBS (immediate) */
+
+ | ADDSUB wreg COMMA wreg COMMA imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, #<imm>{, <shift>}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, #<imm>{, <shift>}")
+ else if not (0 <= $6 && $6 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else `AArch64AddSubImmediate ($2,$4,Set32,$1.sub_op,$1.setflags,reg_size_bits_R32_of_int $6) }
+ | ADDSUB wreg COMMA wreg COMMA imm COMMA SHIFT imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn|WSP>, #<imm>{, <shift>}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>, #<imm>{, <shift>}")
+ else if not (0 <= $6 && $6 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else if not ($8.shift_type = ShiftType_LSL && ($9 = 0 || $9 = 12)) then error_arg "<shift> must be 'LSL #0' or 'LSL #12'"
+ else `AArch64AddSubImmediate ($2,$4,Set32,$1.sub_op,$1.setflags,reg_size_bits_R32_of_int ($6 lsl $9)) }
+ | ADDSUB xreg COMMA xreg COMMA imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, #<imm>{, <shift>}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")
+ else if not (0 <= $6 && $6 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else `AArch64AddSubImmediate ($2,$4,Set64,$1.sub_op,$1.setflags,reg_size_bits_R64_of_int $6) }
+ | ADDSUB xreg COMMA xreg COMMA imm COMMA SHIFT imm
+ { if $1.setflags && not (isregzr $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn|SP>, #<imm>{, <shift>}")
+ else if not $1.setflags && not (isregsp $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")
+ else if not (0 <= $6 && $6 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else if not ($8.shift_type = ShiftType_LSL && ($9 = 0 || $9 = 12)) then error_arg "<shift> must be 'LSL #0' or 'LSL #12'"
+ else `AArch64AddSubImmediate ($2,$4,Set64,$1.sub_op,$1.setflags,reg_size_bits_R64_of_int ($6 lsl $9)) }
+
+ /* ADR/ADRP */
+/*
+ | ADR xreg COMMA NAME
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <label>")
+ else `AArch64Address ($2,$1.page,(* FIXME: label *)) }
+*/
+
+ /* AND/ANDS/EOR/ORR (immediate) */
+
+ | LOGOP wreg COMMA wreg COMMA big_imm
+ { if $1.invert then error_arg "bad logical operator"
+ else if not $1.setflags && not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn>, #<imm>")
+ else if $1.setflags && not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<imm>")
+ else
+ match encodeBitMasks 32 $6 with
+ | None -> error_arg "<imm> can not be encoded as bitmask"
+ | _ -> `AArch64LogicalImmediate($2,$4,Set32,$1.setflags,$1.op,reg_size_bits_R32_of_big_int $6) }
+ | LOGOP xreg COMMA xreg COMMA big_imm
+ { if $1.invert then error_arg "bad logical operator"
+ else if not $1.setflags && not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn>, #<imm>")
+ else if $1.setflags && not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<imm>")
+ else
+ match encodeBitMasks 64 $6 with
+ | None -> error_arg "<imm> can not be encoded as bitmask"
+ | _ -> `AArch64LogicalImmediate($2,$4,Set64,$1.setflags,$1.op,reg_size_bits_R64_of_big_int $6) }
+
+ /* AND/ANDS/EOR/ORR/BIC/BICS/EON/ORN (shifted register) */
+
+ | LOGOP wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>{, <shift> #<amount>}")
+ else `AArch64LogicalShiftedRegister($2,$4,$6,Set32,$1.setflags,$1.op,ShiftType_LSL,0,$1.invert) }
+ | LOGOP wreg COMMA wreg COMMA wreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>{, <shift> #<amount>}")
+ else if not (0 <= $9 && $9 <= 31) then error_arg "<amount> must be in the range 0 to 31"
+ else `AArch64LogicalShiftedRegister($2,$4,$6,Set32,$1.setflags,$1.op,$8.shift_type,$9,$1.invert) }
+
+ | LOGOP xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>{, <shift> #<amount>}")
+ else `AArch64LogicalShiftedRegister($2,$4,$6,Set64,$1.setflags,$1.op,ShiftType_LSL,0,$1.invert) }
+ | LOGOP xreg COMMA xreg COMMA xreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>{, <shift> #<amount>}")
+ else if not (0 <= $9 && $9 <= 63) then error_arg "<amount> must be in the range 0 to 63"
+ else `AArch64LogicalShiftedRegister($2,$4,$6,Set64,$1.setflags,$1.op,$8.shift_type,$9,$1.invert) }
+
+
+ /* LSL/LSR/ASR/ROR (register) alias of LSLV/LSRV/ASRV/RORV */
+
+ | SHIFT wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64Shift($2,$4,$6,Set32,$1.shift_type) }
+ | SHIFT xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64Shift($2,$4,$6,Set64,$1.shift_type) }
+
+ /* LSL/LSR/ASR/ROR (immediate) alias of UBFM/UBFM/SBFM/EXTR */
+
+ | SHIFT wreg COMMA wreg COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<shift>")
+ else if not (0 <= $6 && $6 <= 31) then error_arg "<shift> must be in the range 0 to 31"
+ else match $1.shift_type with
+ | ShiftType_ASR ->
+ let (wmask,tmask) = decodeBitMasks 32 0 31 $6 false in
+ `AArch64BitfieldMove($2,$4,Set32,true,true,$6,31,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask)
+ | ShiftType_LSL ->
+ let (wmask,tmask) = decodeBitMasks 32 0 (31-$6) (-$6 mod 32) false in
+ `AArch64BitfieldMove($2,$4,Set32,true,false,-$6 mod 32,31-$6,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask)
+ | ShiftType_LSR ->
+ let (wmask,tmask) = decodeBitMasks 32 0 31 $6 false in
+ `AArch64BitfieldMove($2,$4,Set32,true,false,$6,31,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask)
+ | ShiftType_ROR ->
+ `AArch64ExtractRegister($2,$4,$4,Set32,$6) }
+ | SHIFT xreg COMMA xreg COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<shift>")
+ else if not (0 <= $6 && $6 <= 63) then error_arg "<shift> must be in the range 0 to 64"
+ else match $1.shift_type with
+ | ShiftType_ASR ->
+ let (wmask,tmask) = decodeBitMasks 64 1 63 $6 false in
+ `AArch64BitfieldMove($2,$4,Set64,true,true,$6,63,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask)
+ | ShiftType_LSL ->
+ let (wmask,tmask) = decodeBitMasks 64 1 (63-$6) ((64-$6) mod 64) false in
+ `AArch64BitfieldMove($2,$4,Set64,true,false,(64-$6) mod 64,63-$6,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask)
+ | ShiftType_LSR ->
+ let (wmask,tmask) = decodeBitMasks 64 1 63 $6 false in
+ `AArch64BitfieldMove($2,$4,Set64,true,false,$6,63,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask)
+ | ShiftType_ROR ->
+ `AArch64ExtractRegister($2,$4,$4,Set64,$6) }
+
+ /* ASRV/LSLV/LSRV/RORV */
+
+ | SHIFTOP wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64Shift($2,$4,$6,Set32,$1.shift_type) }
+ | SHIFTOP xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64Shift($2,$4,$6,Set64,$1.shift_type) }
+
+ /* B.cond */
+/*
+ | BCOND NAME
+ { `AArch64BranchConditional((* FIXME: label *),$1.condition) }
+*/
+ /* B/BL */
+/*
+ | B NAME
+ { `AArch64BranchImmediate($1.branch_type,(* FIXME: label *)) }
+*/
+ /* BFI alias of BFM */
+
+ | BFI wreg COMMA wreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 31) then error_arg "<lsb> must be in the range 0 to 31"
+ else if not (1 <= $8 && $8 <= 32-$6) then error_arg "<width> must be in the range 1 to 32-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 32 0 ($8 - 1) (-$6 mod 32) false in
+ `AArch64BitfieldMove($2,$4,Set32,false,false,(-$6 mod 32),($8 - 1),reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask) }
+ | BFI xreg COMMA xreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 63) then error_arg "<lsb> must be in the range 0 to 63"
+ else if not (1 <= $8 && $8 <= 64-$6) then error_arg "<width> must be in the range 1 to 64-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 64 1 ($8 - 1) (-$6 mod 64) false in
+ `AArch64BitfieldMove($2,$4,Set64,false,false,(-$6 mod 64),($8 - 1),reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask) }
+
+ /* BFM/SBFM/UBFM */
+
+ | BFM wreg COMMA wreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<immr>, #<imms>")
+ else if not (0 <= $6 && $6 <= 31) then error_arg "<immr> must be in the range 0 to 31"
+ else if not (0 <= $8 && $8 <= 31) then error_arg "<imms> must be in the range 0 to 31"
+ else
+ let (wmask,tmask) = decodeBitMasks 32 0 $8 $6 false in
+ `AArch64BitfieldMove($2,$4,Set32,$1.inzero,$1.extend,$6,$8,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask) }
+ | BFM xreg COMMA xreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<immr>, #<imms>")
+ else if not (0 <= $6 && $6 <= 63) then error_arg "<immr> must be in the range 0 to 63"
+ else if not (0 <= $8 && $8 <= 63) then error_arg "<imms> must be in the range 0 to 63"
+ else
+ let (wmask,tmask) = decodeBitMasks 64 1 $8 $6 false in
+ `AArch64BitfieldMove($2,$4,Set64,$1.inzero,$1.extend,$6,$8,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask) }
+
+ /* BFXIL alias of BFM */
+
+ | BFXIL wreg COMMA wreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 31) then error_arg "<immr> must be in the range 0 to 31"
+ else if not (1 <= $8 && $8 <= 32-$6) then error_arg "<imms> must be in the range 1 to 32-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 32 0 ($6+$8-1) $6 false in
+ `AArch64BitfieldMove($2,$4,Set32,false,false,$6,$6+$8-1,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask) }
+ | BFXIL xreg COMMA xreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 63) then error_arg "<immr> must be in the range 0 to 63"
+ else if not (1 <= $8 && $8 <= 64-$6) then error_arg "<imms> must be in the range 1 to 64-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 64 1 ($6+$8-1) $6 false in
+ `AArch64BitfieldMove($2,$4,Set64,false,false,$6,$6+$8-1,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask) }
+
+ /* BR/BLR */
+
+ | BR xreg
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xn>")
+ else `AArch64BranchRegister($2,$1.branch_type) }
+
+ /* CBZ/CBNZ */
+/*
+ | CBZ wreg COMMA NAME
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wt>, <label>")
+ else `AArch64CompareAndBranch($2,Set32,$1.iszero,(* FIXME: label *)) }
+ | CBZ xreg COMMA NAME
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xt>, <label>")
+ else `AArch64CompareAndBranch($2,Set64,$1.iszero,(* FIXME: label *)) }
+*/
+
+ /* CCMN/CCMP (immediate) */
+
+ | CCM wreg COMMA imm COMMA imm COMMA COND
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wn>, #<imm>, #<nzcv>, <cond>")
+ else if not (iskbituimm 5 $4) then error_arg "<imm> must be in the range 0 to 31"
+ else if not (0 <= $6 && $6 <= 15) then error_arg "<nzcv> must be in the range 0 to 15"
+ else `AArch64ConditionalCompareImmediate($2,Set32,$1.sub_op,$8,$6,reg_size_bits_R32_of_int $4) }
+ | CCM xreg COMMA imm COMMA imm COMMA COND
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xn>, #<imm>, #<nzcv>, <cond>")
+ else if not (iskbituimm 5 $4) then error_arg "<imm> must be in the range 0 to 31"
+ else if not (0 <= $6 && $6 <= 15) then error_arg "<nzcv> must be in the range 0 to 15"
+ else `AArch64ConditionalCompareImmediate($2,Set64,$1.sub_op,$8,$6,reg_size_bits_R64_of_int $4) }
+
+ /* CCMN/CCMP (register) */
+
+ | CCM wreg COMMA wreg COMMA imm COMMA COND
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn>, <Wm>, #<nzcv>, <cond>")
+ else if not (0 <= $6 && $6 <= 15) then error_arg "<nzcv> must be in the range 0 to 15"
+ else `AArch64ConditionalCompareRegister($2,$4,Set32,$1.sub_op,$8,$6) }
+ | CCM xreg COMMA xreg COMMA imm COMMA COND
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn>, <Xm>, #<nzcv>, <cond>")
+ else if not (0 <= $6 && $6 <= 15) then error_arg "<nzcv> must be in the range 0 to 15"
+ else `AArch64ConditionalCompareRegister($2,$4,Set64,$1.sub_op,$8,$6) }
+
+ /* CINC/CINV/CNEG alias of CSINC/CSINV/CSNEG */
+
+ | CON wreg COMMA wreg COMMA COND
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <cond>")
+ else if ($6 = 0b1110 || $6 = 0b1111) then error_arg "<cond> must not be AL or NV"
+ else `AArch64ConditionalSelect($2,$4,$4,Set32,invert $6,$1.else_inv,$1.else_inc) }
+ | CON xreg COMMA xreg COMMA COND
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <cond>")
+ else if ($6 = 0b1110 || $6 = 0b1111) then error_arg "<cond> must not be AL or NV"
+ else `AArch64ConditionalSelect($2,$4,$4,Set64,invert $6,$1.else_inv,$1.else_inc) }
+
+ /* CLREX */
+
+ | CLREX
+ { `AArch64ClearExclusiveMonitor(15) }
+ | CLREX imm
+ { if not (iskbituimm 4 $2) then error_arg "<imm> must be in the range 0 to 15"
+ else `AArch64ClearExclusiveMonitor($2) }
+
+ /* CLS/CLZ */
+
+ | CL wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>")
+ else `AArch64CountLeading($2,$4,Set32,$1.opcode) }
+ | CL xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>")
+ else `AArch64CountLeading($2,$4,Set64,$1.opcode) }
+
+ /* CMN/CMP (extended register) alias of ADDS/SUBS (extended register) */
+
+ | CM wreg COMMA wreg
+ { (* ambiguous with (shifted register) *)
+ if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else `AArch64AddSubExtendRegister (W ZR,$2,$4,Set32,$1.sub_op,true,ExtendType_UXTW,0) }
+ | CM wreg COMMA wreg COMMA EXTEND
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else `AArch64AddSubExtendRegister (W ZR,$2,$4,Set32,$1.sub_op,true,$6._type,0) }
+ | CM wreg COMMA wreg COMMA SHIFT
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else `AArch64AddSubExtendRegister (W ZR,$2,$4,Set32,$1.sub_op,true,ExtendType_UXTW,0) }
+ | CM wreg COMMA wreg COMMA EXTEND imm
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not (0 <= $7 && $7 <= 4) then error_arg "<amount> must be in the range 0 to 4"
+ else `AArch64AddSubExtendRegister (W ZR,$2,$4,Set32,$1.sub_op,true,$6._type,$7) }
+ | CM wreg COMMA wreg COMMA SHIFT imm
+ { if issp $2 then
+ begin
+ (* (extended register) *)
+ if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else if not (0 <= $7 && $7 <= 4) then error_arg "<amount> must be in the range 0 to 4"
+ else `AArch64AddSubExtendRegister (W ZR,$2,$4,Set32,$1.sub_op,true,ExtendType_UXTW,$7)
+ end
+ else
+ begin
+ (* (shifted register) *)
+ if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn>, <Wm>{, <shift> #<amount>}")
+ else if $6.shift_type = ShiftType_ROR then error_arg "<shift> must be one of LSL,LSR,ASR"
+ else if not (0 <= $7 && $7 <= 31) then error_arg "<amount> must be in the range 0 to 31"
+ else `AArch64AddSubShiftedRegister (W ZR,$2,$4,Set32,$1.sub_op,true,$6.shift_type,$7)
+ end }
+
+ | CM xreg COMMA xreg
+ { (* ambiguous with (shifted register) *)
+ if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,ExtendType_UXTX,0) }
+ | CM xreg COMMA wreg COMMA EXTEND
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if $6._type = ExtendType_UXTX || $6._type = ExtendType_SXTX then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,$6._type,0) }
+ | CM xreg COMMA wreg COMMA SHIFT
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,ExtendType_UXTX,0) }
+ | CM xreg COMMA wreg COMMA EXTEND imm
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not (0 <= $7 && $7 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else if $6._type = ExtendType_UXTX || $6._type = ExtendType_SXTX then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,$6._type,$7) }
+ | CM xreg COMMA wreg COMMA SHIFT imm
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else if not (0 <= $7 && $7 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,ExtendType_UXTX,$7) }
+ | CM xreg COMMA xreg COMMA EXTEND
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($6._type = ExtendType_UXTX || $6._type = ExtendType_SXTX) then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,$6._type,0) }
+ | CM xreg COMMA xreg COMMA SHIFT
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,ExtendType_UXTX,0) }
+ | CM xreg COMMA xreg COMMA EXTEND imm
+ { if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <R><m>{, <extend> {#<amount>}}")
+ else if not (0 <= $7 && $7 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else if not ($6._type = ExtendType_UXTX || $6._type = ExtendType_SXTX) then error_arg "<R> doesn't match <extend>"
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,$6._type,$7) }
+ | CM xreg COMMA xreg COMMA SHIFT imm
+ { if issp $2 then
+ begin
+ (* (extended register) *)
+ if not (isregsp $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, <X ZR>")
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of UXTB,UXTH,UXTW,UXTX,SXTB,SXTH,SXTW,SXTX,LSL"
+ else if not (0 <= $7 && $7 <= 4) then error_arg "<amount> must be in the range 0 to 4."
+ else `AArch64AddSubExtendRegister (X ZR,$2,$4,Set64,$1.sub_op,true,ExtendType_UXTX,$7)
+ end
+ else
+ begin
+ (* (shifted register) *)
+ if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn>, <Xm>{, <shift> #<amount>}")
+ else if $6.shift_type = ShiftType_ROR then error_arg "<shift> must be one of LSL,LSR,ASR"
+ else if not (0 <= $7 && $7 <= 63) then error_arg "<amount> must be in the range 0 to 63"
+ else `AArch64AddSubShiftedRegister (X ZR,$2,$4,Set64,$1.sub_op,true,$6.shift_type,$7)
+ end }
+
+ /* CMN/CMP (immediate) alias of ADDS/SUBS (immediate) */
+
+ | CM wreg COMMA imm
+ { if not (isregsp $2) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, #<imm>{, <shift>}")
+ else if not (0 <= $4 && $4 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else `AArch64AddSubImmediate (W ZR,$2,Set32,$1.sub_op,true,reg_size_bits_R32_of_int $4) }
+ | CM wreg COMMA imm COMMA SHIFT imm
+ { if not (isregsp $2) then error_registers ("expected " ^ $1.txt ^ " <Wn|WSP>, #<imm>{, <shift>}")
+ else if not (0 <= $4 && $4 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else if not ($6.shift_type = ShiftType_LSL && ($7 = 0 || $7 = 12)) then error_arg "<shift> must be 'LSL #0' or 'LSL #12'"
+ else `AArch64AddSubImmediate (W ZR,$2,Set32,$1.sub_op,true,reg_size_bits_R32_of_int ($4 lsl $7)) }
+ | CM xreg COMMA imm
+ { if not (isregsp $2) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, #<imm>{, <shift>}")
+ else if not (0 <= $4 && $4 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else `AArch64AddSubImmediate (X ZR,$2,Set64,$1.sub_op,true,reg_size_bits_R64_of_int $4) }
+ | CM xreg COMMA imm COMMA SHIFT imm
+ { if not (isregsp $2) then error_registers ("expected " ^ $1.txt ^ " <Xn|SP>, #<imm>{, <shift>}")
+ else if not (0 <= $4 && $4 <= 4095) then error_arg "<imm> must be in the range 0 to 4095"
+ else if not ($6.shift_type = ShiftType_LSL && ($7 = 0 || $7 = 12)) then error_arg "<shift> must be 'LSL #0' or 'LSL #12'"
+ else `AArch64AddSubImmediate (X ZR,$2,Set64,$1.sub_op,true,reg_size_bits_R64_of_int ($4 lsl $7)) }
+
+ /* CRC32B/CRC32H/CRC32W */
+ /* CRC32CB/CRC32CH/CRC32CW */
+
+ | CRC wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64CRC($2,$4,$6,$1.size,$1.crc32c) }
+
+ /* CRC32X/CRC32CX */
+
+ | CRC32X wreg COMMA wreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Xm>")
+ else `AArch64CRC($2,$4,$6,DataSize64,$1.crc32c) }
+
+ /* CSEL/CSINV/CSINC/CSNEG */
+
+ | CSEL wreg COMMA wreg COMMA wreg COMMA COND
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>, <cond>")
+ else `AArch64ConditionalSelect($2,$4,$6,Set32,$8,$1.else_inv,$1.else_inc) }
+ | CSEL xreg COMMA xreg COMMA xreg COMMA COND
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>, <cond>")
+ else `AArch64ConditionalSelect($2,$4,$6,Set64,$8,$1.else_inv,$1.else_inc) }
+
+ /* CSET/CSETM alias of CSINC/CSINV */
+
+ | CSET wreg COMMA COND
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <cond>")
+ else if ($4 = 0b1110 || $4 = 0b1111) then error_arg "<cond> must not be AL or NV"
+ else
+ let invert = (lxor) 0b0001 in
+ `AArch64ConditionalSelect($2,W ZR,W ZR,Set32,invert $4,$1.else_inv,$1.else_inc) }
+ | CSET xreg COMMA COND
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <cond>")
+ else if ($4 = 0b1110 || $4 = 0b1111) then error_arg "<cond> must not be AL or NV"
+ else
+ let invert = (lxor) 0b0001 in
+ `AArch64ConditionalSelect($2,X ZR,X ZR,Set64,invert $4,$1.else_inv,$1.else_inc) }
+
+ /* DMB/DSB */
+
+ | MEMBARR BARROP
+ { `AArch64Barrier($1.op,$2.domain,$2.types) }
+ | MEMBARR imm
+ { if not (0 <= $2 && $2 <= 15) then error_arg "<imm> must be in the range 0 to 15"
+ else
+ let domain =
+ match $2 / 4 with
+ | 0b00 -> MBReqDomain_OuterShareable
+ | 0b01 -> MBReqDomain_Nonshareable
+ | 0b10 -> MBReqDomain_InnerShareable
+ | 0b11 -> MBReqDomain_FullSystem
+ | _ -> assert false
+ in
+ let (domain,types) =
+ match $2 mod 4 with
+ | 0b01 -> (domain,MBReqTypes_Reads)
+ | 0b10 -> (domain,MBReqTypes_Writes)
+ | 0b11 -> (domain,MBReqTypes_All)
+ | _ -> (MBReqDomain_FullSystem,MBReqTypes_All)
+ in
+ `AArch64Barrier($1.op,domain,types) }
+
+ /* EXTR */
+
+ | EXTR wreg COMMA wreg COMMA wreg COMMA imm
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>, #<lsb>")
+ else if not (0 <= $8 && $8 <= 31) then error_arg "<lsb> must be in the range 0 to 31"
+ else `AArch64ExtractRegister($2,$4,$6,Set32,$8) }
+ | EXTR xreg COMMA xreg COMMA xreg COMMA imm
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>, #<lsb>")
+ else if not (0 <= $8 && $8 <= 63) then error_arg "<lsb> must be in the range 0 to 63"
+ else `AArch64ExtractRegister($2,$4,$6,Set64,$8) }
+
+ /* HINT */
+
+ | HINT imm
+ { if not (0 <= $2 && $2 <= 127) then error_arg "<imm> must be in the range 0 to 127"
+ else
+ match $2 with
+ | 0 -> `AArch64Hint(SystemHintOp_NOP)
+ | 1 -> `AArch64Hint(SystemHintOp_YIELD)
+ | 2 -> `AArch64Hint(SystemHintOp_WFE)
+ | 3 -> `AArch64Hint(SystemHintOp_WFI)
+ | 4 -> `AArch64Hint(SystemHintOp_SEV)
+ | 5 -> `AArch64Hint(SystemHintOp_SEVL)
+ | _ -> `AArch64Hint(SystemHintOp_NOP) }
+
+ /* ISB */
+
+ | ISB
+ { `AArch64Barrier(MemBarrierOp_ISB,MBReqDomain_FullSystem,MBReqTypes_All) }
+ | ISB BARROP
+ { if not ($2 = {domain=MBReqDomain_FullSystem; types=MBReqTypes_All}) then error_arg "<option> must be SY"
+ else `AArch64Barrier(MemBarrierOp_ISB,MBReqDomain_FullSystem,MBReqTypes_All) }
+ | ISB imm
+ { (* FIXME: this seems like an ARM bug, why do we let this be anything other then 15 *)
+ if not (0 <= $2 && $2 <= 15) then error_arg "<imm> must be in the range 0 to 15"
+ else
+ let domain =
+ match $2 / 4 with
+ | 0b00 -> MBReqDomain_OuterShareable
+ | 0b01 -> MBReqDomain_Nonshareable
+ | 0b10 -> MBReqDomain_InnerShareable
+ | 0b11 -> MBReqDomain_FullSystem
+ | _ -> assert false
+ in
+ let (domain,types) =
+ match $2 mod 4 with
+ | 0b01 -> (domain,MBReqTypes_Reads)
+ | 0b10 -> (domain,MBReqTypes_Writes)
+ | 0b11 -> (domain,MBReqTypes_All)
+ | _ -> (MBReqDomain_FullSystem,MBReqTypes_All)
+ in
+ `AArch64Barrier(MemBarrierOp_ISB,domain,types) }
+
+ /* LDAR/LDARB/LDARH
+ LDAXR/LDAXRB/LDAXRH
+ LDXR/LDXRB/LDXRH
+ STLR/STLRB/STLRH */
+
+ | LDAXR wreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($5,$2,W ZR (* ARM: 0b11111 *),W ZR (* ARM: 0b11111 *),$1.acctype,$1.excl,false,$1.memop,$1.var32.elsize,Set32,$1.var32.datasize) }
+ | LDAXR wreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregsp $5 && $7 = 0) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($5,$2,W ZR (* ARM: 0b11111 *),W ZR (* ARM: 0b11111 *),$1.acctype,$1.excl,false,$1.memop,$1.var32.elsize,Set32,$1.var32.datasize) }
+ | LDAXR xreg COMMA LBRK xreg RBRK
+ { if not $1.var64 then error_arg "unrecognised instruction"
+ else if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($5,$2,X ZR (* ARM: 0b11111 *),W ZR (* ARM: 0b11111 *),$1.acctype,$1.excl,false,$1.memop,64,Set64,DataSize64) }
+ | LDAXR xreg COMMA LBRK xreg COMMA imm RBRK
+ { if not $1.var64 then error_arg "unrecognised instruction"
+ else if not (isregzr $2 && isregsp $5 && $7 = 0) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($5,$2,X ZR (* ARM: 0b11111 *),W ZR (* ARM: 0b11111 *),$1.acctype,$1.excl,false,$1.memop,64,Set64,DataSize64) }
+
+ /* STXR/STXRB/STXRH */
+ /* STLXR/STLXRB/STLXRH */
+
+ | STLXR wreg COMMA wreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Wt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$4,W ZR (* ARM: 0b11111 *),$2,$1.acctype,true,false,MemOp_STORE,$1.var32.elsize,Set32,$1.var32.datasize) }
+ | STLXR wreg COMMA wreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7 && $9 = 0) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Wt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$4,W ZR (* ARM: 0b11111 *),$2,$1.acctype,true,false,MemOp_STORE,$1.var32.elsize,Set32,$1.var32.datasize) }
+ | STLXR wreg COMMA xreg COMMA LBRK xreg RBRK
+ { if not $1.var64 then error_arg "unrecognised instruction"
+ else if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Xt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$4,X ZR (* ARM: 0b11111 *),$2,$1.acctype,true,false,MemOp_STORE,64,Set64,DataSize64) }
+ | STLXR wreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK
+ { if not $1.var64 then error_arg "unrecognised instruction"
+ else if not (isregzr $2 && isregzr $4 && isregsp $7 && $9 = 0) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Xt>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$4,X ZR (* ARM: 0b11111 *),$2,$1.acctype,true,false,MemOp_STORE,64,Set64,DataSize64) }
+
+ /* LDAXP/LDXP */
+
+ | LDXP wreg COMMA wreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Wt1>, <Wt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$2,$4,W ZR (* ARM: 0b11111 *),$1.acctype,true,true,MemOp_LOAD,32,Set32,DataSize32) }
+ | LDXP wreg COMMA wreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7 && $9 = 0) then error_registers ("expected " ^ $1.txt ^ " <Wt1>, <Wt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$2,$4,W ZR (* ARM: 0b11111 *),$1.acctype,true,true,MemOp_LOAD,32,Set32,DataSize32) }
+ | LDXP xreg COMMA xreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$2,$4,W ZR (* ARM: 0b11111 *),$1.acctype,true,true,MemOp_LOAD,64,Set64,DataSize64) }
+ | LDXP xreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7 && $9 = 0) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($7,$2,$4,W ZR (* ARM: 0b11111 *),$1.acctype,true,true,MemOp_LOAD,64,Set64,DataSize64) }
+
+ /* STLXP/STXP */
+
+ | STXP wreg COMMA wreg COMMA wreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregsp $9) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Wt1>, <Wt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($9,$4,$6,$2,$1.acctype,true,true,MemOp_STORE,32,Set32,DataSize32) }
+ | STXP wreg COMMA wreg COMMA wreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregsp $9 && $11 = 0) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Wt1>, <Wt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($9,$4,$6,$2,$1.acctype,true,true,MemOp_STORE,32,Set32,DataSize32) }
+ | STXP wreg COMMA xreg COMMA xreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregsp $9) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($9,$4,$6,$2,$1.acctype,true,true,MemOp_STORE,64,Set64,DataSize64) }
+ | STXP wreg COMMA xreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregsp $9 && $11 = 0) then error_registers ("expected " ^ $1.txt ^ " <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]")
+ else `AArch64LoadStoreAcqExc($9,$4,$6,$2,$1.acctype,true,true,MemOp_STORE,64,Set64,DataSize64) }
+
+ /* LDP/STP (post-index) */
+
+ | LDSTP wreg COMMA wreg COMMA LBRK xreg RBRK COMMA imm
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Wt1>, <Wt2>, [<Xn|SP>], #<imm>")
+ else if not (-256 <= $10 && $10 <= 252) then error_arg "<imm> must be in the range -256 to 252"
+ else if not ($10 mod 4 = 0) then error_arg "<imm> must be a multiple of 4"
+ else `AArch64LoadStorePair (true,true,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize32,bit64_of_int $10) }
+ | LDSTP xreg COMMA xreg COMMA LBRK xreg RBRK COMMA imm
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>], #<imm>")
+ else if not (-512 <= $10 && $10 <= 504) then error_arg "<imm> must be in the range -512 to 504"
+ else if not ($10 mod 8 = 0) then error_arg "<imm> must be a multiple of 8"
+ else `AArch64LoadStorePair (true,true,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize64,bit64_of_int $10) }
+
+ /* LDP/STP (pre-index) */
+
+ | LDSTP wreg COMMA wreg COMMA LBRK xreg COMMA imm RBRK EXCL
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]!")
+ else if not (-256 <= $9 && $9 <= 252) then error_arg "<imm> must be in the range -256 to 252"
+ else if not ($9 mod 4 = 0) then error_arg "<imm> must be a multiple of 4"
+ else `AArch64LoadStorePair (true,false,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize32,bit64_of_int $9) }
+ | LDSTP xreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK EXCL
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!")
+ else if not (-512 <= $9 && $9 <= 504) then error_arg "<imm> must be in the range -512 to 504"
+ else if not ($9 mod 8 = 0) then error_arg "<imm> must be a multiple of 8"
+ else `AArch64LoadStorePair (true,false,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize64,bit64_of_int $9) }
+
+ /* LDP/STP (signed offset) */
+
+ | LDSTP wreg COMMA wreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Wt1>, <Wt2>, [<Xn|SP>{, #<imm>}]")
+ else `AArch64LoadStorePair (false,false,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize32,bit64_of_int 0) }
+ | LDSTP wreg COMMA wreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Wt1>, <Wt2>, [<Xn|SP>{, #<imm>}]")
+ else if not (-256 <= $9 && $9 <= 252) then error_arg "<imm> must be in the range -256 to 252"
+ else if not ($9 mod 4 = 0) then error_arg "<imm> must be a multiple of 4"
+ else `AArch64LoadStorePair (false,false,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize32,bit64_of_int $9) }
+ | LDSTP xreg COMMA xreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]")
+ else `AArch64LoadStorePair (false,false,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize64,bit64_of_int 0) }
+ | LDSTP xreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]")
+ else if not (-512 <= $9 && $9 <= 504) then error_arg "<imm> must be in the range -512 to 504"
+ else if not ($9 mod 8 = 0) then error_arg "<imm> must be a multiple of 8"
+ else `AArch64LoadStorePair (false,false,$7,$2,$4,AccType_NORMAL,$1.memop,false,DataSize64,bit64_of_int $9) }
+
+ /* LDPSW (post-index) */
+
+ | LDPSW xreg COMMA xreg COMMA LBRK xreg RBRK COMMA imm
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>], #<imm>")
+ else if not (-256 <= $10 && $10 <= 252) then error_arg "<imm> must be in the range -256 to 252"
+ else if not ($10 mod 4 = 0) then error_arg "<imm> must be a multiple of 4"
+ else `AArch64LoadStorePair (true,true,$7,$2,$4,AccType_NORMAL,MemOp_LOAD,true,DataSize32,bit64_of_int $10) }
+
+ /* LDPSW (pre-index) */
+
+ | LDPSW xreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK EXCL
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!")
+ else if not (-256 <= $9 && $9 <= 252) then error_arg "<imm> must be in the range -256 to 252"
+ else if not ($9 mod 4 = 0) then error_arg "<imm> must be a multiple of 4"
+ else `AArch64LoadStorePair (true,false,$7,$2,$4,AccType_NORMAL,MemOp_LOAD,true,DataSize32,bit64_of_int $9) }
+
+ /* LDPSW (signed offset) */
+
+ | LDPSW xreg COMMA xreg COMMA LBRK xreg RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]")
+ else `AArch64LoadStorePair (false,false,$7,$2,$4,AccType_NORMAL,MemOp_LOAD,true,DataSize32,bit64_of_int 0) }
+ | LDPSW xreg COMMA xreg COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregzr $2 && isregzr $4 && isregsp $7) then error_registers ("expected " ^ $1.txt ^ " <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]")
+ else if not (-256 <= $9 && $9 <= 252) then error_arg "<imm> must be in the range -256 to 252"
+ else if not ($9 mod 4 = 0) then error_arg "<imm> must be a multiple of 4"
+ else `AArch64LoadStorePair (false,false,$7,$2,$4,AccType_NORMAL,MemOp_LOAD,true,DataSize32,bit64_of_int $9) }
+
+ /* LDR/LDRB/LDRH/LDRSB/LDRSH/LDRSW/STR/STRB/STRH (immediate) (post-index) */
+
+ | LDSTR wreg COMMA LBRK xreg RBRK COMMA imm
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>], #<simm>")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>]")
+ else if not (-256 <= $8 && $8 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,true,true,bit64_of_int $8,Set32,var32.datasize) }
+ | LDSTR xreg COMMA LBRK xreg RBRK COMMA imm
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>], #<simm>")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>]")
+ else if not (-256 <= $8 && $8 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,true,true,bit64_of_int $8,Set64,var64.datasize) }
+
+ /* LDR/LDRB/LDRH/LDRSB/LDRSH/LDRSW/STR/STRB/STRH (immediate) (pre-index) */
+
+ | LDSTR wreg COMMA LBRK xreg COMMA imm RBRK EXCL
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, #<simm>]!")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, #<simm>]!")
+ else if not (-256 <= $7 && $7 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,true,false,bit64_of_int $7,Set32,var32.datasize) }
+ | LDSTR xreg COMMA LBRK xreg COMMA imm RBRK EXCL
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, #<simm>]!")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, #<simm>]!")
+ else if not (-256 <= $7 && $7 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,true,false,bit64_of_int $7,Set64,var64.datasize) }
+
+ /* LDR/LDRB/LDRH/LDRSB/LDRSH/LDRSW/STR/STRB/STRH (immediate) (unsigned offset) */
+
+ | LDSTR wreg COMMA LBRK xreg RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<pimm>}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<pimm>}]")
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,false,false,bit64_of_int 0,Set32,var32.datasize) }
+ | LDSTR wreg COMMA LBRK xreg COMMA imm RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<pimm>}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<pimm>}]")
+ else if var32.datasize = DataSize8 && not (0 <= $7 && $7 <= 4095) then error_arg "<pimm> must be in the range 0 to 4095"
+ else if var32.datasize = DataSize16 && not (0 <= $7 && $7 <= 8190) then error_arg "<pimm> must be in the range 0 to 8190"
+ else if var32.datasize = DataSize16 && not ($7 mod 2 = 0) then error_arg "<pimm> must be a multiple of 2"
+ else if var32.datasize = DataSize32 && not (0 <= $7 && $7 <= 16380) then error_arg "<pimm> must be in the range 0 to 16380"
+ else if var32.datasize = DataSize32 && not ($7 mod 4 = 0) then error_arg "<pimm> must be a multiple of 4"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,false,false,bit64_of_int $7,Set32,var32.datasize) }
+ | LDSTR xreg COMMA LBRK xreg RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<pimm>}]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<pimm>}]")
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,false,false,bit64_of_int 0,Set64,var64.datasize) }
+ | LDSTR xreg COMMA LBRK xreg COMMA imm RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<pimm>}]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<pimm>}]")
+ else if var64.datasize = DataSize8 && not (0 <= $7 && $7 <= 4095) then error_arg "<pimm> must be in the range 0 to 4095"
+ else if var64.datasize = DataSize16 && not (0 <= $7 && $7 <= 8190) then error_arg "<pimm> must be in the range 0 to 8190"
+ else if var64.datasize = DataSize16 && not ($7 mod 2 = 0) then error_arg "<pimm> must be a multiple of 2"
+ else if var64.datasize = DataSize32 && not (0 <= $7 && $7 <= 16380) then error_arg "<pimm> must be in the range 0 to 16380"
+ else if var64.datasize = DataSize32 && not ($7 mod 4 = 0) then error_arg "<pimm> must be a multiple of 4"
+ else if var64.datasize = DataSize64 && not (0 <= $7 && $7 <= 32760) then error_arg "<pimm> must be in the range 0 to 32760"
+ else if var64.datasize = DataSize64 && not ($7 mod 8 = 0) then error_arg "<pimm> must be a multiple of 8"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,$1.memop,$1.signed,false,false,bit64_of_int $7,Set64,var64.datasize) }
+
+ /* LDR/LDRSW (literal) */
+/*
+ | LDSTR wreg COMMA NAME
+ { if not $1.lit32 then error_arg "unrecognised instruction"
+ else if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wt>, <label>")
+ else `AArch64LoadLiteral($2,MemOp_LOAD,$1.signed,4,(* FIXME: label *),DataSize32) }
+ | LDSTR xreg COMMA NAME
+ { match $1.lit64 with
+ | None -> error_arg "unrecognised instruction"
+ | Some lit64 ->
+ if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xt>, <label>")
+ else `AArch64LoadLiteral($2,MemOp_LOAD,$1.signed,lit64.size,(* FIXME: label *),lit64.datasize) }
+*/
+
+ /* LDR/LDRB/LDRH/LDRSB/LDRSH/LDRSW/STR/STRB/STRH (register) */ /* FIXME: the combination of extend and amount is not clear in ARM */
+
+ | LDSTR wreg COMMA LBRK xreg COMMA wreg COMMA EXTEND RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9._type = ExtendType_UXTW || $9._type = ExtendType_SXTW) then error_arg "<extend> must be one of UXTW,SXTW"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,$9._type,0,Set32,var32.datasize) }
+ | LDSTR wreg COMMA LBRK xreg COMMA xreg RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>]")
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,ExtendType_UXTX,0,Set32,var32.datasize) }
+ | LDSTR wreg COMMA LBRK xreg COMMA xreg COMMA EXTEND RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9._type = ExtendType_SXTX) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,$9._type,0,Set32,var32.datasize) }
+ | LDSTR wreg COMMA LBRK xreg COMMA xreg COMMA SHIFT RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,ExtendType_UXTX,0,Set32,var32.datasize) }
+ | LDSTR wreg COMMA LBRK xreg COMMA xreg COMMA SHIFT imm RBRK
+ { match $1.var32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var32 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else if var32.datasize = DataSize8 && not ($10 = 0) then error_arg "<amount> must be 0"
+ else if var32.datasize = DataSize16 && not ($10 = 0 || $10 = 1) then error_arg "<amount> must be one of 0,1"
+ else if var32.datasize = DataSize32 && not ($10 = 0 || $10 = 2) then error_arg "<amount> must be one of 0,2"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,ExtendType_UXTX,$10,Set32,var32.datasize) }
+
+ | LDSTR xreg COMMA LBRK xreg COMMA wreg COMMA EXTEND RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9._type = ExtendType_UXTW || $9._type = ExtendType_SXTW) then error_arg "<extend> must be one of UXTW,SXTW"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,$9._type,0,Set64,var64.datasize) }
+ | LDSTR xreg COMMA LBRK xreg COMMA xreg RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>]")
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,ExtendType_UXTX,0,Set64,var64.datasize) }
+ | LDSTR xreg COMMA LBRK xreg COMMA xreg COMMA EXTEND RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9._type = ExtendType_SXTX) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,$9._type,0,Set64,var64.datasize) }
+ | LDSTR xreg COMMA LBRK xreg COMMA xreg COMMA SHIFT RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,ExtendType_UXTX,0,Set64,var64.datasize) }
+ | LDSTR xreg COMMA LBRK xreg COMMA xreg COMMA SHIFT imm RBRK
+ { match $1.var64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ | Some var64 ->
+ if not (isregzr $2 && isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else if var64.datasize = DataSize8 && not ($10 = 0) then error_arg "<amount> must be 0"
+ else if var64.datasize = DataSize16 && not ($10 = 0 || $10 = 1) then error_arg "<amount> must be one of 0,1"
+ else if var64.datasize = DataSize32 && not ($10 = 0 || $10 = 2) then error_arg "<amount> must be one of 0,2"
+ else if var64.datasize = DataSize64 && not ($10 = 0 || $10 = 3) then error_arg "<amount> must be one of 0,3"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,$1.memop,$1.signed,false,false,ExtendType_UXTX,$10,Set64,var64.datasize) }
+
+ /* LDTR/LDTRB/LDTRH/LDTRSB/LDTRSH/LDTRSW
+ LDUR/LDURB/LDURH/LDURSB/LDURSH/LDURSW
+ STTR/STTRB/STTRH
+ STUR/STURB/STURH */
+
+ | LDSTTUR wreg COMMA LBRK xreg RBRK
+ { match $1.off32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<simm>}]")
+ | Some off32 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<simm>}]")
+ else `AArch64LoadImmediate($5,$2,$1.acctype,$1.memop,$1.signed,false,false,bit64_of_int 0,Set32,off32.datasize) }
+ | LDSTTUR wreg COMMA LBRK xreg COMMA imm RBRK
+ { match $1.off32 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<simm>}]")
+ | Some off32 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<simm>}]")
+ else if not (-256 <= $7 && $7 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,$1.acctype,$1.memop,$1.signed,false,false,bit64_of_int $7,Set32,off32.datasize) }
+ | LDSTTUR xreg COMMA LBRK xreg RBRK
+ { match $1.off64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<simm>}]")
+ | Some off64 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<simm>}]")
+ else `AArch64LoadImmediate($5,$2,$1.acctype,$1.memop,$1.signed,false,false,bit64_of_int 0,Set64,off64.datasize) }
+ | LDSTTUR xreg COMMA LBRK xreg COMMA imm RBRK
+ { match $1.off64 with
+ | None -> error_registers ("expected " ^ $1.txt ^ " <Wt>, [<Xn|SP>{, #<simm>}]")
+ | Some off64 ->
+ if not (isregzr $2 && isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <Xt>, [<Xn|SP>{, #<simm>}]")
+ else if not (-256 <= $7 && $7 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,$1.acctype,$1.memop,$1.signed,false,false,bit64_of_int $7,Set64,off64.datasize) }
+
+ /* MADD/MSUB */
+
+ | MADDSUB wreg COMMA wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregzr $8) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>, <Wa>")
+ else `AArch64MultiplyAddSub($2,$4,$6,$8,Set32,DataSize32,$1.sub_op) }
+ | MADDSUB xreg COMMA xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregzr $8) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>, <Xa>")
+ else `AArch64MultiplyAddSub($2,$4,$6,$8,Set64,DataSize64,$1.sub_op) }
+
+ /* MUL/MNEG alias of MADD/MSUB */
+
+ | MUL wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64MultiplyAddSub($2,$4,$6,W ZR,Set32,DataSize32,$1.sub_op) }
+ | MUL xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64MultiplyAddSub($2,$4,$6,X ZR,Set64,DataSize64,$1.sub_op) }
+
+ /* MOV (to/from SP) alias of ADD (immediate) */
+ /* MOV (register) alias of ORR (shifted register) */
+ /* There is an ambiguity about the above two in the ARM manual.
+ Merging the two into one, where the "to/from SP" variant has priority. */
+
+ | MOV wreg COMMA wreg
+ { if (isregsp $2 && isregsp $4)
+ then `AArch64AddSubImmediate($2,$4,Set32,false,false,reg_size_bits_R32_of_int 0)
+ else if (isregzr $2 && isregzr $4)
+ then `AArch64LogicalShiftedRegister($2,W ZR,$4,Set32,false,LogicalOp_ORR,ShiftType_LSL,0,false)
+ else
+ error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>") }
+
+ | MOV xreg COMMA xreg
+ { if (isregsp $2 && isregsp $4)
+ then `AArch64AddSubImmediate($2,$4,Set64,false,false,reg_size_bits_R64_of_int 0)
+ else if (isregzr $2 && isregzr $4)
+ then `AArch64LogicalShiftedRegister($2,X ZR,$4,Set64,false,LogicalOp_ORR,ShiftType_LSL,0,false)
+ else
+ error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>") }
+
+ /* MOV (... immediate) alias of MOVZ/MOVN/ORR */
+
+ | MOV wreg COMMA imm
+ { if issp $2 then
+ begin
+ (* bitmask immediate *)
+ match encodeBitMasks 32 (Nat_big_num.of_int $4) with
+ | Some _ -> `AArch64LogicalImmediate($2,W ZR,Set32,false,LogicalOp_ORR,reg_size_bits_R32_of_int $4)
+ | None -> error_arg "<imm> can not be encoded"
+ end
+ else if not (iskbituimm 32 $4) then error_arg "<imm> must be a 32-bit unsigned immediate"
+ else if $4 land 0xffff0000 = 0 then
+ (* wide immediate *)
+ `AArch64MoveWide($2,Set32,$4,0,MoveWideOp_Z)
+ else if $4 land 0x0000ffff = 0 then
+ (* wide immediate *)
+ `AArch64MoveWide($2,Set32,$4 lsr 16,16,MoveWideOp_Z)
+ else if (lnot $4) land 0xffff0000 = 0 then
+ (* inverted wide immediate *)
+ `AArch64MoveWide($2,Set32,lnot $4,0,MoveWideOp_N)
+ else if (lnot $4) land 0x0000ffff = 0 then
+ (* inverted wide immediate *)
+ `AArch64MoveWide($2,Set32,(lnot $4) lsr 16,16,MoveWideOp_N)
+ else
+ (* bitmask immediate *)
+ match encodeBitMasks 32 (Nat_big_num.of_int $4) with
+ | Some _ -> `AArch64LogicalImmediate($2,W ZR,Set32,false,LogicalOp_ORR,reg_size_bits_R32_of_int $4)
+ | None -> error_arg "<imm> can not be encoded" }
+ | MOV xreg COMMA big_imm
+ { if issp $2 then
+ begin
+ (* bitmask immediate *)
+ match encodeBitMasks 64 $4 with
+ | Some _ -> `AArch64LogicalImmediate($2,X ZR,Set64,false,LogicalOp_ORR,reg_size_bits_R64_of_big_int $4)
+ | None -> error_arg "<imm> can not be encoded"
+ end
+ else if not (big_iskbituimm 64 $4) then error_arg "<imm> must be a 64-bit unsigned immediate"
+ else if check_bits $4 0 16 then
+ (* wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int $4,0,MoveWideOp_Z)
+ else if check_bits $4 16 16 then
+ (* wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int (Nat_big_num.extract_num $4 16 16),16,MoveWideOp_Z)
+ else if check_bits $4 32 16 then
+ (* wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int (Nat_big_num.extract_num $4 32 16),32,MoveWideOp_Z)
+ else if check_bits $4 48 16 then
+ (* wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int (Nat_big_num.extract_num $4 48 16),48,MoveWideOp_Z)
+ else
+ begin
+ let not_imm = (* the following should negate the first 64 bits of $4
+ by doing 0xffffffffffffffff - $4 *)
+ Nat_big_num.sub
+ (Nat_big_num.pred (Nat_big_num.shift_left (Nat_big_num.of_int 1) 64))
+ $4 in
+ if check_bits not_imm 0 16 then
+ (* inverted wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int not_imm,0,MoveWideOp_N)
+ else if check_bits not_imm 16 16 then
+ (* inverted wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int (Nat_big_num.extract_num not_imm 16 16),16,MoveWideOp_N)
+ else if check_bits not_imm 32 16 then
+ (* inverted wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int (Nat_big_num.extract_num not_imm 32 16),32,MoveWideOp_N)
+ else if check_bits not_imm 48 16 then
+ (* inverted wide immediate *)
+ `AArch64MoveWide($2,Set64,Nat_big_num.to_int (Nat_big_num.extract_num not_imm 48 16),48,MoveWideOp_N)
+ else
+ (* bitmask immediate *)
+ match encodeBitMasks 64 $4 with
+ | Some _ -> `AArch64LogicalImmediate($2,X ZR,Set64,false,LogicalOp_ORR,reg_size_bits_R64_of_big_int $4)
+ | None -> error_arg "<imm> can not be encoded"
+ end}
+
+ /* MOVK/MOVN/MOVZ */
+
+ | MOVWIDE wreg COMMA imm
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wd>, #<imm>{, LSL #<shift>}")
+ else if not (0 <= $4 && $4 <= 65535) then error_arg "<imm> must be in the range 0 to 65535"
+ else `AArch64MoveWide($2,Set32,$4,0,$1.opcode) }
+ | MOVWIDE wreg COMMA imm COMMA SHIFT imm
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wd>, #<imm>{, LSL #<shift>}")
+ else if not (0 <= $4 && $4 <= 65535) then error_arg "<imm> must be in the range 0 to 65535"
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "must be LSL"
+ else if not ($7 = 0 || $7 = 16) then error_arg "<shift> must be one of 0,16"
+ else `AArch64MoveWide($2,Set32,$4,$7,$1.opcode) }
+ | MOVWIDE xreg COMMA imm
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xd>, #<imm>{, LSL #<shift>}")
+ else if not (0 <= $4 && $4 <= 65535) then error_arg "<imm> must be in the range 0 to 65535"
+ else `AArch64MoveWide($2,Set64,$4,0,$1.opcode) }
+ | MOVWIDE xreg COMMA imm COMMA SHIFT imm
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xd>, #<imm>{, LSL #<shift>}")
+ else if not (0 <= $4 && $4 <= 65535) then error_arg "<imm> must be in the range 0 to 65535"
+ else if not ($6.shift_type = ShiftType_LSL) then error_arg "must be LSL"
+ else if not ($7 = 0 || $7 = 16 || $7 = 32 || $7 = 48) then error_arg "<shift> must be one of 0,16,32,48"
+ else `AArch64MoveWide($2,Set64,$4,$7,$1.opcode) }
+
+ /* MVN alias of ORN (shifted register) */
+
+ | MVN wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wm>{, <shift> #<amount>}")
+ else `AArch64LogicalShiftedRegister($2,W ZR,$4,Set32,false,LogicalOp_ORR,ShiftType_LSL,0,true) }
+ | MVN wreg COMMA wreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wm>{, <shift> #<amount>}")
+ else if not (0 <= $7 && $7 <= 31) then error_arg "<amount> must be in the range 0 to 31"
+ else `AArch64LogicalShiftedRegister($2,W ZR,$4,Set32,false,LogicalOp_ORR,$6.shift_type,$7,true) }
+ | MVN xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xm>{, <shift> #<amount>}")
+ else `AArch64LogicalShiftedRegister($2,X ZR,$4,Set64,false,LogicalOp_ORR,ShiftType_LSL,0,true) }
+ | MVN xreg COMMA xreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xm>{, <shift> #<amount>}")
+ else if not (0 <= $7 && $7 <= 63) then error_arg "<amount> must be in the range 0 to 63"
+ else `AArch64LogicalShiftedRegister($2,X ZR,$4,Set64,false,LogicalOp_ORR,$6.shift_type,$7,true) }
+
+ /* NEG/NEGS (shifted register) alias of SUB/SUBS (shifted register) */
+
+ | NEG wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wm>{, <shift> #<amount>}")
+ else `AArch64AddSubShiftedRegister($2,W ZR,$4,Set32,true,$1.setflags,ShiftType_LSL,0) }
+ | NEG wreg COMMA wreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wm>{, <shift> #<amount>}")
+ else if $6.shift_type = ShiftType_ROR then error_arg "<shift> must be one of LSL,LSR,ASR"
+ else if not (0 <= $7 && $7 <= 31) then error_arg "<amount> must be in the range 0 to 31"
+ else `AArch64AddSubShiftedRegister($2,W ZR,$4,Set32,true,$1.setflags,$6.shift_type,0) }
+ | NEG xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xm>{, <shift> #<amount>}")
+ else `AArch64AddSubShiftedRegister($2,X ZR,$4,Set64,true,$1.setflags,ShiftType_LSL,0) }
+ | NEG xreg COMMA xreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xm>{, <shift> #<amount>}")
+ else if $6.shift_type = ShiftType_ROR then error_arg "<shift> must be one of LSL,LSR,ASR"
+ else if not (0 <= $7 && $7 <= 63) then error_arg "<amount> must be in the range 0 to 63"
+ else `AArch64AddSubShiftedRegister($2,X ZR,$4,Set64,true,$1.setflags,$6.shift_type,$7) }
+
+ /* NGC/NGCS alias of SBC/SBCS */
+
+ | NGC wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wm>")
+ else `AArch64AddSubCarry ($2,W ZR,$4,Set32,true,$1.setflags) }
+ | NGC xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xm>")
+ else `AArch64AddSubCarry ($2,X ZR,$4,Set64,true,$1.setflags) }
+
+ /* NOP alias of HINT */
+
+ | NOP
+ { `AArch64Hint(SystemHintOp_NOP) }
+
+ /* PRFM (immediate) */
+
+ | PRFM PRFOP COMMA LBRK xreg RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<pimm>}]")
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int 0,Set64,DataSize64) }
+ | PRFM PRFOP COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<pimm>}]")
+ else if not (0 <= $7 && $7 <= 32760) then error_arg "<pimm> must be in the range 0 to 32760"
+ else if not ($7 mod 8 = 0) then error_arg "<pimm> must be a multiple of 8"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int $7,Set64,DataSize64) }
+ | PRFM imm COMMA LBRK xreg RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<pimm>}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else `AArch64LoadImmediate($5,X (Ireg (ireg_of_int $2)),AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int 0,Set64,DataSize64) }
+ | PRFM imm COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<pimm>}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else if not (0 <= $7 && $7 <= 32760) then error_arg "<pimm> must be in the range 0 to 32760"
+ else if not ($7 mod 8 = 0) then error_arg "<pimm> must be a multiple of 8"
+ else `AArch64LoadImmediate($5,X (Ireg (ireg_of_int $2)),AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int $7,Set64,DataSize64) }
+
+ /* PRFM (literal) */
+/*
+ | PRFM PRFOP COMMA NAME
+ { `AArch64LoadLiteral($2,MemOp_PREFETCH,false,0,(* FIXME: label *),DataSize32) }
+ | PRFM imm COMMA NAME
+ { if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else `AArch64LoadLiteral(X (Ireg (ireg_of_int $2)),MemOp_PREFETCH,false,0,(* FIXME: label *),DataSize32) }
+*/
+
+ /* PRFM (register) */
+
+ | PRFM PRFOP COMMA LBRK xreg COMMA wreg COMMA EXTEND RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9._type = ExtendType_UXTW || $9._type = ExtendType_SXTW) then error_arg "<extend> must be one of UXTW,SXTW"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,$9._type,0,Set32,DataSize64) }
+ | PRFM PRFOP COMMA LBRK xreg COMMA xreg RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,ExtendType_UXTX,0,Set32,DataSize64) }
+ | PRFM PRFOP COMMA LBRK xreg COMMA xreg COMMA EXTEND RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9._type = ExtendType_SXTX) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,$9._type,0,Set32,DataSize64) }
+ | PRFM PRFOP COMMA LBRK xreg COMMA xreg COMMA SHIFT RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,ExtendType_UXTX,0,Set32,DataSize64) }
+ | PRFM PRFOP COMMA LBRK xreg COMMA xreg COMMA SHIFT imm RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else if not ($10 = 0 || $10 = 3) then error_arg "<amount> must be one of 0,3"
+ else `AArch64LoadRegister($5,$2,$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,ExtendType_UXTX,$10,Set32,DataSize64) }
+
+ | PRFM imm COMMA LBRK xreg COMMA wreg COMMA EXTEND RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else if not ($9._type = ExtendType_UXTW || $9._type = ExtendType_SXTW) then error_arg "<extend> must be one of UXTW,SXTW"
+ else `AArch64LoadRegister($5,X (Ireg (ireg_of_int $2)),$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,$9._type,0,Set32,DataSize64) }
+ | PRFM imm COMMA LBRK xreg COMMA xreg RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else `AArch64LoadRegister($5,X (Ireg (ireg_of_int $2)),$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,ExtendType_UXTX,0,Set32,DataSize64) }
+ | PRFM imm COMMA LBRK xreg COMMA xreg COMMA EXTEND RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else if not ($9._type = ExtendType_SXTX) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,X (Ireg (ireg_of_int $2)),$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,$9._type,0,Set32,DataSize64) }
+ | PRFM imm COMMA LBRK xreg COMMA xreg COMMA SHIFT RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else `AArch64LoadRegister($5,X (Ireg (ireg_of_int $2)),$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,ExtendType_UXTX,0,Set32,DataSize64) }
+ | PRFM imm COMMA LBRK xreg COMMA xreg COMMA SHIFT imm RBRK
+ { if not (isregsp $5 && isregzr $7) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else if not ($9.shift_type = ShiftType_LSL) then error_arg "<extend> must be one of LSL,SXTX"
+ else if not ($10 = 0 || $10 = 3) then error_arg "<amount> must be one of 0,3"
+ else `AArch64LoadRegister($5,X (Ireg (ireg_of_int $2)),$7,AccType_NORMAL,MemOp_PREFETCH,false,false,false,ExtendType_UXTX,$10,Set32,DataSize64) }
+
+ /* PRFUM */
+
+ | PRFUM PRFOP COMMA LBRK xreg RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<simm>}]")
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int 0,Set64,DataSize64) }
+ | PRFUM PRFOP COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<simm>}]")
+ else if not (-256 <= $7 && $7 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,$2,AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int $7,Set64,DataSize64) }
+ | PRFUM imm COMMA LBRK xreg RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<simm>}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else `AArch64LoadImmediate($5,X (Ireg (ireg_of_int $2)),AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int 0,Set64,DataSize64) }
+ | PRFUM imm COMMA LBRK xreg COMMA imm RBRK
+ { if not (isregsp $5) then error_registers ("expected " ^ $1.txt ^ " <prfop>, [<Xn|SP>{, #<simm>}]")
+ else if not ($2 = 6 || $2 = 7 || $2 = 14 || $2 = 15 || (22 <= $2 && $2 <= 31)) then error_arg "<prfop> must be one of 6,7,14,15,22-31"
+ else if not (-256 <= $7 && $7 <= 255) then error_arg "<simm> must be in the range -256 to 255"
+ else `AArch64LoadImmediate($5,X (Ireg (ireg_of_int $2)),AccType_NORMAL,MemOp_PREFETCH,false,false,false,bit64_of_int $7,Set64,DataSize64) }
+
+ /* RET */
+
+ | RET
+ { `AArch64BranchRegister(X (Ireg R30),BranchType_RET) }
+ | RET xreg
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " {<Xn>}")
+ else `AArch64BranchRegister($2,BranchType_RET) }
+
+ /* RBIT/REV/REV16/REV32 */
+
+ | REV wreg COMMA wreg
+ { match $1.op32 with
+ | None -> error_arg "unrecognised instruction"
+ | Some op ->
+ if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>")
+ else `AArch64Reverse($2,$4,Set32,op) }
+ | REV xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>")
+ else `AArch64Reverse($2,$4,Set64,$1.op64) }
+
+ /* SBFIZ/UBFIZ alias of SBFM/UBFM */
+
+ | BFIZ wreg COMMA wreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 31) then error_arg "<lsb> must be in the range 0 to 31"
+ else if not (1 <= $8 && $8 <= (32 - $6)) then error_arg "<width> must be in the range 1 to 32-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 32 0 ($8 - 1) (-$6 mod 32) false in
+ `AArch64BitfieldMove($2,$4,Set32,true,$1.extend,-$6 mod 32,$8 - 1,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask) }
+ | BFIZ xreg COMMA xreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 63) then error_arg "<lsb> must be in the range 0 to 63"
+ else if not (1 <= $8 && $8 <= (64 - $6)) then error_arg "<width> must be in the range 1 to 64-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 64 1 ($8 - 1) (-$6 mod 64) false in
+ `AArch64BitfieldMove($2,$4,Set64,true,$1.extend,-$6 mod 64,$8 - 1,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask) }
+
+ /* SBFX/UBFX alias of SBFM/UBFM */
+
+ | BFX wreg COMMA wreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 31) then error_arg "<lsb> must be in the range 0 to 31"
+ else if not (1 <= $8 && $8 <= (32 - $6)) then error_arg "<width> must be in the range 1 to 32-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 32 0 ($6 + $8 - 1) $6 false in
+ `AArch64BitfieldMove($2,$4,Set32,true,$1.extend,$6,$6 + $8 - 1,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask) }
+ | BFX xreg COMMA xreg COMMA imm COMMA imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, #<lsb>, #<width>")
+ else if not (0 <= $6 && $6 <= 63) then error_arg "<lsb> must be in the range 0 to 63"
+ else if not (1 <= $8 && $8 <= (64 - $6)) then error_arg "<width> must be in the range 1 to 64-<lsb>"
+ else
+ let (wmask,tmask) = decodeBitMasks 64 1 ($6 + $8 - 1) $6 false in
+ `AArch64BitfieldMove($2,$4,Set64,true,$1.extend,$6,$6 + $8 - 1,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask) }
+
+ /* SDIV/UDIV */
+
+ | DIV wreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>, <Wm>")
+ else `AArch64Division($2,$4,$6,Set32,$1.unsigned) }
+ | DIV xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64Division($2,$4,$6,Set64,$1.unsigned) }
+
+ /* SMADDL/SMSUBL/UMADDL/UMSUBL */
+
+ | MADDSUBL xreg COMMA wreg COMMA wreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6 && isregzr $8) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Wn>, <Wm>, <Xa>")
+ else `AArch64MultiplyAddSubLong($2,$4,$6,$8,Set64,DataSize32,$1.sub_op,$1.unsigned) }
+
+ /* SMNEGL/UMNEGL alias of SMSUBL/UMSUBL */
+
+ | MNEGL xreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Wn>, <Wm>")
+ else `AArch64MultiplyAddSubLong($2,$4,$6,X ZR,Set64,DataSize32,true,$1.unsigned) }
+
+ /* SMULH/UMULH */
+
+ | MULH xreg COMMA xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xn>, <Xm>")
+ else `AArch64MultiplyHigh($2,$4,$6,X ZR,Set64,DataSize64,$1.unsigned) }
+
+ /* SMULL/UMULL alias of SMADDL/UMADDL */
+
+ | MULL xreg COMMA wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4 && isregzr $6) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Wn>, <Wm>")
+ else `AArch64MultiplyAddSubLong($2,$4,$6,X ZR,Set64,DataSize32,false,$1.unsigned) }
+
+ /* SXTB/SXTH/SXTW alias of SBFM
+ UXTB/UXTH alias of UBFM */
+
+ | EXTEND wreg COMMA wreg
+ { match $1.inst with
+ | None -> error_not_instruction $1.txt
+ | Some inst ->
+ if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>")
+ else
+ let (wmask,tmask) = decodeBitMasks 32 0 7 0 false in
+ `AArch64BitfieldMove($2,$4,Set32,true,inst.extend,0,7,reg_size_bits_R32_of_big_int wmask,reg_size_bits_R32_of_big_int tmask) }
+ | EXTEND xreg COMMA wreg
+ { match $1.inst with
+ | None -> error_not_instruction $1.txt
+ | Some inst ->
+ if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wn>")
+ else
+ let (wmask,tmask) = decodeBitMasks 64 1 7 0 false in
+ `AArch64BitfieldMove($2,$4,Set64,true,inst.extend,0,7,reg_size_bits_R64_of_big_int wmask,reg_size_bits_R64_of_big_int tmask) }
+
+ /* TBZ/TBNZ */
+/*
+ | TBZ wreg COMMA imm COMMA NAME
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <R><t>, #<imm>, <label>")
+ else if not (0 <= $4 && $4 <= 31) then error_arg "<imm> must be in the range 0 to 31"
+ else `AArch64TestBitAndBranch($2,Set32,$4,$1.bit_val,(* FIXME: label *)) }
+ | TBZ xreg COMMA imm COMMA NAME
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <R><t>, #<imm>, <label>")
+ else if not (0 <= $4 && $4 <= 63) then error_arg "<imm> must be in the range 0 to 63"
+ else `AArch64TestBitAndBranch($2,Set64,$4,$1.bit_val,(* FIXME: label *)) }
+*/
+
+ /* TST (immediate) alias of ANDS (immediate) */
+
+ | TST wreg COMMA big_imm
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Wd>, #<imm>")
+ else match encodeBitMasks 32 $4 with
+ | None -> error_arg "<imm> can not be encoded as bitmask"
+ | _ -> `AArch64LogicalImmediate(W ZR,$2,Set32,true,LogicalOp_AND,reg_size_bits_R32_of_big_int $4) }
+ | TST xreg COMMA big_imm
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xd>, #<imm>")
+ else match encodeBitMasks 64 $4 with
+ | None -> error_arg "<imm> can not be encoded as bitmask"
+ | _ -> `AArch64LogicalImmediate(X ZR,$2,Set64,true,LogicalOp_AND,reg_size_bits_R64_of_big_int $4) }
+
+ /* TST (shifted register) alias of ANDS (shifted register) */
+
+ | TST wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn>, <Wm>{, <shift> #<amount>}")
+ else `AArch64LogicalShiftedRegister(W ZR,$2,$4,Set32,true,LogicalOp_AND,ShiftType_LSL,0,false) }
+ | TST wreg COMMA wreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wn>, <Wm>{, <shift> #<amount>}")
+ else if not (0 <= $7 && $7 <= 31) then error_arg "<amount> must be in the range 0 to 31"
+ else `AArch64LogicalShiftedRegister(W ZR,$2,$4,Set32,true,LogicalOp_AND,$6.shift_type,$7,false) }
+
+ | TST xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn>, <Xm>{, <shift> #<amount>}")
+ else `AArch64LogicalShiftedRegister(X ZR,$2,$4,Set64,true,LogicalOp_AND,ShiftType_LSL,0,false) }
+ | TST xreg COMMA xreg COMMA SHIFT imm
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xn>, <Xm>{, <shift> #<amount>}")
+ else if not (0 <= $7 && $7 <= 63) then error_arg "<amount> must be in the range 0 to 63"
+ else `AArch64LogicalShiftedRegister(X ZR,$2,$4,Set64,true,LogicalOp_AND,$6.shift_type,$7,false) }
+
+ /* MRS */
+
+ | MRS xreg COMMA SYSREG
+ { if not (isregzr $2) then error_registers ("expected " ^ $1.txt ^ " <Xt>, <systemreg>")
+ else `AArch64MoveSystemRegister($2,$4.sys_op0,$4.sys_op1,$4.sys_op2,$4.sys_crn,$4.sys_crm,true) }
+
+ /* MSR (immediate) */
+
+ | MSR PSTATEFIELD COMMA imm
+ { if not (0 <= $4 && $4 <= 15) then error_arg "<imm> must be in the range 0 to 15"
+ else `AArch64MoveSystemImmediate($4,$2) }
+
+ /* MSR (register) */
+
+ | MSR SYSREG COMMA xreg
+ { if not (isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <systemreg>, <Xt>")
+ else `AArch64MoveSystemRegister($4,$2.sys_op0,$2.sys_op1,$2.sys_op2,$2.sys_crn,$2.sys_crm,false) }
diff --git a/aarch64_small/gen/pretty.hgen b/aarch64_small/gen/pretty.hgen
new file mode 100644
index 00000000..2bbf7af7
--- /dev/null
+++ b/aarch64_small/gen/pretty.hgen
@@ -0,0 +1,393 @@
+| `AArch64TMStart t ->
+ sprintf "TSTART %s" (pp_regzr Set64 t)
+
+| `AArch64TMCommit -> "TCOMMIT"
+
+| `AArch64TMAbort (retry,reason) ->
+ sprintf "TABORT %s" (pp_imm (if retry then 32 + reason else reason))
+
+| `AArch64TMTest -> "TTEST"
+
+| `AArch64ImplementationDefinedStopFetching ->
+ "_STOP_FETCHING"
+
+| `AArch64ImplementationDefinedThreadStart ->
+ "_THREAD_START"
+
+| `AArch64ImplementationDefinedTestBeginEnd (isEnd) ->
+ if isEnd then
+ "_TEST_ENDS"
+ else
+ "_TEST_BEGINS"
+
+| `AArch64AddSubCarry (d,n,m,datasize,sub_op,setflags) ->
+ if sub_op && is_zero_reg n then
+ sprintf "%s %s,%s" (pp_withflags "NGC" setflags) (pp_regzr datasize d) (pp_regzr datasize m)
+ else if sub_op then
+ sprintf "%s %s,%s,%s" (pp_withflags "SBC" setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
+ else
+ sprintf "%s %s,%s,%s" (pp_withflags "ADC" setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
+
+| `AArch64AddSubExtendRegister (d,n,m,datasize,sub_op,setflags,extend_type,shift) ->
+ if setflags && is_zero_reg d then
+ begin
+ if (is_sp_reg n) && ((datasize = Set32 && extend_type = ExtendType_UXTW) || (datasize = Set64 && extend_type = ExtendType_UXTX)) then
+ sprintf "%s %s,%s%s" (if sub_op then "CMP" else "CMN") (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m)
+ (if shift = 0 then "" else (",LSL " ^ (pp_imm shift)))
+ else
+ sprintf "%s %s,%s%s" (if sub_op then "CMP" else "CMN") (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m) (pp_addsub_regext datasize extend_type shift)
+ end
+ else if (is_sp_reg d || is_sp_reg n) && ((datasize = Set32 && extend_type = ExtendType_UXTW) || (datasize = Set64 && extend_type = ExtendType_UXTX)) then
+ sprintf "%s %s,%s,%s%s" (pp_addsub sub_op setflags) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m)
+ (if shift = 0 then "" else (",LSL " ^ (pp_imm shift)))
+ else
+ sprintf "%s %s,%s,%s%s" (pp_addsub sub_op setflags) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m) (pp_addsub_regext datasize extend_type shift)
+
+| `AArch64AddSubImmediate (d,n,datasize,sub_op,setflags,imm) ->
+ let (imm12,shift) =
+ if reg_size_bits_iskbituimm 12 imm then (reg_size_bits_to_int imm, 0)
+ else (reg_size_bits_to_int (reg_size_bits_shift_right imm 12), 12)
+ in
+ if (sub_op,setflags) = (false,false) && (is_sp_reg d || is_sp_reg n) && (shift = 0 && imm12 = 0) then
+ sprintf "MOV %s,%s" (pp_regsp datasize d) (pp_regsp datasize n)
+ else if setflags && is_zero_reg d then
+ sprintf "%s %s,%s%s" (if sub_op then "CMP" else "CMN") (pp_regsp datasize n) (pp_imm imm12) (if shift = 0 then "" else ",LSL #12")
+ else
+ sprintf "%s %s,%s,%s%s" (pp_addsub sub_op setflags) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regsp datasize n) (pp_imm imm12) (if shift = 0 then "" else ",LSL #12")
+
+| `AArch64AddSubShiftedRegister (d,n,m,datasize,sub_op,setflags,shift_type,shift_amount) ->
+ if setflags && is_zero_reg d then
+ begin
+ if shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "%s %s,%s" (if sub_op then "CMP" else "CMN") (pp_regzr datasize n) (pp_regzr datasize m)
+ else
+ sprintf "%s %s,%s,%s %s" (if sub_op then "CMP" else "CMN") (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
+ end
+ else if sub_op && is_zero_reg n then
+ begin
+ if shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "%s %s,%s" (pp_withflags "NEG" setflags) (pp_regzr datasize d) (pp_regzr datasize m)
+ else
+ sprintf "%s %s,%s,%s %s" (pp_withflags "NEG" setflags) (pp_regzr datasize d) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
+ end
+ else if shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "%s %s,%s,%s" (pp_addsub sub_op setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
+ else
+ sprintf "%s %s,%s,%s,%s %s" (pp_addsub sub_op setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
+
+| `AArch64Address (d,page,imm) ->
+ sprintf "%s %s,%s" (if page then "ADRP" else "ADR") (pp_regzr Set64 d) (pp_offset page imm)
+
+| `AArch64LogicalImmediate (d,n,datasize,setflags,op,imm) ->
+ if op = LogicalOp_AND && setflags && is_zero_reg d then
+ sprintf "TST %s,%s" (pp_regzr datasize n) (pp_reg_size_imm imm)
+ else if op = LogicalOp_ORR && not setflags && is_zero_reg n && not (moveWidePreferred datasize imm) then (* ARM: missing the check of n=ZR *)
+ sprintf "MOV %s,%s" (pp_regsp datasize d) (pp_reg_size_imm imm)
+ else sprintf "%s %s,%s,%s" (pp_logop op setflags false) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regzr datasize n) (pp_reg_size_imm imm)
+
+| `AArch64LogicalShiftedRegister (d,n,m,datasize,setflags,op,shift_type,shift_amount,invert) ->
+ if op = LogicalOp_AND && setflags && not invert && is_zero_reg d then
+ begin
+ if shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "TST %s,%s" (pp_regzr datasize n) (pp_regzr datasize m)
+ else
+ sprintf "TST %s,%s,%s %s" (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
+ end
+ else if op = LogicalOp_ORR && not setflags && invert && is_zero_reg n then
+ begin
+ if shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "MVN %s,%s" (pp_regzr datasize d) (pp_regzr datasize m)
+ else
+ sprintf "MVN %s,%s,%s %s" (pp_regzr datasize d) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
+ end
+ else if op = LogicalOp_ORR && not setflags && not invert && is_zero_reg n && shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_regzr datasize m)
+ else
+ begin
+ if shift_type = ShiftType_LSL && shift_amount = 0 then
+ sprintf "%s %s,%s,%s" (pp_logop op setflags invert) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
+ else
+ sprintf "%s %s,%s,%s,%s %s" (pp_logop op setflags invert) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
+ end
+
+| `AArch64Shift (d,n,m,datasize,shift_type) ->
+ sprintf "%s %s,%s,%s" (pp_shiftop shift_type) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
+
+| `AArch64BranchConditional (offset,condition) ->
+ sprintf "B.%s %s" (pp_cond condition) (pp_offset false offset)
+
+| `AArch64BranchImmediate (branch_type,offset) ->
+ sprintf "%s %s" (pp_branchimmediate branch_type) (pp_offset false offset)
+
+| `AArch64BitfieldMove (d,n,datasize,inzero,extend,_R,_S,wmask,tmask) ->
+ if (inzero,extend) = (false,false) && _S < _R then
+ sprintf "BFI %s,%s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S+1)) (* FIXME: I'm not sure this is the right translation of imms and immr *)
+ else if (inzero,extend) = (false,false) && _S >= _R then
+ sprintf "BFXIL %s,%s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S-_R+1))
+ else if (inzero,extend) = (true,false) && datasize = Set32 && _S <> 0b011111 && _S+1 = _R then
+ sprintf "LSL %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm (31-_S))
+ else if (inzero,extend) = (true,false) && datasize = Set64 && _S <> 0b111111 && _S+1 = _R then
+ sprintf "LSL %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm (63-_S))
+ else if inzero && datasize = Set32 && _S = 0b011111 then
+ sprintf "%s %s,%s,%s" (if extend then "ASR" else "LSR") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R)
+ else if inzero && datasize = Set64 && _S = 0b111111 then
+ sprintf "%s %s,%s,%s" (if extend then "ASR" else "LSR") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R)
+ else if inzero && _S < _R then
+ sprintf "%s %s,%s,%s,%s" (if extend then "SBFIZ" else "UBFIZ") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S+1)) (* FIXME: -<lsb> MOD 32/64 *)
+ else if inzero && bFXPreferred datasize (if extend then 0 else 1) _S _R then
+ sprintf "%s %s,%s,%s,%s" (if extend then "SBFX" else "UBFX") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S - _R + 1))
+ else if inzero && _R = 0 && _S = 0b000111 then
+ sprintf "%s %s,%s" (if extend then "SXTB" else "UXTB") (pp_regzr datasize d) (pp_regzr Set32 n)
+ else if inzero && _R = 0 && _S = 0b001111 then
+ sprintf "%s %s,%s" (if extend then "SXTH" else "UXTH") (pp_regzr datasize d) (pp_regzr Set32 n)
+ else if (inzero,extend) = (true,true) && _R = 0 && _S = 0b011111 then (* implicitly datasize = Set64 *)
+ sprintf "SXTW %s,%s" (pp_regzr datasize d) (pp_regzr Set32 n)
+ else
+ sprintf "%s %s,%s,%s,%s" (pp_bfm inzero extend) (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm _S)
+
+| `AArch64BranchRegister (n,branch_type) ->
+ if branch_type = BranchType_RET && n = X (Ireg R30) then
+ "RET"
+ else
+ sprintf "%s %s" (pp_branchregister branch_type) (pp_regzr Set64 n)
+
+| `AArch64CompareAndBranch (t,datasize,iszero,offset) ->
+ sprintf "%s %s,%s" (if iszero then "CBZ" else "CBNZ") (pp_regzr datasize t) (pp_offset false offset)
+
+| `AArch64ConditionalCompareImmediate (n,datasize,sub_op,condition,flags,imm) ->
+ sprintf "%s %s,%s,%s,%s" (if sub_op then "CCMP" else "CCMN") (pp_regzr datasize n) (pp_reg_size_imm imm) (pp_imm flags) (pp_cond condition)
+
+| `AArch64ConditionalCompareRegister (n,m,datasize,sub_op,condition,flags) ->
+ sprintf "%s %s,%s,%s,%s" (if sub_op then "CCMP" else "CCMN") (pp_regzr datasize n) (pp_regzr datasize m) (pp_imm flags) (pp_cond condition)
+
+| `AArch64ClearExclusiveMonitor (imm) ->
+ if imm = 15 then
+ sprintf "CLREX"
+ else
+ sprintf "CLREX %s" (pp_imm imm)
+
+| `AArch64CountLeading (d,n,datasize,opcode) ->
+ sprintf "%s %s,%s" (pp_countop opcode) (pp_regzr datasize d) (pp_regzr datasize n)
+
+| `AArch64CRC (d,n,m,size,crc32c) ->
+ sprintf "%s %s,%s,%s" (pp_crc size crc32c) (pp_regzr Set32 d) (pp_regzr Set32 n) (pp_regzr (if size = DataSize64 then Set64 else Set32) m)
+
+| `AArch64ConditionalSelect (d,n,m,datasize,condition,else_inv,else_inc) ->
+ if not else_inv && else_inc && n = m && not (is_zero_reg n) && not (condition = 0b1110 || condition = 0b1111) then
+ sprintf "CINC %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_cond condition)
+ else if not else_inv && else_inc && n = m && is_zero_reg n && not (condition = 0b1110 || condition = 0b1111) then
+ sprintf "CSET %s,%s" (pp_regzr datasize d) (pp_cond condition)
+ else if else_inv && not else_inc && n = m && not (is_zero_reg n) && not (condition = 0b1110 || condition = 0b1111) then
+ sprintf "CINV %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_cond condition)
+ else if else_inv && not else_inc && n = m && is_zero_reg n && not (condition = 0b1110 || condition = 0b1111) then
+ sprintf "CSETM %s,%s" (pp_regzr datasize d) (pp_cond condition)
+ else if else_inv && else_inc && n = m && not (condition = 0b1110 || condition = 0b1111) then
+ sprintf "CNEG %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_cond condition)
+ else
+ sprintf "%s %s,%s,%s,%s" (pp_csel else_inv else_inc) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_cond condition)
+
+| `AArch64Barrier (op,domain,types) ->
+ if op = MemBarrierOp_ISB && domain = MBReqDomain_FullSystem && types = MBReqTypes_All then
+ pp_barr op
+ else
+ sprintf "%s %s" (pp_barr op) (pp_barroption domain types)
+
+| `AArch64ExtractRegister (d,n,m,datasize,lsb) ->
+ if n = m then
+ sprintf "ROR %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm lsb)
+ else
+ sprintf "EXTR %s,%s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_imm lsb)
+
+| `AArch64Hint (op) ->
+ begin
+ match op with
+ | SystemHintOp_NOP -> "NOP"
+ | SystemHintOp_YIELD -> "YIELD"
+ | SystemHintOp_WFE -> "WFE"
+ | SystemHintOp_WFI -> "WFI"
+ | SystemHintOp_SEV -> "SEV"
+ | SystemHintOp_SEVL -> "SEVL"
+ end
+
+| `AArch64LoadStoreAcqExc (n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) ->
+ if pair && memop = MemOp_LOAD then
+ sprintf "%s %s,%s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n)
+ else if pair && memop = MemOp_STORE then
+ sprintf "%s %s,%s,%s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr Set32 s) (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n)
+ else if not pair && memop = MemOp_STORE && excl then
+ sprintf "%s %s,%s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr Set32 s) (pp_regzr regsize t) (pp_regsp Set64 n)
+ else
+ sprintf "%s %s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr regsize t) (pp_regsp Set64 n)
+
+| `AArch64LoadStorePair (wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset) ->
+ begin
+ let inst = if signed then "LDPSW" else if memop = MemOp_LOAD then "LDP" else "STP" in
+ let regsize = if signed then Set64 else (match datasize with DataSize32 -> Set32 | DataSize64 -> Set64 | DataSize16 | DataSize8 -> failwith "unexpected value") in
+ match (wback,postindex) with
+ | (true,true) ->
+ sprintf "%s %s,%s,[%s],%s" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n) (pp_big_imm offset)
+ | (true,false) ->
+ sprintf "%s %s,%s,[%s,%s]!" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n) (pp_big_imm offset)
+ | (false,false) ->
+ if eq_bit64 offset (bit64_of_int 0) then
+ sprintf "%s %s,%s,[%s]" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n)
+ else
+ sprintf "%s %s,%s,[%s,%s]" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n) (pp_big_imm offset)
+ | (false,true) -> failwith "unexpected value"
+ end
+
+| `AArch64LoadImmediate (n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize) ->
+ begin
+ if memop = MemOp_PREFETCH then
+ begin
+ (* the ast does not hold enough information to distinguish PRFM and PRFUM in some cases.
+ PRFM: <pimm> is a multiple of 8 in the range 0 to 32760
+ PRFUM: <simm> is in the range -256 to 255 *)
+ if eq_bit64 offset (bit64_of_int 0) then
+ sprintf "PRFM %s,[%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n)
+ else if big_in_range offset (-256) 255 then
+ sprintf "PRFUM %s,[%s,%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_big_imm offset)
+ else
+ sprintf "PRFM %s,[%s,%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_big_imm offset)
+ end
+ else
+ let inst =
+ (if memop = MemOp_LOAD then "LD" else "ST") ^
+ (if not wback && not postindex &&
+ not begin match datasize with
+ | DataSize8 ->
+ Nat_big_num.less_equal Nat_big_num.zero offset &&
+ Nat_big_num.less_equal offset (Nat_big_num.of_int 4095)
+ | DataSize16 ->
+ Nat_big_num.less_equal Nat_big_num.zero offset &&
+ Nat_big_num.less_equal offset (Nat_big_num.of_int 8190) &&
+ Nat_big_num.equal
+ (Nat_big_num.modulus offset (Nat_big_num.of_int 2))
+ Nat_big_num.zero
+ | DataSize32 ->
+ Nat_big_num.less_equal Nat_big_num.zero offset &&
+ Nat_big_num.less_equal offset (Nat_big_num.of_int 16380) &&
+ Nat_big_num.equal
+ (Nat_big_num.modulus offset (Nat_big_num.of_int 4))
+ Nat_big_num.zero
+ | DataSize64 ->
+ Nat_big_num.less_equal Nat_big_num.zero offset &&
+ Nat_big_num.less_equal offset (Nat_big_num.of_int 32760) &&
+ Nat_big_num.equal
+ (Nat_big_num.modulus offset (Nat_big_num.of_int 8))
+ Nat_big_num.zero
+ end
+ then
+ begin
+ if acctype=AccType_UNPRIV then "TR"
+ else "UR"
+ end
+ else "R") ^
+ (if signed then "S" else "") ^
+ (match datasize with
+ | DataSize8 -> "B"
+ | DataSize16 -> "H"
+ | DataSize32 -> if regsize = Set32 then "" else "W"
+ | DataSize64 -> "") in
+ match (wback,postindex) with
+ | (true,true) ->
+ sprintf "%s %s,[%s],%s" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_big_imm offset)
+ | (true,false) ->
+ sprintf "%s %s,[%s,%s]!" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_big_imm offset)
+ | (false,false) ->
+ if eq_bit64 offset (bit64_of_int 0) then
+ sprintf "%s %s,[%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n)
+ else
+ sprintf "%s %s,[%s,%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_big_imm offset)
+ | (false,true) -> failwith "unexpected value"
+ end
+
+| `AArch64LoadLiteral (t,memop,signed,size,offset,datasize) ->
+ if memop = MemOp_PREFETCH then
+ sprintf "PRFM %s,%s" (pp_prfop (inst_reg_to_int t)) (pp_offset false offset)
+ else
+ let datasize =
+ if signed then Set64
+ else
+ begin match datasize with
+ | DataSize64 -> Set64
+ | DataSize32 -> Set32
+ | DataSize16 | DataSize8 -> failwith "unexpected value"
+ end
+ in
+ sprintf "%s %s,%s" (if signed then "LDRSW" else "LDR") (pp_regzr datasize t) (pp_offset false offset)
+
+| `AArch64LoadRegister (n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize) ->
+ begin
+ if memop = MemOp_PREFETCH then
+ begin
+ if extend_type = ExtendType_UXTX && shift = 0 then
+ sprintf "PRFM %s,[%s,%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m)
+ else if extend_type = ExtendType_UXTX (* && shift <> 0 *) then
+ sprintf "PRFM %s,[%s,%s,LSL %s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_imm shift)
+ else
+ sprintf "PRFM %s,[%s,%s%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_ldrstr_regext extend_type shift)
+ end
+ else
+ let inst =
+ (if memop = MemOp_LOAD then "LDR" else "STR") ^
+ (if signed then "S" else "") ^
+ (match datasize with
+ | DataSize8 -> "B"
+ | DataSize16 -> "H"
+ | DataSize32 -> if regsize = Set32 then "" else "W"
+ | DataSize64 -> "") in
+ if extend_type = ExtendType_UXTX && shift = 0 then
+ sprintf "%s %s,[%s,%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m)
+ else if extend_type = ExtendType_UXTX (* && shift <> 0 *) then
+ sprintf "%s %s,[%s,%s,LSL %s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_imm shift)
+ else
+ sprintf "%s %s,[%s,%s%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_ldrstr_regext extend_type shift)
+ end
+
+| `AArch64MultiplyAddSub (d,n,m,a,destsize,datasize,sub_op) ->
+ if is_zero_reg a then
+ sprintf "%s %s,%s,%s" (if sub_op then "MNEG" else "MUL") (pp_regzr destsize d) (pp_regzr destsize n) (pp_regzr destsize m)
+ else
+ sprintf "%s %s,%s,%s,%s" (if sub_op then "MSUB" else "MADD") (pp_regzr destsize d) (pp_regzr destsize n) (pp_regzr destsize m) (pp_regzr destsize a)
+
+| `AArch64MoveWide (d,datasize,imm,pos,opcode) ->
+ if opcode = MoveWideOp_N && datasize = Set32 && (not (imm = 0 && pos <> 0)) && not (imm = 0xffff) then
+ sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_imm (lnot (imm lsl (pos*16))))
+ else if opcode = MoveWideOp_N && datasize = Set64 && (not (imm = 0 && pos <> 0)) then
+ sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_imm (lnot (imm lsl (pos*16))))
+ else if opcode = MoveWideOp_Z && (not (imm = 0 && pos <> 0)) then
+ sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_imm (imm lsl (pos*16)))
+ else if pos = 0 then
+ sprintf "%s %s,%s" (pp_movwide opcode) (pp_regzr datasize d) (pp_imm imm)
+ else
+ sprintf "%s %s,%s,LSL %s" (pp_movwide opcode) (pp_regzr datasize d) (pp_imm imm) (pp_imm pos)
+
+| `AArch64Reverse (d,n,datasize,op) ->
+ sprintf "%s %s,%s" (pp_reverse datasize op) (pp_regzr datasize d) (pp_regzr datasize n)
+
+| `AArch64Division (d,n,m,datasize,unsigned) ->
+ sprintf "%s %s,%s,%s" (if unsigned then "UDIV" else "SDIV") (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
+
+| `AArch64MultiplyAddSubLong (d,n,m,a,destsize,datasize,sub_op,unsigned) ->
+ if sub_op && is_zero_reg a then
+ sprintf "%s %s,%s,%s" (if unsigned then "UMNEGL" else "SMNEGL") (pp_regzr Set64 d) (pp_regzr Set32 n) (pp_regzr Set32 m)
+ else if not sub_op && is_zero_reg a then
+ sprintf "%s %s,%s,%s" (if unsigned then "UMULL" else "SMULL") (pp_regzr Set64 d) (pp_regzr Set32 n) (pp_regzr Set32 m)
+ else
+ sprintf "%s %s,%s,%s,%s" (pp_maddsubl sub_op unsigned) (pp_regzr Set64 d) (pp_regzr Set32 n) (pp_regzr Set32 m) (pp_regzr Set64 a)
+
+| `AArch64MultiplyHigh (d,n,m,a,destsize,datasize,unsigned) ->
+ sprintf "%s %s,%s,%s" (if unsigned then "UMULH" else "SMULH") (pp_regzr Set64 d) (pp_regzr Set64 n) (pp_regzr Set64 m)
+
+| `AArch64TestBitAndBranch (t,datasize,bit_pos,bit_val,offset) ->
+ sprintf "%s %s,%s,%s" (if bit_pos = 1 then "TBNZ" else "TBZ") (pp_regzr datasize t) (pp_imm bit_pos) (pp_offset false offset)
+
+| `AArch64MoveSystemRegister (t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read) ->
+ if read then
+ sprintf "MRS %s,%s" (pp_regzr Set64 t) (pp_sysreg (sys_op0,sys_op1,sys_op2,sys_crn,sys_crm))
+ else
+ sprintf "MSR %s,%s" (pp_sysreg (sys_op0,sys_op1,sys_op2,sys_crn,sys_crm)) (pp_regzr Set64 t)
+
+| `AArch64MoveSystemImmediate (operand,field) ->
+ sprintf "MSR %s,%s" (pp_pstatefield field) (pp_imm operand)
diff --git a/aarch64_small/gen/regs_out_in.hgen b/aarch64_small/gen/regs_out_in.hgen
new file mode 100644
index 00000000..724a574b
--- /dev/null
+++ b/aarch64_small/gen/regs_out_in.hgen
@@ -0,0 +1,155 @@
+(* for each instruction instance, identify the role of the registers
+ and possible branching: (outputs, inputs, voidstars, branch) *)
+
+| `AArch64TMStart t -> failwith "TSTART is not implemented"
+| `AArch64TMCommit -> failwith "TCOMMIT is not implemented"
+| `AArch64TMAbort (retry,reason) -> failwith "TABORT is not implemented"
+| `AArch64TMTest -> failwith "TTEST is not implemented"
+
+| `AArch64AddSubCarry (d,n,m,_datasize,_sub_op,_setflags) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64AddSubExtendRegister (d,n,m,_datasize,_sub_op,_setflags,_extend_type,_shift) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64AddSubShiftedRegister (d,n,m,_datasize,_sub_op,_setflags,_shift_type,_shift_amount) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64AddSubImmediate (d,n,_datasize,_sub_op,_setflags,_imm) ->
+ ([d], [n], [], [Next])
+
+| `AArch64Address (d,_page,_imm) ->
+ ([d], [], [], [Next])
+
+| `AArch64LogicalImmediate (d,n,_datasize,_setflags,_op,_imm) ->
+ ([d], [n], [], [Next])
+
+| `AArch64LogicalShiftedRegister (d,n,m,_datasize,_setflags,_op,_shift_type,_shift_amount,_invert) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64Shift (d,n,m,_datasize,_shift_type) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64BranchConditional (__offset,_condition) ->
+ ([], [], [], [Next])
+
+| `AArch64BranchImmediate (branch_type,__offset) ->
+ ([], [], [], [Next])
+
+| `AArch64BitfieldMove (d,n,_datasize,_inzero,_extend,_R,_S,_wmask,_tmask) ->
+ ([d], [n], [], [Next])
+
+| `AArch64BranchRegister (n,branch_type) ->
+ ([], [n], [], [Next])
+
+| `AArch64CompareAndBranch (t,_datasize,_iszero,__offset) ->
+ ([], [t], [], [Next])
+
+| `AArch64ConditionalCompareImmediate (n,_datasize,_sub_op,_condition,_flags,_imm) ->
+ ([], [n], [], [Next])
+
+| `AArch64ConditionalCompareRegister (n,m,_datasize,_sub_op,_condition,_flags) ->
+ ([], [n; m], [], [Next])
+
+| `AArch64ClearExclusiveMonitor (_imm) ->
+ ([], [], [], [Next])
+
+| `AArch64CountLeading (d,n,_datasize,__opcode) ->
+ ([d], [n], [], [Next])
+
+| `AArch64CRC (d,n,m,_size,_crc32c) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64ConditionalSelect (d,n,m,_datasize,_condition,_else_inv,_else_inc) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64Barrier (_op,_domain,_types) ->
+ ([], [], [], [Next])
+
+| `AArch64ExtractRegister (d,n,m,_datasize,_lsb) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64Hint (_op) ->
+ ([], [], [], [Next])
+
+| `AArch64LoadStoreAcqExc (n,t,t2,s,_acctype,false,false,MemOp_STORE,_elsize,_regsize,_datasize) ->
+ ([], [t; n], [n], [Next])
+| `AArch64LoadStoreAcqExc (n,t,t2,s,_acctype,true,false,MemOp_STORE,_elsize,_regsize,_datasize) ->
+ ([s], [t; n], [n], [Next])
+| `AArch64LoadStoreAcqExc (n,t,t2,s,_acctype,true,true,MemOp_STORE,_elsize,_regsize,_datasize) ->
+ ([s], [t; t2; n], [n], [Next])
+
+| `AArch64LoadStoreAcqExc (n,t,t2,s,_acctype,false,false,MemOp_LOAD,_elsize,_regsize,_datasize) ->
+ ([t], [n], [n], [Next])
+| `AArch64LoadStoreAcqExc (n,t,t2,s,_acctype,true,false,MemOp_LOAD,_elsize,_regsize,_datasize) ->
+ ([t], [n], [n], [Next])
+| `AArch64LoadStoreAcqExc (n,t,t2,s,_acctype,true,true,MemOp_LOAD,_elsize,_regsize,_datasize) ->
+ ([t; t2], [n], [n], [Next])
+
+| `AArch64LoadStorePair (false,_postindex,n,t,t2,_acctype,MemOp_STORE,_signed,_datasize,_offset) ->
+ ([], [n; t; t2], [n], [Next])
+| `AArch64LoadStorePair (true,_postindex,n,t,t2,_acctype,MemOp_STORE,_signed,_datasize,_offset) ->
+ ([n], [n; t; t2], [n], [Next])
+
+| `AArch64LoadStorePair (false,_postindex,n,t,t2,_acctype,MemOp_LOAD,_signed,_datasize,_offset) ->
+ ([t; t2], [n], [n], [Next])
+| `AArch64LoadStorePair (true,_postindex,n,t,t2,_acctype,MemOp_LOAD,_signed,_datasize,_offset) ->
+ ([t; t2; n], [n], [n], [Next])
+
+| `AArch64LoadImmediate (n,t,_acctype,MemOp_STORE,_signed,false,_postindex,_offset,_regsize,_datasize) ->
+ ([], [n; t], [n], [Next])
+| `AArch64LoadImmediate (n,t,_acctype,MemOp_STORE,_signed,true,_postindex,_offset,_regsize,_datasize) ->
+ ([n], [n; t], [n], [Next])
+
+| `AArch64LoadImmediate (n,t,_acctype,MemOp_LOAD,_signed,false,_postindex,_offset,_regsize,_datasize) ->
+ ([t], [n], [n], [Next])
+| `AArch64LoadImmediate (n,t,_acctype,MemOp_LOAD,_signed,true,_postindex,_offset,_regsize,_datasize) ->
+ ([t; n], [n], [n], [Next])
+
+| `AArch64LoadLiteral (t,MemOp_STORE,_signed,_size,_offset,_datasize) ->
+ ([], [t], [], [Next])
+
+| `AArch64LoadLiteral (t,MemOp_LOAD,_signed,_size,_offset,_datasize) ->
+ ([t], [], [], [Next])
+
+| `AArch64LoadRegister (n,t,m,_acctype,MemOp_STORE,_signed,false,_postindex,_extend_type,_shift,_regsize,_datasize) ->
+ ([], [n; t; m], [n], [Next])
+| `AArch64LoadRegister (n,t,m,_acctype,MemOp_STORE,_signed,true,_postindex,_extend_type,_shift,_regsize,_datasize) ->
+ ([n], [n; t; m], [n], [Next])
+
+| `AArch64LoadRegister (n,t,m,_acctype,MemOp_LOAD,_signed,false,_postindex,_extend_type,_shift,_regsize,_datasize) ->
+ ([t], [n; m], [n], [Next])
+| `AArch64LoadRegister (n,t,m,_acctype,MemOp_LOAD,_signed,true,_postindex,_extend_type,_shift,_regsize,_datasize) ->
+ ([t; n], [n; m], [n], [Next])
+
+| `AArch64LoadRegister (n,t,m,_acctype,MemOp_PREFETCH,_signed,_wback,_postindex,_extend_type,_shift,_regsize,_datasize) ->
+ ([], [n; m], [n], [Next])
+
+| `AArch64MultiplyAddSub (d,n,m,a,_destsize,_datasize,_sub_op) ->
+ ([d], [n; m; a], [], [Next])
+
+| `AArch64MoveWide (d,_datasize,_imm,_pos,_opcode) ->
+ ([d], [], [], [Next])
+
+| `AArch64Reverse (d,n,_datasize,_op) ->
+ ([d], [n], [], [Next])
+
+| `AArch64Division (d,n,m,_datasize,_unsigned) ->
+ ([d], [n; m], [], [Next])
+
+| `AArch64MultiplyAddSubLong (d,n,m,a,_destsize,_datasize,_sub_op,_unsigned) ->
+ ([d], [n; m; a], [], [Next])
+
+| `AArch64MultiplyHigh (d,n,m,a,_destsize,_datasize,_unsigned) ->
+ ([d], [n; m; a], [], [Next])
+
+| `AArch64TestBitAndBranch (t,_datasize,_bit_pos,_bit_val,_offset) ->
+ ([], [t], [], [Next])
+
+| `AArch64MoveSystemRegister (t,_sys_op0,_sys_op1,_sys_op2,_sys_crn,_sys_crm,true) ->
+ ([t], [], [], [Next])
+| `AArch64MoveSystemRegister (t,_sys_op0,_sys_op1,_sys_op2,_sys_crn,_sys_crm,false) ->
+ ([], [t], [], [Next])
+
+| `AArch64MoveSystemImmediate (_operand,_field) ->
+ ([], [], [], [Next])
diff --git a/aarch64_small/gen/sail_trans_out.hgen b/aarch64_small/gen/sail_trans_out.hgen
new file mode 100644
index 00000000..84826c18
--- /dev/null
+++ b/aarch64_small/gen/sail_trans_out.hgen
@@ -0,0 +1,326 @@
+| ("TMStart", [t]) ->
+ `AArch64TMStart (translate_out_regzr Set64 t)
+
+| ("TMCommit", []) -> `AArch64TMCommit
+
+| ("TMAbort", [retry; reason]) ->
+ `AArch64TMAbort ( translate_out_bool retry,
+ translate_out_bits reason)
+
+| ("TMTest", []) -> `AArch64TMTest
+
+| ("ImplementationDefinedStopFetching",[]) ->
+ `AArch64ImplementationDefinedStopFetching
+
+| ("ImplementationDefinedThreadStart",[]) ->
+ `AArch64ImplementationDefinedThreadStart
+
+| ("ImplementationDefinedTestBeginEnd" , [isEnd]) ->
+ `AArch64ImplementationDefinedTestBeginEnd (translate_out_bool isEnd)
+
+| ("AddSubCarry", [d; n; m; datasize; sub_op; setflags]) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64AddSubCarry ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bool setflags)
+
+| "AddSubExtendRegister", [d; n; m; datasize; sub_op; setflags; extend_type; shift] ->
+ let setflags' = translate_out_bool setflags in
+ let datasize' = translate_out_reg_size datasize in
+ let extend_type' = translate_out_extendType extend_type in
+ `AArch64AddSubExtendRegister ((if setflags' then translate_out_regzr datasize' d else translate_out_regsp datasize' d),
+ translate_out_regsp datasize' n,
+ translate_out_regzrbyext datasize' extend_type' m,
+ datasize',
+ translate_out_bool sub_op,
+ setflags',
+ extend_type',
+ translate_out_int shift)
+
+| "AddSubShiftedRegister", [d; n; m; datasize; sub_op; setflags; shift_type; shift_amount] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64AddSubShiftedRegister ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bool setflags,
+ translate_out_shiftType shift_type,
+ translate_out_int shift_amount)
+
+| "AddSubImmediate", [d; n; datasize; sub_op; setflags; imm] ->
+ let setflags' = translate_out_bool setflags in
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64AddSubImmediate ( (if setflags' then translate_out_regzr datasize' d else translate_out_regsp datasize' d),
+ translate_out_regsp datasize' n,
+ datasize',
+ translate_out_bool sub_op,
+ setflags',
+ translate_out_reg_size_bits imm)
+
+| "Address", [d; page; imm] ->
+ `AArch64Address ( translate_out_regzr Set64 d,
+ translate_out_bool page,
+ translate_out_signed_big_bit imm)
+
+| "LogicalImmediate", [d; n; datasize; setflags; op; imm] ->
+ let setflags' = translate_out_bool setflags in
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64LogicalImmediate ((if setflags' then translate_out_regzr datasize' d else translate_out_regsp datasize' d),
+ translate_out_regzr datasize' n,
+ datasize',
+ setflags',
+ translate_out_logicalOp op,
+ translate_out_reg_size_bits imm)
+
+| "LogicalShiftedRegister", [d; n; m; datasize; setflags; op; shift_type; shift_amount; invert] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64LogicalShiftedRegister (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool setflags,
+ translate_out_logicalOp op,
+ translate_out_shiftType shift_type,
+ translate_out_int shift_amount,
+ translate_out_bool invert)
+
+| "Shift", [d; n; m; datasize; shift_type] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64Shift ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_shiftType shift_type)
+
+| "BranchConditional", [offset; condition] ->
+ `AArch64BranchConditional ( translate_out_signed_big_bit offset,
+ translate_out_bits condition)
+
+| "BranchImmediate", [branch_type; offset] ->
+ `AArch64BranchImmediate ( translate_out_branchType branch_type,
+ translate_out_signed_big_bit offset)
+
+| "BitfieldMove", [d; n; datasize; inzero; extend; _R; _S; wmask; tmask] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64BitfieldMove (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ datasize',
+ translate_out_bool inzero,
+ translate_out_bool extend,
+ translate_out_int _R,
+ translate_out_int _S,
+ translate_out_reg_size_bits wmask,
+ translate_out_reg_size_bits wmask)
+
+| "BranchRegister", [n; branch_type] ->
+ `AArch64BranchRegister (translate_out_regzr Set64 n,
+ translate_out_branchType branch_type)
+
+| "CompareAndBranch", [t; datasize; iszero; offset] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64CompareAndBranch (translate_out_regzr datasize' t,
+ datasize',
+ translate_out_bool iszero,
+ translate_out_signed_big_bit offset)
+
+| "ConditionalCompareImmediate", [n; datasize; sub_op; condition; flags; imm] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ConditionalCompareImmediate ( translate_out_regzr datasize' n,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bits condition,
+ translate_out_bits flags,
+ translate_out_reg_size_bits imm)
+
+| "ConditionalCompareRegister", [n; m; datasize; sub_op; condition; flags] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ConditionalCompareRegister (translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bits condition,
+ translate_out_bits flags)
+
+| "ClearExclusiveMonitor", [imm] -> `AArch64ClearExclusiveMonitor (translate_out_int imm)
+
+| "CountLeading", [d; n; datasize; opcode] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64CountLeading (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ datasize',
+ translate_out_countOp opcode)
+
+| "CRC", [d; n; m; size; crc32c] ->
+ let size' = translate_out_data_size size in
+ `AArch64CRC ( translate_out_regzr Set32 d,
+ translate_out_regzr Set32 n,
+ translate_out_regzr (if size' = DataSize64 then Set64 else Set32) m,
+ size',
+ translate_out_bool crc32c)
+
+| "ConditionalSelect", [d; n; m; datasize; condition; else_inf; else_inc] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ConditionalSelect ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bits condition,
+ translate_out_bool else_inf,
+ translate_out_bool else_inc)
+
+| "Barrier", [op; domain; types] ->
+ `AArch64Barrier ( translate_out_memBarrierOp op,
+ translate_out_mBReqDomain domain,
+ translate_out_mBReqTypes types)
+
+| "ExtractRegister", [d; n; m; datasize; lsb] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ExtractRegister ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_int lsb)
+
+| "Hint", [op] -> `AArch64Hint (translate_out_systemHintOp op)
+
+| "LoadStoreAcqExc", [n; t; t2; s; acctype; excl; pair; memop; elsize; regsize; datasize] ->
+ let regsize' = translate_out_reg_size regsize in
+ `AArch64LoadStoreAcqExc ( translate_out_regsp Set64 n,
+ translate_out_regzr regsize' t,
+ translate_out_regzr regsize' t2,
+ translate_out_regzr Set32 s,
+ translate_out_accType acctype,
+ translate_out_bool excl,
+ translate_out_bool pair,
+ translate_out_memOp memop,
+ translate_out_int elsize,
+ regsize',
+ translate_out_data_size datasize)
+
+| "LoadStorePair",[wback; postindex; n; t; t2; acctype; memop; signed; datasize; offset] ->
+ let signed' = translate_out_bool signed in
+ let regsize = if signed' then Set64 else translate_out_reg_size datasize in
+ `AArch64LoadStorePair ( translate_out_bool wback,
+ translate_out_bool postindex,
+ translate_out_regsp Set64 n,
+ translate_out_regzr regsize t,
+ translate_out_regzr regsize t2,
+ translate_out_accType acctype,
+ translate_out_memOp memop,
+ signed',
+ translate_out_data_size datasize,
+ translate_out_signed_big_bit offset)
+
+| "LoadImmediate",[n; t; acctype; memop; signed; wback; postindex; offset; regsize; datasize] ->
+ let regsize' = translate_out_reg_size regsize in
+ `AArch64LoadImmediate ( translate_out_regsp Set64 n,
+ translate_out_regzr regsize' t,
+ translate_out_accType acctype,
+ translate_out_memOp memop,
+ translate_out_bool signed,
+ translate_out_bool wback,
+ translate_out_bool postindex,
+ translate_out_signed_big_bit offset,
+ translate_out_reg_size regsize,
+ translate_out_data_size datasize)
+
+| "LoadLiteral",[t; memop; signed; size; offset; datasize] ->
+ `AArch64LoadLiteral ( translate_out_regzr (translate_out_reg_size datasize) t,
+ translate_out_memOp memop,
+ translate_out_bool signed,
+ translate_out_int size,
+ translate_out_signed_big_bit offset,
+ translate_out_data_size datasize)
+
+| "LoadRegister",[n; t; m; acctype; memop; signed; wback; postindex; extend_type; shift; regsize; datasize] ->
+ let regsize' = translate_out_reg_size regsize in
+ let extend_type' = translate_out_extendType extend_type in
+ `AArch64LoadRegister (translate_out_regsp Set64 n,
+ translate_out_regzr regsize' t,
+ translate_out_regzrbyext Set64 extend_type' m,
+ translate_out_accType acctype,
+ translate_out_memOp memop,
+ translate_out_bool signed,
+ translate_out_bool wback,
+ translate_out_bool postindex,
+ extend_type',
+ translate_out_int shift,
+ translate_out_reg_size regsize ,
+ translate_out_data_size datasize)
+
+| "MultiplyAddSub", [d; n; m; a; destsize; datasize; sub_op] ->
+ let destsize' = translate_out_reg_size destsize in
+ `AArch64MultiplyAddSub (translate_out_regzr destsize' d,
+ translate_out_regzr destsize' n,
+ translate_out_regzr destsize' m,
+ translate_out_regzr destsize' a,
+ destsize',
+ translate_out_data_size datasize,
+ translate_out_bool sub_op)
+
+| "MoveWide", [d; datasize; imm; pos; opcode] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64MoveWide (translate_out_regzr datasize' d,
+ datasize',
+ translate_out_bits imm,
+ translate_out_int pos,
+ translate_out_moveWideOp opcode)
+
+| "Reverse", [d; n; datasize; op] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64Reverse ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ datasize',
+ translate_out_revOp op)
+
+| "Division", [d; n; m; datasize; unsigned] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64Division (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool unsigned)
+
+| "MultiplyAddSubLong", [d; n; m; a; destsize; datasize; sub_op; unsigned] ->
+ `AArch64MultiplyAddSubLong (translate_out_regzr Set64 d,
+ translate_out_regzr Set32 n,
+ translate_out_regzr Set32 m,
+ translate_out_regzr Set64 a,
+ translate_out_reg_size destsize,
+ translate_out_data_size datasize,
+ translate_out_bool sub_op,
+ translate_out_bool unsigned)
+
+| "MultiplyHigh", [d; n; m; a; destsize; datasize; unsigned] ->
+ `AArch64MultiplyHigh (translate_out_regzr Set64 d,
+ translate_out_regzr Set64 n,
+ translate_out_regzr Set64 m,
+ translate_out_regzr Set64 a,
+ translate_out_reg_size destsize,
+ translate_out_data_size datasize,
+ translate_out_bool unsigned)
+
+| "TestBitAndBranch", [t; datasize; bit_pos; bit_val; offset] ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64TestBitAndBranch (translate_out_regzr datasize' t,
+ datasize',
+ translate_out_int bit_pos,
+ translate_out_bool bit_val,
+ translate_out_signed_big_bit offset)
+
+| "MoveSystemRegister", [t; sys_op0; sys_op1; sys_op2; sys_crn; sys_crm; read] ->
+ `AArch64MoveSystemRegister (translate_out_regzr Set64 t,
+ translate_out_int sys_op0,
+ translate_out_int sys_op1,
+ translate_out_int sys_op2,
+ translate_out_int sys_crn,
+ translate_out_int sys_crm,
+ translate_out_bool read)
+
+| "MoveSystemImmediate", [operand; field] ->
+ `AArch64MoveSystemImmediate ( translate_out_int operand,
+ translate_out_pSTATEField field)
diff --git a/aarch64_small/gen/shallow_ast_to_herdtools_ast.hgen b/aarch64_small/gen/shallow_ast_to_herdtools_ast.hgen
new file mode 100644
index 00000000..7362304c
--- /dev/null
+++ b/aarch64_small/gen/shallow_ast_to_herdtools_ast.hgen
@@ -0,0 +1,326 @@
+| TMStart t ->
+ `AArch64TMStart (translate_out_regzr Set64 t)
+
+| TMCommit -> `AArch64TMCommit
+
+| TMAbort (retry, reason) ->
+ `AArch64TMAbort ( translate_out_bool retry,
+ translate_out_bits reason)
+
+| TMTest -> `AArch64TMTest
+
+| ImplementationDefinedStopFetching ->
+ `AArch64ImplementationDefinedStopFetching
+
+| ImplementationDefinedThreadStart ->
+ `AArch64ImplementationDefinedThreadStart
+
+| ImplementationDefinedTestBeginEnd (isEnd) ->
+ `AArch64ImplementationDefinedTestBeginEnd (translate_out_bool isEnd)
+
+| AddSubCarry (d, n, m, datasize, sub_op, setflags) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64AddSubCarry ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bool setflags)
+
+| AddSubExtendRegister (d, n, m, datasize, sub_op, setflags, extend_type, shift) ->
+ let setflags' = translate_out_bool setflags in
+ let datasize' = translate_out_reg_size datasize in
+ let extend_type' = translate_out_extendType extend_type in
+ `AArch64AddSubExtendRegister ((if setflags' then translate_out_regzr datasize' d else translate_out_regsp datasize' d),
+ translate_out_regsp datasize' n,
+ translate_out_regzrbyext datasize' extend_type' m,
+ datasize',
+ translate_out_bool sub_op,
+ setflags',
+ extend_type',
+ translate_out_int shift)
+
+| AddSubShiftedRegister (d, n, m, datasize, sub_op, setflags, shift_type, shift_amount) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64AddSubShiftedRegister ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bool setflags,
+ translate_out_shiftType shift_type,
+ translate_out_int shift_amount)
+
+| AddSubImmediate (d, n, datasize, sub_op, setflags, imm) ->
+ let setflags' = translate_out_bool setflags in
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64AddSubImmediate ( (if setflags' then translate_out_regzr datasize' d else translate_out_regsp datasize' d),
+ translate_out_regsp datasize' n,
+ datasize',
+ translate_out_bool sub_op,
+ setflags',
+ translate_out_reg_size_bits imm)
+
+| Address0 (d, page, imm) ->
+ `AArch64Address ( translate_out_regzr Set64 d,
+ translate_out_bool page,
+ translate_out_signed_big_bit imm)
+
+| LogicalImmediate (d, n, datasize, setflags, op, imm) ->
+ let setflags' = translate_out_bool setflags in
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64LogicalImmediate ((if setflags' then translate_out_regzr datasize' d else translate_out_regsp datasize' d),
+ translate_out_regzr datasize' n,
+ datasize',
+ setflags',
+ translate_out_logicalOp op,
+ translate_out_reg_size_bits imm)
+
+| LogicalShiftedRegister (d, n, m, datasize, setflags, op, shift_type, shift_amount, invert) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64LogicalShiftedRegister (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool setflags,
+ translate_out_logicalOp op,
+ translate_out_shiftType shift_type,
+ translate_out_int shift_amount,
+ translate_out_bool invert)
+
+| Shift (d, n, m, datasize, shift_type) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64Shift ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_shiftType shift_type)
+
+| BranchConditional (offset, condition) ->
+ `AArch64BranchConditional ( translate_out_signed_big_bit offset,
+ translate_out_bits condition)
+
+| BranchImmediate (branch_type, offset) ->
+ `AArch64BranchImmediate ( translate_out_branchType branch_type,
+ translate_out_signed_big_bit offset)
+
+| BitfieldMove (d, n, datasize, inzero, extend, _R, _S, wmask, tmask) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64BitfieldMove (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ datasize',
+ translate_out_bool inzero,
+ translate_out_bool extend,
+ translate_out_int _R,
+ translate_out_int _S,
+ translate_out_reg_size_bits wmask,
+ translate_out_reg_size_bits wmask)
+
+| BranchRegister (n, branch_type) ->
+ `AArch64BranchRegister (translate_out_regzr Set64 n,
+ translate_out_branchType branch_type)
+
+| CompareAndBranch (t, datasize, iszero, offset) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64CompareAndBranch (translate_out_regzr datasize' t,
+ datasize',
+ translate_out_bool iszero,
+ translate_out_signed_big_bit offset)
+
+| ConditionalCompareImmediate (n, datasize, sub_op, condition, flags, imm) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ConditionalCompareImmediate ( translate_out_regzr datasize' n,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bits condition,
+ translate_out_bits flags,
+ translate_out_reg_size_bits imm)
+
+| ConditionalCompareRegister (n, m, datasize, sub_op, condition, flags) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ConditionalCompareRegister (translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool sub_op,
+ translate_out_bits condition,
+ translate_out_bits flags)
+
+| ClearExclusiveMonitor (imm) -> `AArch64ClearExclusiveMonitor (translate_out_int imm)
+
+| CountLeading (d, n, datasize, opcode) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64CountLeading (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' d,
+ datasize',
+ translate_out_countOp opcode)
+
+| CRC (d, n, m, size, crc32c) ->
+ let size' = translate_out_data_size size in
+ `AArch64CRC ( translate_out_regzr Set32 d,
+ translate_out_regzr Set32 n,
+ translate_out_regzr (if size' = DataSize64 then Set64 else Set32) m,
+ size',
+ translate_out_bool crc32c)
+
+| ConditionalSelect (d, n, m, datasize, condition, else_inf, else_inc) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ConditionalSelect ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bits condition,
+ translate_out_bool else_inf,
+ translate_out_bool else_inc)
+
+| Barrier3 (op, domain, types) ->
+ `AArch64Barrier ( translate_out_memBarrierOp op,
+ translate_out_mBReqDomain domain,
+ translate_out_mBReqTypes types)
+
+| ExtractRegister (d, n, m, datasize, lsb) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64ExtractRegister ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_int lsb)
+
+| Hint (op) -> `AArch64Hint (translate_out_systemHintOp op)
+
+| LoadStoreAcqExc (n, t, t2, s, acctype, excl, pair, memop, elsize, regsize, datasize) ->
+ let regsize' = translate_out_reg_size regsize in
+ `AArch64LoadStoreAcqExc ( translate_out_regsp Set64 n,
+ translate_out_regzr regsize' t,
+ translate_out_regzr regsize' t2,
+ translate_out_regzr Set32 s,
+ translate_out_accType acctype,
+ translate_out_bool excl,
+ translate_out_bool pair,
+ translate_out_memOp memop,
+ translate_out_int elsize,
+ regsize',
+ translate_out_data_size datasize)
+
+| LoadStorePair(wback, postindex, n, t, t2, acctype, memop, signed, datasize, offset) ->
+ let signed' = translate_out_bool signed in
+ let regsize = if signed' then Set64 else translate_out_reg_size datasize in
+ `AArch64LoadStorePair ( translate_out_bool wback,
+ translate_out_bool postindex,
+ translate_out_regsp Set64 n,
+ translate_out_regzr regsize t,
+ translate_out_regzr regsize t2,
+ translate_out_accType acctype,
+ translate_out_memOp memop,
+ signed',
+ translate_out_data_size datasize,
+ translate_out_signed_big_bit offset)
+
+| LoadImmediate(n, t, acctype, memop, signed, wback, postindex, offset, regsize, datasize) ->
+ let regsize' = translate_out_reg_size regsize in
+ `AArch64LoadImmediate ( translate_out_regsp Set64 n,
+ translate_out_regzr regsize' t,
+ translate_out_accType acctype,
+ translate_out_memOp memop,
+ translate_out_bool signed,
+ translate_out_bool wback,
+ translate_out_bool postindex,
+ translate_out_signed_big_bit offset,
+ translate_out_reg_size regsize,
+ translate_out_data_size datasize)
+
+| LoadLiteral(t, memop, signed, size, offset, datasize) ->
+ `AArch64LoadLiteral ( translate_out_regzr (translate_out_reg_size datasize) t,
+ translate_out_memOp memop,
+ translate_out_bool signed,
+ translate_out_int size,
+ translate_out_signed_big_bit offset,
+ translate_out_data_size datasize)
+
+| LoadRegister(n, t, m, acctype, memop, signed, wback, postindex, extend_type, shift, regsize, datasize) ->
+ let regsize' = translate_out_reg_size regsize in
+ let extend_type' = translate_out_extendType extend_type in
+ `AArch64LoadRegister (translate_out_regsp Set64 n,
+ translate_out_regzr regsize' t,
+ translate_out_regzrbyext Set64 extend_type' m,
+ translate_out_accType acctype,
+ translate_out_memOp memop,
+ translate_out_bool signed,
+ translate_out_bool wback,
+ translate_out_bool postindex,
+ extend_type',
+ translate_out_int shift,
+ translate_out_reg_size regsize ,
+ translate_out_data_size datasize)
+
+| MultiplyAddSub (d, n, m, a, destsize, datasize, sub_op) ->
+ let destsize' = translate_out_reg_size destsize in
+ `AArch64MultiplyAddSub (translate_out_regzr destsize' d,
+ translate_out_regzr destsize' n,
+ translate_out_regzr destsize' m,
+ translate_out_regzr destsize' a,
+ destsize',
+ translate_out_data_size datasize,
+ translate_out_bool sub_op)
+
+| MoveWide (d, datasize, imm, pos, opcode) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64MoveWide (translate_out_regzr datasize' d,
+ datasize',
+ translate_out_bits imm,
+ translate_out_int pos,
+ translate_out_moveWideOp opcode)
+
+| Reverse (d, n, datasize, op) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64Reverse ( translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ datasize',
+ translate_out_revOp op)
+
+| Division (d, n, m, datasize, unsigned) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64Division (translate_out_regzr datasize' d,
+ translate_out_regzr datasize' n,
+ translate_out_regzr datasize' m,
+ datasize',
+ translate_out_bool unsigned)
+
+| MultiplyAddSubLong (d, n, m, a, destsize, datasize, sub_op, unsigned) ->
+ `AArch64MultiplyAddSubLong (translate_out_regzr Set64 d,
+ translate_out_regzr Set32 n,
+ translate_out_regzr Set32 m,
+ translate_out_regzr Set64 a,
+ translate_out_reg_size destsize,
+ translate_out_data_size datasize,
+ translate_out_bool sub_op,
+ translate_out_bool unsigned)
+
+| MultiplyHigh (d, n, m, a, destsize, datasize, unsigned) ->
+ `AArch64MultiplyHigh (translate_out_regzr Set64 d,
+ translate_out_regzr Set64 n,
+ translate_out_regzr Set64 m,
+ translate_out_regzr Set64 a,
+ translate_out_reg_size destsize,
+ translate_out_data_size datasize,
+ translate_out_bool unsigned)
+
+| TestBitAndBranch (t, datasize, bit_pos, bit_val, offset) ->
+ let datasize' = translate_out_reg_size datasize in
+ `AArch64TestBitAndBranch (translate_out_regzr datasize' t,
+ datasize',
+ translate_out_int bit_pos,
+ translate_out_bool bit_val,
+ translate_out_signed_big_bit offset)
+
+| MoveSystemRegister (t, sys_op0, sys_op1, sys_op2, sys_crn, sys_crm, read) ->
+ `AArch64MoveSystemRegister (translate_out_regzr Set64 t,
+ translate_out_int sys_op0,
+ translate_out_int sys_op1,
+ translate_out_int sys_op2,
+ translate_out_int sys_crn,
+ translate_out_int sys_crm,
+ translate_out_bool read)
+
+| MoveSystemImmediate (operand, field) ->
+ `AArch64MoveSystemImmediate ( translate_out_bits operand,
+ translate_out_pSTATEField field)
diff --git a/aarch64_small/gen/shallow_types_to_herdtools_types.hgen b/aarch64_small/gen/shallow_types_to_herdtools_types.hgen
new file mode 100644
index 00000000..771f52ac
--- /dev/null
+++ b/aarch64_small/gen/shallow_types_to_herdtools_types.hgen
@@ -0,0 +1,154 @@
+let translate_out_big_int_bits x = Sail_values.unsigned x
+
+let translate_out_big_bit = Sail_values.unsigned
+
+let translate_out_signed_big_bit = Sail_values.signed
+
+let translate_out_int inst = (Nat_big_num.to_int inst)
+
+let translate_out_bits bits = Nat_big_num.to_int (Sail_values.unsigned bits)
+
+let translate_out_bool = function
+ | Sail_values.B1 -> true
+ | Sail_values.B0 -> false
+ | Sail_values.BU -> failwith "translate_out_bool Undef"
+
+let translate_out_enum (name,_,bits) =
+ Nat_big_num.to_int (IInt.integer_of_bit_list bits)
+
+let translate_out_reg_size inst =
+ match translate_out_int inst with
+ | 32 -> Set32
+ | 64 -> Set64
+ | _ -> assert false
+
+let translate_out_regzr regsize reg =
+ begin match (regsize, translate_out_int reg) with
+ | (Set32, 31) -> W ZR
+ | (Set32, reg) -> W (Ireg (ireg_of_int reg))
+ | (Set64, 31) -> X ZR
+ | (Set64, reg) -> X (Ireg (ireg_of_int reg))
+ end
+
+let translate_out_regsp regsize reg =
+ begin match (regsize, translate_out_int reg) with
+ | (Set32, 31) -> W SP
+ | (Set32, reg) -> W (Ireg (ireg_of_int reg))
+ | (Set64, 31) -> X SP
+ | (Set64, reg) -> X (Ireg (ireg_of_int reg))
+ end
+
+let translate_out_regzrbyext regsize extend_type reg = begin match extend_type with
+ | ExtendType_UXTX | ExtendType_SXTX -> translate_out_regzr regsize reg
+ | _ -> translate_out_regzr Set32 reg
+ end
+
+let translate_out_reg_size_bits bits =
+ match Nat_big_num.to_int (Sail_values.length bits) with
+ | 32 -> R32Bits (translate_out_bits bits)
+ | 64 -> R64Bits (translate_out_big_bit bits)
+ | _ -> assert false
+
+let translate_out_data_size inst =
+ match (translate_out_int inst) with
+ | 8 -> DataSize8
+ | 16 -> DataSize16
+ | 32 -> DataSize32
+ | 64 -> DataSize64
+ | _ -> assert false
+
+let translate_out_extendType = function
+ | ArmV8_embed_types.ExtendType_UXTB -> ExtendType_UXTB
+ | ArmV8_embed_types.ExtendType_UXTH -> ExtendType_UXTH
+ | ArmV8_embed_types.ExtendType_UXTW -> ExtendType_UXTW
+ | ArmV8_embed_types.ExtendType_UXTX -> ExtendType_UXTX
+ | ArmV8_embed_types.ExtendType_SXTB -> ExtendType_SXTB
+ | ArmV8_embed_types.ExtendType_SXTH -> ExtendType_SXTH
+ | ArmV8_embed_types.ExtendType_SXTW -> ExtendType_SXTW
+ | ArmV8_embed_types.ExtendType_SXTX -> ExtendType_SXTX
+
+let translate_out_shiftType = function
+ | ArmV8_embed_types.ShiftType_LSL -> ShiftType_LSL
+ | ArmV8_embed_types.ShiftType_LSR -> ShiftType_LSR
+ | ArmV8_embed_types.ShiftType_ASR -> ShiftType_ASR
+ | ArmV8_embed_types.ShiftType_ROR -> ShiftType_ROR
+
+let translate_out_logicalOp = function
+ | ArmV8_embed_types.LogicalOp_AND -> LogicalOp_AND
+ | ArmV8_embed_types.LogicalOp_EOR -> LogicalOp_EOR
+ | ArmV8_embed_types.LogicalOp_ORR -> LogicalOp_ORR
+
+let translate_out_branchType = function
+ | ArmV8_embed_types.BranchType_CALL -> BranchType_CALL
+ | ArmV8_embed_types.BranchType_ERET -> BranchType_ERET
+ | ArmV8_embed_types.BranchType_DBGEXIT -> BranchType_DBGEXIT
+ | ArmV8_embed_types.BranchType_RET -> BranchType_RET
+ | ArmV8_embed_types.BranchType_JMP -> BranchType_JMP
+ | ArmV8_embed_types.BranchType_EXCEPTION -> BranchType_EXCEPTION
+ | ArmV8_embed_types.BranchType_UNKNOWN -> BranchType_UNKNOWN
+
+let translate_out_countOp = function
+ | ArmV8_embed_types.CountOp_CLZ -> CountOp_CLZ
+ | ArmV8_embed_types.CountOp_CLS -> CountOp_CLS
+ | ArmV8_embed_types.CountOp_CNT -> CountOp_CNT
+
+let translate_out_memBarrierOp = function
+ | ArmV8_embed_types.MemBarrierOp_DSB -> MemBarrierOp_DSB
+ | ArmV8_embed_types.MemBarrierOp_DMB -> MemBarrierOp_DMB
+ | ArmV8_embed_types.MemBarrierOp_ISB -> MemBarrierOp_ISB
+
+let translate_out_mBReqDomain = function
+ | ArmV8_embed_types.MBReqDomain_Nonshareable -> MBReqDomain_Nonshareable
+ | ArmV8_embed_types.MBReqDomain_InnerShareable -> MBReqDomain_InnerShareable
+ | ArmV8_embed_types.MBReqDomain_OuterShareable -> MBReqDomain_OuterShareable
+ | ArmV8_embed_types.MBReqDomain_FullSystem -> MBReqDomain_FullSystem
+
+let translate_out_mBReqTypes = function
+ | ArmV8_embed_types.MBReqTypes_Reads -> MBReqTypes_Reads
+ | ArmV8_embed_types.MBReqTypes_Writes -> MBReqTypes_Writes
+ | ArmV8_embed_types.MBReqTypes_All -> MBReqTypes_All
+
+let translate_out_systemHintOp = function
+ | ArmV8_embed_types.SystemHintOp_NOP -> SystemHintOp_NOP
+ | ArmV8_embed_types.SystemHintOp_YIELD -> SystemHintOp_YIELD
+ | ArmV8_embed_types.SystemHintOp_WFE -> SystemHintOp_WFE
+ | ArmV8_embed_types.SystemHintOp_WFI -> SystemHintOp_WFI
+ | ArmV8_embed_types.SystemHintOp_SEV -> SystemHintOp_SEV
+ | ArmV8_embed_types.SystemHintOp_SEVL -> SystemHintOp_SEVL
+
+let translate_out_accType = function
+ | ArmV8_embed_types.AccType_NORMAL -> AccType_NORMAL
+ | ArmV8_embed_types.AccType_VEC -> AccType_VEC
+ | ArmV8_embed_types.AccType_STREAM -> AccType_STREAM
+ | ArmV8_embed_types.AccType_VECSTREAM -> AccType_VECSTREAM
+ | ArmV8_embed_types.AccType_ATOMIC -> AccType_ATOMIC
+ | ArmV8_embed_types.AccType_ORDERED -> AccType_ORDERED
+ | ArmV8_embed_types.AccType_UNPRIV -> AccType_UNPRIV
+ | ArmV8_embed_types.AccType_IFETCH -> AccType_IFETCH
+ | ArmV8_embed_types.AccType_PTW -> AccType_PTW
+ | ArmV8_embed_types.AccType_DC -> AccType_DC
+ | ArmV8_embed_types.AccType_IC -> AccType_IC
+ | ArmV8_embed_types.AccType_AT -> AccType_AT
+
+let translate_out_memOp = function
+ | ArmV8_embed_types.MemOp_LOAD -> MemOp_LOAD
+ | ArmV8_embed_types.MemOp_STORE -> MemOp_STORE
+ | ArmV8_embed_types.MemOp_PREFETCH -> MemOp_PREFETCH
+
+
+let translate_out_moveWideOp = function
+ | ArmV8_embed_types.MoveWideOp_N -> MoveWideOp_N
+ | ArmV8_embed_types.MoveWideOp_Z -> MoveWideOp_Z
+ | ArmV8_embed_types.MoveWideOp_K -> MoveWideOp_K
+
+let translate_out_revOp = function
+ | ArmV8_embed_types.RevOp_RBIT -> RevOp_RBIT
+ | ArmV8_embed_types.RevOp_REV16 -> RevOp_REV16
+ | ArmV8_embed_types.RevOp_REV32 -> RevOp_REV32
+ | ArmV8_embed_types.RevOp_REV64 -> RevOp_REV64
+
+let translate_out_pSTATEField = function
+ | ArmV8_embed_types.PSTATEField_DAIFSet -> PSTATEField_DAIFSet
+ | ArmV8_embed_types.PSTATEField_DAIFClr -> PSTATEField_DAIFClr
+ | ArmV8_embed_types.PSTATEField_SP -> PSTATEField_SP
+
diff --git a/aarch64_small/gen/token_types.hgen b/aarch64_small/gen/token_types.hgen
new file mode 100644
index 00000000..411dddf9
--- /dev/null
+++ b/aarch64_small/gen/token_types.hgen
@@ -0,0 +1,85 @@
+(*** instructions ***)
+
+type token_TSTART = {txt : string}
+type token_TCOMMIT = {txt : string}
+type token_TABORT = {txt : string}
+type token_TTEST = {txt : string}
+
+type token_ADCSBC = {txt : string; sub_op : boolean; setflags : boolean}
+type token_ADDSUB = {txt : string; sub_op : boolean; setflags : boolean}
+type token_ADR = {txt : string; page : boolean}
+type token_LOGOP = {txt : string; op : logicalOp; setflags : boolean; invert : boolean}
+type token_SHIFTOP = {txt : string; shift_type : shiftType}
+type token_BCOND = {txt : string; condition : int}
+type token_B = {txt : string; branch_type : branchType}
+type token_BR = {txt : string; branch_type : branchType}
+type token_CBZ = {txt : string; iszero : boolean}
+type token_BFM = {txt : string; inzero : boolean; extend : boolean}
+type token_CCM = {txt : string; sub_op : boolean}
+type token_CM = {txt : string; sub_op : boolean}
+type token_CL = {txt : string; opcode : countOp}
+type token_CRC = {txt : string; size : data_size; crc32c : boolean}
+type token_CRC32X = {txt : string; crc32c : boolean}
+type token_CSEL = {txt : string; else_inv : boolean; else_inc : boolean}
+type token_CSET = {txt : string; else_inv : boolean; else_inc : boolean}
+type token_CSETM = {txt : string; else_inv : boolean; else_inc : boolean}
+type token_CON = {txt : string; else_inv : boolean; else_inc : boolean}
+type token_MEMBARR = {txt : string; op : memBarrierOp}
+type token_LDAXR_var32 = {elsize : int; datasize : data_size}
+type token_LDAXR = {txt : string; acctype : accType; excl : boolean; memop : memOp; var32 : token_LDAXR_var32; var64 : boolean}
+type token_STLXR_var32 = {elsize : int; datasize : data_size}
+type token_STLXR = {txt : string; acctype : accType; var32 : token_STLXR_var32; var64 : boolean}
+type token_LDXP = {txt : string; acctype : accType}
+type token_STXP = {txt : string; acctype : accType}
+type token_LDSTR_var32 = {datasize : data_size}
+type token_LDSTR_var64 = {datasize : data_size}
+type token_LDSTR_lit64 = {datasize : data_size; size : int}
+type token_LDSTR = {txt : string; memop : memOp; signed : boolean; lit32 : boolean; var32 : token_LDSTR_var32 option; var64 : token_LDSTR_var64 option; lit64 : token_LDSTR_lit64 option}
+type token_LDSTTUR_off32 = {datasize : data_size}
+type token_LDSTTUR_off64 = {datasize : data_size}
+type token_LDSTTUR = {txt : string; memop : memOp; acctype : accType; signed : boolean; off32 : token_LDSTTUR_off32 option; off64 : token_LDSTTUR_off64 option}
+type token_MADDSUB = {txt : string; sub_op : boolean}
+type token_MUL = {txt : string; sub_op : boolean}
+type token_MOVWIDE = {txt : string; opcode : moveWideOp}
+type token_NEG = {txt : string; setflags : boolean}
+type token_NGC = {txt : string; setflags : boolean}
+type token_REV = {txt : string; op32 : revOp option; op64 : revOp}
+type token_DIV = {txt : string; unsigned : boolean}
+type token_MADDSUBL = {txt : string; sub_op : boolean; unsigned : boolean}
+type token_MULH = {txt : string; unsigned : boolean}
+type token_MULL = {txt : string; unsigned : boolean}
+type token_LDSTP = {txt : string; memop : memOp}
+type token_TBZ = {txt : string; bit_val : bit}
+type token_BFIZ = {txt : string; extend : boolean}
+type token_BFX = {txt : string; extend : boolean}
+type token_MNEGL = {txt : string; unsigned : boolean}
+type token_BFI = {txt : string}
+type token_BFXIL = {txt : string}
+type token_CLREX = {txt : string}
+type token_EXTR = {txt : string}
+type token_HINT = {txt : string}
+type token_ISB = {txt : string}
+type token_LDPSW = {txt : string}
+type token_MOV = {txt : string}
+type token_MVN = {txt : string}
+type token_NOP = {txt : string}
+type token_PRFM = {txt : string}
+type token_PRFUM = {txt : string}
+type token_RET = {txt : string}
+type token_TST = {txt : string}
+type token_MRS = {txt : string}
+type token_MSR = {txt : string}
+
+(*** instructions/operands ***)
+
+type token_SHIFT = {txt : string; shift_type : shiftType}
+type token_EXTEND_inst = {extend : boolean; imms : int}
+type token_EXTEND = {txt : string; _type : extendType; inst : token_EXTEND_inst option}
+
+(*** operands: ***)
+
+type token_COND = int
+type token_BARROP = {domain : mBReqDomain; types : mBReqTypes}
+type token_PRFOP = inst_reg (* this is an int that is encoded in a reg field *)
+type token_SYSREG = {sys_op0 : uinteger; sys_op1 : uinteger; sys_op2 : uinteger; sys_crn : uinteger; sys_crm : uinteger}
+type token_PSTATEFIELD = pSTATEField
diff --git a/aarch64_small/gen/tokens.hgen b/aarch64_small/gen/tokens.hgen
new file mode 100644
index 00000000..bf49e463
--- /dev/null
+++ b/aarch64_small/gen/tokens.hgen
@@ -0,0 +1,78 @@
+/*** instructions ***/
+
+%token <AArch64HGenBase.token_TSTART> TSTART
+%token <AArch64HGenBase.token_TCOMMIT> TCOMMIT
+%token <AArch64HGenBase.token_TABORT> TABORT
+%token <AArch64HGenBase.token_TTEST> TTEST
+
+%token <AArch64HGenBase.token_ADCSBC> ADCSBC
+%token <AArch64HGenBase.token_ADDSUB> ADDSUB
+%token <AArch64HGenBase.token_ADR> ADR
+%token <AArch64HGenBase.token_LOGOP> LOGOP
+%token <AArch64HGenBase.token_SHIFTOP> SHIFTOP
+%token <AArch64HGenBase.token_BCOND> BCOND
+%token <AArch64HGenBase.token_B> B
+%token <AArch64HGenBase.token_BR> BR
+%token <AArch64HGenBase.token_CBZ> CBZ
+%token <AArch64HGenBase.token_BFM> BFM
+%token <AArch64HGenBase.token_CCM> CCM
+%token <AArch64HGenBase.token_CM> CM
+%token <AArch64HGenBase.token_CL> CL
+%token <AArch64HGenBase.token_CRC> CRC
+%token <AArch64HGenBase.token_CRC32X> CRC32X
+%token <AArch64HGenBase.token_CSEL> CSEL
+%token <AArch64HGenBase.token_CSET> CSET
+%token <AArch64HGenBase.token_CSETM> CSETM
+%token <AArch64HGenBase.token_CON> CON
+%token <AArch64HGenBase.token_MEMBARR> MEMBARR
+%token <AArch64HGenBase.token_LDAXR> LDAXR
+%token <AArch64HGenBase.token_STLXR> STLXR
+%token <AArch64HGenBase.token_LDXP> LDXP
+%token <AArch64HGenBase.token_STXP> STXP
+%token <AArch64HGenBase.token_LDSTR> LDSTR
+%token <AArch64HGenBase.token_LDSTTUR> LDSTTUR
+%token <AArch64HGenBase.token_MADDSUB> MADDSUB
+%token <AArch64HGenBase.token_MUL> MUL
+%token <AArch64HGenBase.token_MOVWIDE> MOVWIDE
+%token <AArch64HGenBase.token_NEG> NEG
+%token <AArch64HGenBase.token_NGC> NGC
+%token <AArch64HGenBase.token_REV> REV
+%token <AArch64HGenBase.token_DIV> DIV
+%token <AArch64HGenBase.token_MADDSUBL> MADDSUBL
+%token <AArch64HGenBase.token_MULH> MULH
+%token <AArch64HGenBase.token_MULL> MULL
+%token <AArch64HGenBase.token_LDSTP> LDSTP
+%token <AArch64HGenBase.token_TBZ> TBZ
+%token <AArch64HGenBase.token_BFIZ> BFIZ
+%token <AArch64HGenBase.token_BFX> BFX
+%token <AArch64HGenBase.token_MNEGL> MNEGL
+%token <AArch64HGenBase.token_BFI> BFI
+%token <AArch64HGenBase.token_BFXIL> BFXIL
+%token <AArch64HGenBase.token_CLREX> CLREX
+%token <AArch64HGenBase.token_EXTR> EXTR
+%token <AArch64HGenBase.token_HINT> HINT
+%token <AArch64HGenBase.token_ISB> ISB
+%token <AArch64HGenBase.token_LDPSW> LDPSW
+%token <AArch64HGenBase.token_MOV> MOV
+%token <AArch64HGenBase.token_MVN> MVN
+%token <AArch64HGenBase.token_NOP> NOP
+%token <AArch64HGenBase.token_PRFM> PRFM
+%token <AArch64HGenBase.token_PRFUM> PRFUM
+%token <AArch64HGenBase.token_RET> RET
+%token <AArch64HGenBase.token_TST> TST
+%token <AArch64HGenBase.token_MRS> MRS
+%token <AArch64HGenBase.token_MSR> MSR
+
+/*** instructions/operands ***/
+
+%token <AArch64HGenBase.token_SHIFT> SHIFT
+%token <AArch64HGenBase.token_EXTEND> EXTEND
+
+/*** operands: ***/
+
+%token <AArch64HGenBase.token_COND> COND
+%token <AArch64HGenBase.token_BARROP> BARROP
+%token <AArch64HGenBase.token_PRFOP> PRFOP
+%token <AArch64HGenBase.token_SYSREG> SYSREG
+%token <AArch64HGenBase.token_PSTATEFIELD> PSTATEFIELD
+
diff --git a/aarch64_small/gen/trans_sail.hgen b/aarch64_small/gen/trans_sail.hgen
new file mode 100644
index 00000000..2b176308
--- /dev/null
+++ b/aarch64_small/gen/trans_sail.hgen
@@ -0,0 +1,379 @@
+| `AArch64TMStart t ->
+ ("TMStart", [translate_reg "t" t], [])
+
+| `AArch64TMCommit -> ("TMCommit", [], [])
+
+| `AArch64TMAbort (retry,reason) ->
+ ("TMAbort",
+ [ translate_boolean "retry" retry;
+ translate_bit5 "reason" reason],
+ [])
+
+| `AArch64TMTest -> ("TMTest", [], [])
+
+
+| `AArch64ImplementationDefinedStopFetching ->
+ ("ImplementationDefinedStopFetching",
+ [],
+ [])
+
+| `AArch64ImplementationDefinedThreadStart ->
+ ("ImplementationDefinedThreadStart",
+ [],
+ [])
+
+| `AArch64ImplementationDefinedTestBeginEnd(isEnd) ->
+ ("ImplementationDefinedTestBeginEnd",
+ [translate_boolean "isEnd" isEnd],
+ [])
+
+| `AArch64AddSubCarry(d,n,m,datasize,sub_op,setflags) ->
+ ("AddSubCarry",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_boolean "setflags" setflags],
+ [])
+
+| `AArch64AddSubExtendRegister (d,n,m,datasize,sub_op,setflags,extend_type,shift) ->
+ ("AddSubExtendRegister",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_boolean "setflags" setflags;
+ translate_extendType "extend_type" extend_type;
+ translate_range0_7 "shift" shift],
+ [])
+
+| `AArch64AddSubShiftedRegister (d,n,m,datasize,sub_op,setflags,shift_type,shift_amount) ->
+ ("AddSubShiftedRegister",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_boolean "setflags" setflags;
+ translate_shiftType "shift_type" shift_type;
+ translate_range0_63 "shift_amount" shift_amount],
+ [])
+
+| `AArch64AddSubImmediate (d,n,datasize,sub_op,setflags,imm) ->
+ ("AddSubImmediate",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_boolean "setflags" setflags;
+ translate_reg_size_bits "imm" imm],
+ [])
+
+| `AArch64Address (d,page,imm) ->
+ ("Address",
+ [translate_reg "d" d;
+ translate_boolean "page" page;
+ translate_bit64 "imm" imm],
+ [])
+
+| `AArch64LogicalImmediate (d,n,datasize,setflags,op,imm) ->
+ ("LogicalImmediate",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "setflags" setflags;
+ translate_logicalOp "op" op;
+ translate_reg_size_bits "imm" imm],
+ [])
+
+| `AArch64LogicalShiftedRegister (d,n,m,datasize,setflags,op,shift_type,shift_amount,invert) ->
+ ("LogicalShiftedRegister",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "setflags" setflags;
+ translate_logicalOp "op" op;
+ translate_shiftType "shift_type" shift_type;
+ translate_range0_63 "shift_amount" shift_amount;
+ translate_boolean "invert" invert],
+ [])
+
+| `AArch64Shift (d,n,m,datasize,shift_type) ->
+ ("Shift",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_shiftType "shift_type" shift_type],
+ [])
+
+| `AArch64BranchConditional (offset,condition) ->
+ ("BranchConditional",
+ [translate_bit64 "offset" offset;
+ translate_bit4 "condition" condition],
+ [])
+
+| `AArch64BranchImmediate (branch_type,offset) ->
+ ("BranchImmediate",
+ [translate_branchType "branch_type" branch_type;
+ translate_bit64 "offset" offset],
+ [])
+
+| `AArch64BitfieldMove (d,n,datasize,inzero,extend,_R,_S,wmask,tmask) ->
+ ("BitfieldMove",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "inzero" inzero;
+ translate_boolean "extend" extend;
+ translate_uinteger "_R" _R;
+ translate_uinteger "_S" _S;
+ translate_reg_size_bits "wmask" wmask;
+ translate_reg_size_bits "tmask" tmask],
+ [])
+
+| `AArch64BranchRegister (n,branch_type) ->
+ ("BranchRegister",
+ [translate_reg "n" n;
+ translate_branchType "branch_type" branch_type],
+ [])
+
+| `AArch64CompareAndBranch (t,datasize,iszero,offset) ->
+ ("CompareAndBranch",
+ [translate_reg "t" t;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "iszero" iszero;
+ translate_bit64 "offset" offset],
+ [])
+
+| `AArch64ConditionalCompareImmediate (n,datasize,sub_op,condition,flags,imm) ->
+ ("ConditionalCompareImmediate",
+ [translate_reg "n" n;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_bit4 "condition" condition;
+ translate_bit4 "flags" flags;
+ translate_reg_size_bits "imm" imm],
+ [])
+
+| `AArch64ConditionalCompareRegister (n,m,datasize,sub_op,condition,flags) ->
+ ("ConditionalCompareRegister",
+ [translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_bit4 "condition" condition;
+ translate_bit4 "flags" flags],
+ [])
+
+| `AArch64ClearExclusiveMonitor (imm) ->
+ ("ClearExclusiveMonitor",
+ [translate_uinteger "imm" imm],
+ [])
+
+| `AArch64CountLeading (d,n,datasize,opcode) ->
+ ("CountLeading",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg_size "datasize" datasize;
+ translate_countOp "opcode" opcode],
+ [])
+
+| `AArch64CRC (d,n,m,size,crc32c) ->
+ ("CRC",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_data_size "size" size;
+ translate_boolean "crc32c" crc32c],
+ [])
+
+| `AArch64ConditionalSelect (d,n,m,datasize,condition,else_inv,else_inc) ->
+ ("ConditionalSelect",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_bit4 "condition" condition;
+ translate_boolean "else_inv" else_inv;
+ translate_boolean "else_inc" else_inc],
+ [])
+
+| `AArch64Barrier (op,domain,types) ->
+ ("Barrier",
+ [translate_memBarrierOp "op" op;
+ translate_mBReqDomain "domain" domain;
+ translate_mBReqTypes "types" types],
+ [])
+
+| `AArch64ExtractRegister (d,n,m,datasize,lsb) ->
+ ("ExtractRegister",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_uinteger "lsb" lsb],
+ [])
+
+| `AArch64Hint (op) ->
+ ("Hint",
+ [translate_systemHintOp "op" op],
+ [])
+
+| `AArch64LoadStoreAcqExc (n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) ->
+ ("LoadStoreAcqExc",
+ [translate_reg "n" n;
+ translate_reg "t" t;
+ translate_reg "t2" t2;
+ translate_reg "s" s;
+ translate_accType "acctype" acctype;
+ translate_boolean "excl" excl;
+ translate_boolean "pair" pair;
+ translate_memOp "memop" memop;
+ translate_uinteger "elsize" elsize;
+ translate_reg_size "regsize" regsize;
+ translate_data_size "datasize" datasize],
+ [])
+
+| `AArch64LoadStorePair (wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset) ->
+ ("LoadStorePair",
+ [translate_boolean "wback" wback;
+ translate_boolean "postindex" postindex;
+ translate_reg "n" n;
+ translate_reg "t" t;
+ translate_reg "t2" t2;
+ translate_accType "acctype" acctype;
+ translate_memOp "memop" memop;
+ translate_boolean "signed" signed;
+ translate_data_size "datasize" datasize;
+ translate_bit64 "offset" offset],
+ [])
+
+| `AArch64LoadImmediate (n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize) ->
+ ("LoadImmediate",
+ [translate_reg "n" n;
+ translate_reg "t" t;
+ translate_accType "acctype" acctype;
+ translate_memOp "memop" memop;
+ translate_boolean "signed" signed;
+ translate_boolean "wback" wback;
+ translate_boolean "postindex" postindex;
+ translate_bit64 "offset" offset;
+ translate_reg_size "regsize" regsize;
+ translate_data_size "datasize" datasize],
+ [])
+
+| `AArch64LoadLiteral (t,memop,signed,size,offset,datasize) ->
+ ("LoadLiteral",
+ [translate_reg "t" t;
+ translate_memOp "memop" memop;
+ translate_boolean "signed" signed;
+ translate_uinteger "size" size;
+ translate_bit64 "offset" offset;
+ translate_data_size "datasize" datasize;],
+ [])
+
+| `AArch64LoadRegister (n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize) ->
+ ("LoadRegister",
+ [translate_reg "n" n;
+ translate_reg "t" t;
+ translate_reg "m" m;
+ translate_accType "acctype" acctype;
+ translate_memOp "memop" memop;
+ translate_boolean "signed" signed;
+ translate_boolean "wback" wback;
+ translate_boolean "postindex" postindex;
+ translate_extendType "extend_type" extend_type;
+ translate_uinteger "shift" shift;
+ translate_reg_size "regsize" regsize;
+ translate_data_size "datasize" datasize],
+ [])
+
+| `AArch64MultiplyAddSub (d,n,m,a,destsize,datasize,sub_op) ->
+ ("MultiplyAddSub",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg "a" a;
+ translate_reg_size "destsize" destsize;
+ translate_data_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op],
+ [])
+
+| `AArch64MoveWide (d,datasize,imm,pos,opcode) ->
+ ("MoveWide",
+ [translate_reg "d" d;
+ translate_reg_size "datasize" datasize;
+ translate_bit16 "imm" imm;
+ translate_uinteger "pos" pos;
+ translate_moveWideOp "opcode" opcode],
+ [])
+
+| `AArch64Reverse (d,n,datasize,op) ->
+ ("Reverse",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg_size "datasize" datasize;
+ translate_revOp "op" op],
+ [])
+
+| `AArch64Division (d,n,m,datasize,unsigned) ->
+ ("Division",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg_size "datasize" datasize;
+ translate_boolean "unsigned" unsigned],
+ [])
+
+| `AArch64MultiplyAddSubLong (d,n,m,a,destsize,datasize,sub_op,unsigned) ->
+ ("MultiplyAddSubLong",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg "a" a;
+ translate_reg_size "destsize" destsize;
+ translate_data_size "datasize" datasize;
+ translate_boolean "sub_op" sub_op;
+ translate_boolean "unsigned" unsigned],
+ [])
+
+| `AArch64MultiplyHigh (d,n,m,a,destsize,datasize,unsigned) ->
+ ("MultiplyHigh",
+ [translate_reg "d" d;
+ translate_reg "n" n;
+ translate_reg "m" m;
+ translate_reg "a" a;
+ translate_reg_size "destsize" destsize;
+ translate_data_size "datasize" datasize;
+ translate_boolean "unsigned" unsigned],
+ [])
+
+| `AArch64TestBitAndBranch (t,datasize,bit_pos,bit_val,offset) ->
+ ("TestBitAndBranch",
+ [translate_reg "t" t;
+ translate_reg_size "datasize" datasize;
+ translate_uinteger "bit_pos" bit_pos;
+ translate_bit "bit_val" bit_val;
+ translate_bit64 "offset" offset],
+ [])
+
+| `AArch64MoveSystemRegister (t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read) ->
+ ("MoveSystemRegister",
+ [translate_reg "t" t;
+ translate_uinteger "sys_op0" sys_op0;
+ translate_uinteger "sys_op1" sys_op1;
+ translate_uinteger "sys_op2" sys_op2;
+ translate_uinteger "sys_crn" sys_crn;
+ translate_uinteger "sys_crm" sys_crm;
+ translate_boolean "read" read],
+ [])
+
+| `AArch64MoveSystemImmediate (operand,field) ->
+ ("MoveSystemImmediate",
+ [translate_bit4 "operand" operand;
+ translate_pSTATEField "field" field],
+ [])
diff --git a/aarch64_small/gen/types.hgen b/aarch64_small/gen/types.hgen
new file mode 100644
index 00000000..d581a233
--- /dev/null
+++ b/aarch64_small/gen/types.hgen
@@ -0,0 +1,90 @@
+type reg_size = Set64 | Set32
+
+type reg_size_bits = R32Bits of int | R64Bits of Nat_big_num.num
+let reg_size_bits_R32_of_int value = R32Bits value
+let reg_size_bits_R64_of_int value = R64Bits (Nat_big_num.of_int value)
+let reg_size_bits_R32_of_big_int value = R32Bits (Nat_big_num.to_int value)
+let reg_size_bits_R64_of_big_int value = R64Bits value
+let eq_reg_size_bits = function
+ | (R32Bits lhs, R32Bits rhs) -> lhs = rhs
+ | (R64Bits lhs, R64Bits rhs) -> Nat_big_num.equal lhs rhs
+ | (R32Bits _, R64Bits _) -> false
+ | (R64Bits _, R32Bits _) -> false
+let reg_size_bits_iskbituimm k value =
+ match value with
+ | R32Bits value -> iskbituimm k value
+ | R64Bits value -> big_iskbituimm k value
+let reg_size_bits_shift_right value n =
+ match value with
+ | R32Bits value -> R32Bits (value lsr n)
+ | R64Bits value -> R64Bits (Nat_big_num.shift_right value n)
+let reg_size_bits_to_int value =
+ match value with
+ | R32Bits value -> value
+ | R64Bits value -> Nat_big_num.to_int value
+
+type data_size = DataSize64 | DataSize32 | DataSize16 | DataSize8
+
+type reg_index = int
+
+type boolean = bool
+
+type range0_7 = int
+
+type range0_63 = int
+
+type bit64 = Nat_big_num.num
+let bit64_of_int = Nat_big_num.of_int
+let bit64_to_int = Nat_big_num.to_int
+let eq_bit64 = Nat_big_num.equal
+
+type bit4 = int
+
+type bit5 = int
+
+type bit16 = int
+
+type bit = bool
+
+type range8_64 = int
+
+type uinteger = int
+
+type extendType = ExtendType_SXTB | ExtendType_SXTH | ExtendType_SXTW | ExtendType_SXTX |
+ ExtendType_UXTB | ExtendType_UXTH | ExtendType_UXTW | ExtendType_UXTX
+
+
+type shiftType = ShiftType_LSL | ShiftType_LSR | ShiftType_ASR | ShiftType_ROR
+
+type logicalOp = LogicalOp_AND | LogicalOp_EOR | LogicalOp_ORR
+
+type branchType = BranchType_CALL | BranchType_ERET | BranchType_DBGEXIT |
+ BranchType_RET | BranchType_JMP | BranchType_EXCEPTION |
+ BranchType_UNKNOWN
+
+type countOp = CountOp_CLZ | CountOp_CLS | CountOp_CNT
+
+type memBarrierOp = MemBarrierOp_DSB | MemBarrierOp_DMB | MemBarrierOp_ISB
+
+type mBReqDomain = MBReqDomain_Nonshareable | MBReqDomain_InnerShareable |
+ MBReqDomain_OuterShareable | MBReqDomain_FullSystem
+
+type mBReqTypes = MBReqTypes_Reads | MBReqTypes_Writes | MBReqTypes_All
+
+type systemHintOp = SystemHintOp_NOP | SystemHintOp_YIELD |
+ SystemHintOp_WFE | SystemHintOp_WFI |
+ SystemHintOp_SEV | SystemHintOp_SEVL
+
+type accType = AccType_NORMAL | AccType_VEC | AccType_STREAM |
+ AccType_VECSTREAM | AccType_ATOMIC | AccType_ORDERED |
+ AccType_UNPRIV | AccType_IFETCH | AccType_PTW |
+ AccType_DC | AccType_IC | AccType_AT
+
+type memOp = MemOp_LOAD | MemOp_STORE | MemOp_PREFETCH
+
+type moveWideOp = MoveWideOp_N | MoveWideOp_Z | MoveWideOp_K
+
+type revOp = RevOp_RBIT | RevOp_REV16 | RevOp_REV32 | RevOp_REV64
+
+type pSTATEField = PSTATEField_DAIFSet | PSTATEField_DAIFClr |
+ PSTATEField_SP
diff --git a/aarch64_small/gen/types_sail_trans_out.hgen b/aarch64_small/gen/types_sail_trans_out.hgen
new file mode 100644
index 00000000..082a5464
--- /dev/null
+++ b/aarch64_small/gen/types_sail_trans_out.hgen
@@ -0,0 +1,189 @@
+let translate_out_big_int_bits = function
+ | (name, Range0 _, bits) -> IInt.integer_of_bit_list bits
+ | _ -> assert false
+
+let translate_out_big_bit = function
+ | (name, Bvector _, bits) -> IInt.integer_of_bit_list bits
+ | _ -> assert false
+
+let translate_out_signed_big_bit = function
+ | (name, Bvector _, bits) -> IInt.signed_integer_of_bit_list bits
+ | _ -> assert false
+
+let translate_out_int inst = (Nat_big_num.to_int (translate_out_big_int_bits inst))
+
+let translate_out_bits = function
+ | (name, Bvector _, bits) -> Nat_big_num.to_int (IInt.integer_of_bit_list bits)
+ | _ -> assert false
+
+let translate_out_bool = function
+ | (name, Bit, [Bitc_one]) -> true
+ | (name, Bit, [Bitc_zero]) -> false
+ | _ -> assert false
+
+let translate_out_enum (name,_,bits) =
+ Nat_big_num.to_int (IInt.integer_of_bit_list bits)
+
+let translate_out_reg_size inst =
+ match translate_out_int inst with
+ | 32 -> Set32
+ | 64 -> Set64
+ | _ -> assert false
+
+let translate_out_regzr regsize reg =
+ begin match (regsize, translate_out_int reg) with
+ | (Set32, 31) -> W ZR
+ | (Set32, reg) -> W (Ireg (ireg_of_int reg))
+ | (Set64, 31) -> X ZR
+ | (Set64, reg) -> X (Ireg (ireg_of_int reg))
+ end
+
+let translate_out_regsp regsize reg =
+ begin match (regsize, translate_out_int reg) with
+ | (Set32, 31) -> W SP
+ | (Set32, reg) -> W (Ireg (ireg_of_int reg))
+ | (Set64, 31) -> X SP
+ | (Set64, reg) -> X (Ireg (ireg_of_int reg))
+ end
+
+let translate_out_regzrbyext regsize extend_type reg =
+ begin match extend_type with
+ | ExtendType_UXTX | ExtendType_SXTX -> translate_out_regzr regsize reg
+ | _ -> translate_out_regzr Set32 reg
+ end
+
+let translate_out_reg_size_bits ((name,_,bits) as inst) =
+ match List.length bits with
+ | 32 -> R32Bits (translate_out_bits inst)
+ | 64 -> R64Bits (translate_out_big_bit inst)
+ | _ -> assert false
+
+let translate_out_data_size inst =
+ match (translate_out_int inst) with
+ | 8 -> DataSize8
+ | 16 -> DataSize16
+ | 32 -> DataSize32
+ | 64 -> DataSize64
+ | _ -> assert false
+
+let translate_out_extendType inst =
+ match translate_out_enum inst with
+ | 0 -> ExtendType_SXTB
+ | 1 -> ExtendType_SXTH
+ | 2 -> ExtendType_SXTW
+ | 3 -> ExtendType_SXTX
+ | 4 -> ExtendType_UXTB
+ | 5 -> ExtendType_UXTH
+ | 6 -> ExtendType_UXTW
+ | 7 -> ExtendType_UXTX
+ | _ -> assert false
+
+let translate_out_shiftType inst =
+ match translate_out_enum inst with
+ | 0 -> ShiftType_LSL
+ | 1 -> ShiftType_LSR
+ | 2 -> ShiftType_ASR
+ | 3 -> ShiftType_ROR
+ | _ -> assert false
+
+let translate_out_logicalOp inst =
+ match translate_out_enum inst with
+ | 0 -> LogicalOp_AND
+ | 1 -> LogicalOp_EOR
+ | 2 -> LogicalOp_ORR
+ | _ -> assert false
+
+let translate_out_branchType inst =
+ match translate_out_enum inst with
+ | 0 -> BranchType_CALL
+ | 1 -> BranchType_ERET
+ | 2 -> BranchType_DBGEXIT
+ | 3 -> BranchType_RET
+ | 4 -> BranchType_JMP
+ | 5 -> BranchType_EXCEPTION
+ | 6 -> BranchType_UNKNOWN
+ | _ -> assert false
+
+let translate_out_countOp inst =
+ match translate_out_enum inst with
+ | 0 -> CountOp_CLZ
+ | 1 -> CountOp_CLS
+ | 2 -> CountOp_CNT
+ | _ -> assert false
+
+let translate_out_memBarrierOp inst =
+ match translate_out_enum inst with
+ | 0 -> MemBarrierOp_DSB
+ | 1 -> MemBarrierOp_DMB
+ | 2 -> MemBarrierOp_ISB
+ | _ -> assert false
+
+let translate_out_mBReqDomain inst =
+ match translate_out_enum inst with
+ | 0 -> MBReqDomain_Nonshareable
+ | 1 -> MBReqDomain_InnerShareable
+ | 2 -> MBReqDomain_OuterShareable
+ | 3 -> MBReqDomain_FullSystem
+ | _ -> assert false
+
+let translate_out_mBReqTypes inst =
+ match translate_out_enum inst with
+ | 0 -> MBReqTypes_Reads
+ | 1 -> MBReqTypes_Writes
+ | 2 -> MBReqTypes_All
+ | _ -> assert false
+
+let translate_out_systemHintOp inst =
+ match translate_out_enum inst with
+ | 0 -> SystemHintOp_NOP
+ | 1 -> SystemHintOp_YIELD
+ | 2 -> SystemHintOp_WFE
+ | 3 -> SystemHintOp_WFI
+ | 4 -> SystemHintOp_SEV
+ | 5 -> SystemHintOp_SEVL
+ | _ -> assert false
+
+let translate_out_accType inst =
+ match translate_out_enum inst with
+ | 0 -> AccType_NORMAL
+ | 1 -> AccType_VEC
+ | 2 -> AccType_STREAM
+ | 3 -> AccType_VECSTREAM
+ | 4 -> AccType_ATOMIC
+ | 5 -> AccType_ORDERED
+ | 6 -> AccType_UNPRIV
+ | 7 -> AccType_IFETCH
+ | 8 -> AccType_PTW
+ | 9 -> AccType_DC
+ | 10 -> AccType_IC
+ | 11 -> AccType_AT
+ | _ -> assert false
+
+let translate_out_memOp inst =
+ match translate_out_enum inst with
+ | 0 -> MemOp_LOAD
+ | 1 -> MemOp_STORE
+ | 2 -> MemOp_PREFETCH
+ | _ -> assert false
+
+let translate_out_moveWideOp inst =
+ match translate_out_enum inst with
+ | 0 -> MoveWideOp_N
+ | 1 -> MoveWideOp_Z
+ | 2 -> MoveWideOp_K
+ | _ -> assert false
+
+let translate_out_revOp inst =
+ match translate_out_enum inst with
+ | 0 -> RevOp_RBIT
+ | 1 -> RevOp_REV16
+ | 2 -> RevOp_REV32
+ | 3 -> RevOp_REV64
+ | _ -> assert false
+
+let translate_out_pSTATEField inst =
+ match translate_out_enum inst with
+ | 0 -> PSTATEField_DAIFSet
+ | 1 -> PSTATEField_DAIFClr
+ | 2 -> PSTATEField_SP
+ | _ -> assert false
diff --git a/aarch64_small/gen/types_trans_sail.hgen b/aarch64_small/gen/types_trans_sail.hgen
new file mode 100644
index 00000000..7f2d5fe7
--- /dev/null
+++ b/aarch64_small/gen/types_trans_sail.hgen
@@ -0,0 +1,119 @@
+let translate_big_int bits (name : string) value =
+ (name, Range0 (Some bits), IInt.bit_list_of_integer bits value)
+
+let translate_big_bit bits (name:string) value =
+ (name, Bvector (Some bits), IInt.bit_list_of_integer bits value)
+
+let translate_int bits name value =
+ translate_big_int bits name (Nat_big_num.of_int value)
+
+let translate_bits bits (name:string) value =
+ (name, Bvector (Some bits), IInt.bit_list_of_integer bits (Nat_big_num.of_int value))
+
+let translate_bool name value =
+ (name, Bit, [if value then Bitc_one else Bitc_zero])
+
+let translate_enum enum_values (name: string) value =
+ let rec bit_count n =
+ if n = 0 then 0
+ else 1 + (bit_count (n lsr 1)) in
+ let rec find_index element = function
+ | h::tail -> if h = element then 0 else 1 + (find_index element tail)
+ | _ -> failwith "translate_enum could not find value"
+ in
+ let size = bit_count (List.length enum_values) in
+ let index = find_index value enum_values in
+ (name, Range0 (Some size), IInt.bit_list_of_integer size (Nat_big_num.of_int index))
+
+(* the following are tightly coupled with types.hgen. As it is not relevant
+ to herdtools I put it here and not in types.hgen *)
+
+let translate_reg_size name value =
+ match value with
+ | Set32 -> (name, Range0 (Some 7), IInt.bit_list_of_integer 7 (Nat_big_num.of_int 32))
+ | Set64 -> (name, Range0 (Some 7), IInt.bit_list_of_integer 7 (Nat_big_num.of_int 64))
+
+let translate_reg name value =
+ (name, Range0 (Some 5), bit_list_of_integer 5 (Nat_big_num.of_int (inst_reg_to_int value)))
+
+let translate_reg_size_bits name value =
+ match value with
+ | R32Bits value -> translate_bits 32 name value
+ | R64Bits value -> translate_big_bit 64 name value
+
+let translate_data_size name value =
+ match value with
+ | DataSize8 -> (name, Range0 (Some 7), IInt.bit_list_of_integer 7 (Nat_big_num.of_int 8))
+ | DataSize16 -> (name, Range0 (Some 7), IInt.bit_list_of_integer 7 (Nat_big_num.of_int 16))
+ | DataSize32 -> (name, Range0 (Some 7), IInt.bit_list_of_integer 7 (Nat_big_num.of_int 32))
+ | DataSize64 -> (name, Range0 (Some 7), IInt.bit_list_of_integer 7 (Nat_big_num.of_int 64))
+
+let translate_reg_index = translate_int 5
+
+let translate_boolean = translate_bool
+
+let translate_range0_7 = translate_int 3
+
+let translate_range0_63 = translate_int 6
+
+let translate_bit64 = translate_big_bit 64
+
+let translate_bit4 = translate_bits 4
+let translate_bit5 = translate_bits 5
+let translate_bit16 = translate_bits 16
+
+let translate_bit = translate_bool
+
+let translate_range8_64 = translate_int 7
+
+let translate_uinteger = translate_int 63
+
+let translate_extendType =
+ translate_enum [ExtendType_SXTB; ExtendType_SXTH; ExtendType_SXTW; ExtendType_SXTX;
+ ExtendType_UXTB; ExtendType_UXTH; ExtendType_UXTW; ExtendType_UXTX]
+
+let translate_shiftType =
+ translate_enum [ShiftType_LSL; ShiftType_LSR; ShiftType_ASR; ShiftType_ROR]
+
+let translate_logicalOp =
+ translate_enum [LogicalOp_AND; LogicalOp_EOR; LogicalOp_ORR]
+
+let translate_branchType =
+ translate_enum [BranchType_CALL; BranchType_ERET; BranchType_DBGEXIT;
+ BranchType_RET; BranchType_JMP; BranchType_EXCEPTION;
+ BranchType_UNKNOWN]
+
+let translate_countOp =
+ translate_enum [CountOp_CLZ;CountOp_CLS;CountOp_CNT]
+
+let translate_memBarrierOp=
+ translate_enum [MemBarrierOp_DSB; MemBarrierOp_DMB; MemBarrierOp_ISB]
+
+let translate_mBReqDomain =
+ translate_enum [MBReqDomain_Nonshareable; MBReqDomain_InnerShareable;
+ MBReqDomain_OuterShareable; MBReqDomain_FullSystem]
+
+let translate_mBReqTypes =
+ translate_enum [MBReqTypes_Reads; MBReqTypes_Writes; MBReqTypes_All]
+
+let translate_systemHintOp =
+ translate_enum [SystemHintOp_NOP; SystemHintOp_YIELD; SystemHintOp_WFE;
+ SystemHintOp_WFI; SystemHintOp_SEV; SystemHintOp_SEVL]
+
+let translate_accType =
+ translate_enum [AccType_NORMAL; AccType_VEC; AccType_STREAM;
+ AccType_VECSTREAM; AccType_ATOMIC; AccType_ORDERED;
+ AccType_UNPRIV; AccType_IFETCH; AccType_PTW;
+ AccType_DC; AccType_IC; AccType_AT]
+
+let translate_memOp =
+ translate_enum [MemOp_LOAD; MemOp_STORE; MemOp_PREFETCH]
+
+let translate_moveWideOp =
+ translate_enum [MoveWideOp_N; MoveWideOp_Z; MoveWideOp_K]
+
+let translate_revOp =
+ translate_enum [RevOp_RBIT; RevOp_REV16; RevOp_REV32; RevOp_REV64]
+
+let translate_pSTATEField =
+ translate_enum [PSTATEField_DAIFSet; PSTATEField_DAIFClr; PSTATEField_SP]