summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaked Flur2017-12-04 14:54:54 +0000
committerShaked Flur2017-12-04 14:54:54 +0000
commit5fa993caef3c48da36f641bf3608a9515ecc40cf (patch)
tree1d4e4b9a2bb390744708f4fd4486616fd7d1b4b2
parent748318f8af7b82a01bb151f1bfcb466d0fc8291f (diff)
match what rmem expects from sail/arm
-rw-r--r--arm/Makefile59
-rw-r--r--arm/aarch64_regfp.sail598
-rw-r--r--arm/armV8.h.sail24
-rw-r--r--arm/armV8.sail157
-rw-r--r--arm/armV8_A64_lib.sail18
-rw-r--r--arm/armV8_A64_sys_regs.sail200
-rw-r--r--arm/armV8_common_lib.sail10
-rw-r--r--arm/armV8_extras.lem77
-rw-r--r--arm/armV8_extras_embed.lem59
-rw-r--r--arm/armV8_extras_embed_sequential.lem59
-rw-r--r--arm/armV8_lib.h.sail5
-rw-r--r--arm/gen/ast.hgen44
-rw-r--r--arm/gen/fold.hgen44
-rw-r--r--arm/gen/herdtools_ast_to_shallow_ast.hgen335
-rw-r--r--arm/gen/herdtools_types_to_shallow_types.hgen153
-rw-r--r--arm/gen/lexer.hgen309
-rw-r--r--arm/gen/map.hgen44
-rw-r--r--arm/gen/parser.hgen1396
-rw-r--r--arm/gen/pretty.hgen393
-rw-r--r--arm/gen/regs_out_in.hgen155
-rw-r--r--arm/gen/sail_trans_out.hgen326
-rw-r--r--arm/gen/shallow_ast_to_herdtools_ast.hgen326
-rw-r--r--arm/gen/shallow_types_to_herdtools_types.hgen154
-rw-r--r--arm/gen/token_types.hgen85
-rw-r--r--arm/gen/tokens.hgen78
-rw-r--r--arm/gen/trans_sail.hgen379
-rw-r--r--arm/gen/types.hgen90
-rw-r--r--arm/gen/types_sail_trans_out.hgen189
-rw-r--r--arm/gen/types_trans_sail.hgen119
29 files changed, 5623 insertions, 262 deletions
diff --git a/arm/Makefile b/arm/Makefile
index 18eba393..d7124df6 100644
--- a/arm/Makefile
+++ b/arm/Makefile
@@ -1,16 +1,5 @@
-BUILDDIR=./build
-
-SAIL=../sail
-ifeq ("$(wildcard $(SAIL))","")
- $(warning can not find Sail)
-endif
-
-LEM=../../lem/lem
-ifeq ("$(wildcard $(LEM))","")
- $(warning can not find Lem)
-endif
-
-LEMINTERPDIR=../src/lem_interp/
+SAIL:=../src/sail.native
+LEM:=../../lem/lem
# the order of the files is important
SOURCES=armV8.h.sail\
@@ -23,39 +12,28 @@ SOURCES=armV8.h.sail\
armV8_A64_lib.sail\
armV8.sail
-all: $(BUILDDIR)/armv8.ml
-
-clean:
- rm -rf $(BUILDDIR)
-
-ocaml: $(BUILDDIR)/armv8_embed.ml
+all: armV8.lem armV8.ml armV8_embed.lem
-.PHONY: all clean ocaml
+armV8.lem: $(SOURCES)
+ $(SAIL) -lem_ast -o armV8 $(SOURCES)
-$(BUILDDIR):
- mkdir -p $@
+armV8.ml: armV8.lem ../src/lem_interp/interp_ast.lem
+ $(LEM) -ocaml -lib ../src/lem_interp/ $<
-$(BUILDDIR)/armv8.lem: $(SOURCES) | $(BUILDDIR)
- $(SAIL) -lem_ast $(SOURCES) -o $(basename $@)
-# sail generates the .lem file in pwd
- mv $(notdir $@) $@
-$(BUILDDIR)/armv8.ml: $(BUILDDIR)/armv8.lem
- $(LEM) -ocaml -lib $(LEMINTERPDIR) $<
-
-$(BUILDDIR)/armv8_embed.ml: $(SOURCES) | $(BUILDDIR)
- $(SAIL) -ocaml $(SOURCES) -o $(basename $@)
-# sail generates the .lem file in pwd
- mv $(notdir $@) $@
+armV8_embed.lem: $(SOURCES) ../etc/regfp.sail aarch64_regfp.sail
+# also generates armV8_embed_sequential.lem, armV8_embed_types.lem, armV8_toFromInterp.lem
+ $(SAIL) -lem -lem_lib ArmV8_extras_embed -o armV8 $^
+clean:
+ rm -f armV8.lem armV8.ml
+ rm -f armV8_embed*.lem armV8_toFromInterp.lem
######################################################################
ETCDIR=../etc
apply_header:
- -chmod u+w *.sail
headache -c $(ETCDIR)/headache_config -h $(ETCDIR)/arm_header *.sail
- chmod a-w *.sail
.PHONY: apply_header
@@ -63,10 +41,13 @@ apply_header:
IDLARM=../../../rsem/idlarm
pull_from_idlarm:
- svn up $(IDLARM)
- $(MAKE) -C $(IDLARM)
- -chmod u+w *.sail
+ $(MAKE) -C $(IDLARM) clean
+ $(MAKE) -C $(IDLARM) san_sail
rm -f *.sail
cp -a $(IDLARM)/build/*.sail ./
- chmod a-w *.sail
+ cp -a $(IDLARM)/armV8_extras_embed.lem ./
+ cp -a $(IDLARM)/armV8_extras_embed_sequential.lem ./
+ cp -a $(IDLARM)/armV8_extras.lem ./
+ mkdir -p gen
+ cp -a $(IDLARM)/*.hgen gen/
$(MAKE) apply_header
diff --git a/arm/aarch64_regfp.sail b/arm/aarch64_regfp.sail
new file mode 100644
index 00000000..148f9646
--- /dev/null
+++ b/arm/aarch64_regfp.sail
@@ -0,0 +1,598 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Shaked Flur *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+function instruction_kind rmem_kind ((AccType) acctype, (bool) exclusive) =
+ if exclusive then
+ switch acctype {
+ case AccType_ATOMIC -> IK_mem_read(Read_exclusive)
+ case AccType_ORDERED -> IK_mem_read(Read_exclusive_acquire)
+ case _ -> { not_implemented("unimplemented memory access");
+ IK_mem_read(Read_exclusive); }
+ }
+ else
+ switch acctype {
+ case AccType_NORMAL -> IK_mem_read(Read_plain)
+ case AccType_ATOMIC -> IK_mem_read(Read_plain)
+ case AccType_STREAM -> IK_mem_read(Read_stream)
+ case AccType_UNPRIV -> IK_mem_read(Read_plain)
+ case AccType_ORDERED -> IK_mem_read(Read_acquire)
+ }
+
+
+function instruction_kind wmem_kind ((AccType) acctype, (bool) exclusive) =
+ if exclusive then {
+ switch acctype {
+ case AccType_ATOMIC -> IK_mem_write(Write_exclusive)
+ case AccType_ORDERED -> IK_mem_write(Write_exclusive_release)
+ case _ -> { not_implemented("unimplemented memory access");
+ IK_mem_write(Write_exclusive); }
+ }
+ } else {
+ switch acctype {
+ case AccType_NORMAL -> IK_mem_write(Write_plain)
+ case AccType_STREAM -> IK_mem_write(Write_plain)
+ case AccType_UNPRIV -> IK_mem_write(Write_plain)
+ case AccType_ORDERED -> IK_mem_write(Write_release)
+ case _ -> { not_implemented("unimplemented memory access");
+ IK_mem_write(Write_plain) }
+ };
+ }
+
+
+let (vector<30,31,dec,string>) _Rs =
+ ["R30","R29","R28","R27","R26","R25","R24","R23","R22","R21",
+ "R20","R19","R18","R17","R16","R15","R14","R13","R12","R11",
+ "R10","R9" ,"R8" ,"R7" ,"R6" ,"R5" ,"R4" ,"R3" ,"R2" ,"R1" ,
+ "R0"]
+
+let TxNestingLevelfp = RFull("TxNestingLevel")
+let TXIDR_EL0_DEPTHfp = RField("TXIDR_EL0","DEPTH")
+
+let PSTATE_Nfp = RField("NZCV","N")
+let PSTATE_Zfp = RField("NZCV","Z")
+let PSTATE_Cfp = RField("NZCV","C")
+let PSTATE_Vfp = RField("NZCV","V")
+let PSTATE_Dfp = RField("DAIF","D")
+let PSTATE_Afp = RField("DAIF","A")
+let PSTATE_Ifp = RField("DAIF","I")
+let PSTATE_Ffp = RField("DAIF","F")
+let PSTATE_ELfp = RFull("CurrentEL")
+let PSTATE_SPfp = RField("SPSel","SP")
+let _PCfp = RFull("_PC")
+
+let NZCVfp = [|| PSTATE_Nfp, PSTATE_Zfp, PSTATE_Cfp, PSTATE_Vfp ||]
+
+function regfps xFP((reg_index) n) =
+ if n != 31 then [||RFull(_Rs[n])||] else [|| ||]
+
+
+(* check if this is still what we want *)
+function forall Nat 'N, 'N IN {32,64}. (regfps,regfps) BranchToFP (iR,oR) =
+ (if UsingAArch32() then iR else PSTATE_ELfp :: iR, _PCfp :: oR)
+
+function regfps ConditionHoldsIFP((bit[4]) _cond) =
+ switch _cond[3..1] {
+ case 0b000 -> [|| PSTATE_Zfp ||]
+ case 0b001 -> [|| PSTATE_Cfp ||]
+ case 0b010 -> [|| PSTATE_Nfp ||]
+ case 0b011 -> [|| PSTATE_Vfp ||]
+ case 0b100 -> [|| PSTATE_Cfp, PSTATE_Zfp ||]
+ case 0b101 -> [|| PSTATE_Nfp, PSTATE_Vfp ||]
+ case 0b110 -> [|| PSTATE_Nfp, PSTATE_Vfp, PSTATE_Zfp ||]
+ case 0b111 -> [|| ||]
+ }
+
+(* for iR if rSPFP, for oR if wSPFP *)
+let rSPIFP =
+ (* TODO: actually this depends on runtime data: PSTATE_SP and PSTATE_EL *)
+ [|| PSTATE_SPfp, RFull("SP_EL0") ||]
+
+let wSPFP =
+ (* TODO: actually this depends on runtime data: PSTATE_SP and PSTATE_EL *)
+ ([|| PSTATE_SPfp ||],
+ [|| RFull("SP_EL0") ||])
+
+
+let CheckSPAlignmentIFP = PSTATE_ELfp :: rSPIFP
+
+let BigEndianIFP =
+ if UsingAArch32() then [|| RFull("PSTATE_E") ||] else [|| PSTATE_ELfp ||]
+
+let wMem'IFP = BigEndianIFP
+let wMemIFP = wMem'IFP
+
+function (regfps,regfps,regfps,niafps,diafp,instruction_kind) effect pure initial_analysis (instr) = {
+ iR := [|| ||];
+ oR := [|| ||];
+ aR := [|| ||];
+ Nias := [|| NIAFP_successor ||];
+ Dia := DIAFP_none;
+ ik := IK_simple;
+
+ switch instr {
+ case (TMStart(t)) -> {
+ iR := TxNestingLevelfp :: TXIDR_EL0_DEPTHfp :: iR;
+ (* TODO: whether the following applies depends on runtime data:
+ ~(TxNestingLevel >= TXIDR_EL0.DEPTH) *)
+ oR := TxNestingLevelfp :: append(oR,xFP(t));
+ ik := IK_trans(Transaction_start);
+ }
+ case (TMCommit) -> {
+ iR := TxNestingLevelfp :: iR;
+ oR := TxNestingLevelfp :: oR;
+ ik := IK_trans(Transaction_commit);
+ }
+ case (TMAbort(retry,reason)) -> {
+ iR := TxNestingLevelfp :: iR;
+ ik := IK_trans(Transaction_abort);
+ }
+ case (TMTest) -> {
+ iR := TxNestingLevelfp :: iR;
+ oR := RFull("NZCV") :: oR;
+ }
+ case (CompareAndBranch(t,datasize,iszero,offset)) -> {
+ iR := append(iR,xFP(t));
+ (* TODO: whether the following applies depends on runtime data:
+ IsZero(operand1) *)
+ let (i,o) = BranchToFP(iR,oR) in {iR := i; oR := o};
+ (bit[64]) nia' := rPC() + offset;
+ Nias := [|| NIAFP_successor, NIAFP_concrete_address(nia') ||];
+ ik := IK_cond_branch;
+ }
+ case (BranchConditional(offset,condition)) -> {
+ iR := append(iR,ConditionHoldsIFP(condition));
+ (* TODO: whether the following applies depends on runtime data:
+ ConditionHolds(condition) *)
+ let (i,o) = BranchToFP(iR,oR) in {iR := i; oR := o};
+ Nias := [|| NIAFP_successor, NIAFP_concrete_address(rPC() + offset) ||];
+ ik := IK_cond_branch;
+ }
+ case (GenerateExceptionEL1(imm)) -> not_implemented("GenerateExceptionEL1")
+ case (GenerateExceptionEL2(imm)) -> not_implemented("GenerateExceptionEL2")
+ case (GenerateExceptionEL3(imm)) -> not_implemented("GenerateExceptionEL3")
+ case (DebugBreakpoint(comment)) -> not_implemented("DebugBreakpoint")
+ case (ExternalDebugBreakpoint) -> not_implemented("ExternalDebugBreakpoint")
+ case (DebugSwitchToExceptionLevel(target_level)) -> not_implemented("DebugSwitchToExceptionLevel")
+ case (MoveSystemImmediate(operand,field)) ->
+ switch field {
+ case PSTATEField_SP -> oR := PSTATE_SPfp :: oR
+ case PSTATEField_DAIFSet -> {
+ iR := append(iR, [|| PSTATE_Dfp, PSTATE_Afp, PSTATE_Ifp, PSTATE_Ffp ||]);
+ oR := append(oR, [|| PSTATE_Dfp, PSTATE_Afp, PSTATE_Ifp, PSTATE_Ffp ||]);
+ }
+ case PSTATEField_DAIFClr -> {
+ iR := append(iR, [|| PSTATE_Dfp, PSTATE_Afp, PSTATE_Ifp, PSTATE_Ffp ||]);
+ oR := append(oR, [|| PSTATE_Dfp, PSTATE_Afp, PSTATE_Ifp, PSTATE_Ffp ||]);
+ }
+ }
+ case (Hint(op)) ->
+ switch op {
+ case SystemHintOp_YIELD -> ()
+ case SystemHintOp_WFE -> {
+ if EventRegistered() then () (* ClearEventRegister *)
+ else {
+ (* the execute code for this case always fails because of
+ WaitForEvent, declared as extern but not defined *)
+ not_implemented("Hint(SystemHintOp_WFE);")
+ }
+ }
+ case SystemHintOp_WFI -> {
+ (* the execute code for this case always fails because of
+ InterruptPending, declared as extern but not defined *)
+ not_implemented("Hint(SystemHintOp_WFI);")
+ }
+ case SystemHintOp_SEV -> () (*SendEvent*)
+ case SystemHintOp_SEVL ->
+ (* the execute code for this case always fails because of
+ EventRegisterSet, declared as extern but not defined *)
+ not_implemented("Hint(SystemHintOp_SEVL);")
+ case _ -> () (* do nothing *)
+ }
+ case (ClearExclusiveMonitor(imm)) -> () (*ClearExclusiveLocal*)
+ case (Barrier(op,domain,types)) -> {
+ ik := switch op {
+ case MemBarrierOp_DSB ->
+ switch types {
+ case MBReqTypes_Reads -> IK_barrier(Barrier_DSB_LD)
+ case MBReqTypes_Writes -> IK_barrier(Barrier_DSB_ST)
+ case MBReqTypes_All -> IK_barrier(Barrier_DSB)
+ }
+ case MemBarrierOp_DMB ->
+ switch types {
+ case MBReqTypes_Reads -> IK_barrier(Barrier_DMB_LD)
+ case MBReqTypes_Writes -> IK_barrier(Barrier_DMB_ST)
+ case MBReqTypes_All -> IK_barrier(Barrier_DMB)
+ }
+ case MemBarrierOp_ISB ->
+ IK_barrier(Barrier_ISB)
+ };
+ }
+ case (System(t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,has_result)) -> {
+ oR := append(oR,xFP(t));
+ not_implemented("System"); (* because SysOp_R and SysOp_W *)
+ }
+ case (MoveSystemRegister(t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read)) -> {
+ if read then {
+ oR := append(oR,xFP(t));
+ switch (sys_op0,sys_op1,sys_crn,sys_crm,sys_op2) { (* System_Get *)
+ case (3,3,4,2,0) -> iR := RFull("NZCV") :: iR
+ case (3,3,4,2,1) -> iR := RFull("DAIF") :: iR
+ case (3, 3, 13, 0, 2) -> iR := RFull("TPIDR_EL0") :: iR
+ (* TODO FIXME: higher EL TPIDRs *)
+ }
+ }
+ else {
+ iR := append(iR,xFP(t));
+ switch (sys_op0,sys_op1,sys_crn,sys_crm,sys_op2) { (* System_Put *)
+ case (3,3,4,2,0) -> oR := RFull("NZCV") :: oR
+ case (3,3,4,2,1) -> oR := RFull("DAIF") :: oR
+ case (3, 3, 13, 0, 2) -> oR := RFull("TPIDR_EL0") :: oR
+ (* TODO FIXME: higher EL TPIDRs *)
+ }
+ }
+ }
+ case (ImplementationDefinedTestBeginEnd(isEnd)) -> ()
+ case (ImplementationDefinedStopFetching) -> ()
+ case (ImplementationDefinedThreadStart) -> ()
+ case (TestBitAndBranch(t,datasize,bit_pos,bit_val,offset)) -> {
+ iR := append(xFP(t),iR);
+ (* TODO: whether the following applies depends on runtime data:
+ operand[bit_pos] == bit_val *)
+ let (i,o) = BranchToFP(iR,oR) in {iR := i; oR := o};
+ Nias := [|| NIAFP_successor, NIAFP_concrete_address(rPC() + offset) ||];
+ ik := IK_cond_branch;
+ }
+ case (BranchImmediate(branch_type,offset)) -> {
+ if branch_type == BranchType_CALL
+ then {iR := _PCfp :: iR; oR := append(xFP(30),oR)};
+ let (i,o) = BranchToFP(iR,oR) in {iR := i; oR := o};
+ Nias := [|| NIAFP_concrete_address(rPC() + offset) ||];
+ ik := IK_simple (* IK_uncond_branch *)
+ }
+ case (BranchRegister(n,branch_type)) -> {
+ iR := append(iR,xFP(n));
+ if branch_type == BranchType_CALL
+ then {iR := _PCfp :: iR; oR := append(xFP(30),oR)};
+ let (i,o) = BranchToFP(iR,oR) in {iR := i; oR := o};
+ Nias := if n ==31
+ then [|| NIAFP_concrete_address(0) ||]
+ else [|| NIAFP_register(RFull(_Rs[n]))||];
+ ik := IK_simple (* IK_uncond_branch *)
+ }
+ case (ExceptionReturn) -> not_implemented("ExceptionReturn")
+ case (DebugRestorePState) -> not_implemented("DebugRestorePState")
+ case (LoadLiteral(t,memop,_signed,size,offset,datasize)) -> {
+ (* assuming rMem doesn't touch other registers *)
+ iR := _PCfp :: iR;
+ oR := append(xFP(t),oR);
+ aR := _PCfp :: aR;
+ switch memop {
+ case MemOp_LOAD -> ik := IK_mem_read(Read_plain)
+ case MemOp_PREFETCH -> {ik := IK_simple; aR := [|| ||]}
+ }
+ }
+ case (LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize)) -> {
+ (boolean) rt_unknown := false;
+ (boolean) rn_unknown := false;
+ if n==31 then {
+ iR := append(CheckSPAlignmentIFP,iR);
+ iR := append(rSPIFP,iR);
+ aR := append(rSPIFP,aR);
+ }
+ else if rn_unknown then ()
+ else {
+ iR := append(xFP(n),iR);
+ aR := append(xFP(n),aR);
+ };
+ switch memop {
+ case MemOp_STORE -> {
+ if rt_unknown then ()
+ else if pair then iR := append(xFP(t),append(xFP(t2),iR))
+ else iR := append(xFP(t),iR);
+ if excl then {
+ (* TODO: the command below depends on runtime data:
+ AArch64_ExclusiveMonitorsPass(address, dbytes) *)
+ iR := append(iR,wMemIFP);
+ oR := append(xFP(s),oR);
+ ik := wmem_kind(acctype,true);
+ }
+ else {
+ iR := append(iR,wMemIFP);
+ ik := wmem_kind(acctype,false);
+ }
+ }
+ case MemOp_LOAD -> {
+ if pair then {
+ if rt_unknown then
+ oR := append(xFP(t),oR)
+ else if elsize == 32 then {
+ iR := append(iR,BigEndianIFP);
+ oR := append(xFP(t),append(xFP(t2),oR));
+ }
+ else {
+ oR := append(xFP(t),append(xFP(t2),oR))
+ };
+ ik := rmem_kind(acctype,true);
+ }
+ else {
+ oR := append(xFP(t),oR);
+ ik := rmem_kind(acctype,excl);
+ }
+
+ }
+ case MemOp_PREFETCH -> aR := [|| ||]
+ }
+ }
+ case (LoadStorePairNonTemp(wback,postindex,n,t,t2,acctype,memop,scale,datasize,offset)) -> {
+ (boolean) rt_unknown := false;
+ if n == 31 then {
+ iR := append(CheckSPAlignmentIFP,iR);
+ iR := append(rSPIFP,iR);
+ aR := append(rSPIFP,aR);
+ }
+ else {
+ iR := append(xFP(n),iR);
+ aR := append(xFP(n),aR);
+ };
+ if wback then {
+ if n == 31 then
+ let (i,o) = wSPFP in {
+ iR := append(i,iR);
+ oR := append(o,oR);
+ }
+ else
+ oR := append(xFP(n),oR);
+ };
+ switch memop {
+ case MemOp_STORE -> {
+ if rt_unknown & t == n then ()
+ else iR := append(xFP(t),iR);
+ if rt_unknown & t2 == n then ()
+ else iR := append(xFP(t2),iR);
+ iR := append(wMemIFP,iR);
+ ik := wmem_kind(acctype,false);
+ }
+ case MemOp_LOAD -> {
+ oR := append(xFP(t),append(xFP(t2),oR));
+ ik := rmem_kind(acctype,false);
+ }
+ }
+ }
+ case (LoadImmediate(n,t,acctype,memop,_signed,wback,postindex,offset,regsize,datasize)) -> {
+ (boolean) wb_unknown := false;
+ (boolean) rt_unknown := false;
+ if n == 31 then {
+ iR := append(CheckSPAlignmentIFP,iR);
+ iR := append(rSPIFP,iR);
+ aR := append(rSPIFP,aR);
+ }
+ else {
+ iR := append(xFP(n),iR);
+ aR := append(xFP(n),aR);
+ };
+ if wback then {
+ if n == 31 then
+ let (i,o) = wSPFP in {iR := append(i,iR); oR := append(o,oR)}
+ else oR := append(xFP(n),oR);
+ };
+ switch memop {
+ case MemOp_STORE -> {
+ if rt_unknown then ()
+ else iR := append(xFP(t),iR);
+ iR := append(wMemIFP,iR);
+ ik := wmem_kind(acctype,false);
+ }
+ case MemOp_LOAD -> {
+ oR := append(xFP(t),oR);
+ ik := rmem_kind(acctype,false);
+ }
+ case MemOp_PREFETCH -> aR := [|| ||]
+ }
+ }
+ case (LoadRegister(n,t,m,acctype,memop,_signed,wback,postindex,extend_type,shift,regsize,datasize)) -> {
+ iR := append(xFP(m),iR);
+ aR := append(xFP(m),aR);
+ (boolean) wb_unknown := false;
+ (boolean) rt_unknown := false;
+ if n == 31 then {
+ iR := append(CheckSPAlignmentIFP,iR);
+ iR := append(rSPIFP,iR);
+ aR := append(rSPIFP,aR);
+ }
+ else {
+ iR := append(xFP(n),iR);
+ aR := append(xFP(n),aR);
+ };
+ if wback then {
+ if n == 31 then let (i,o) = wSPFP in {iR := append(i,iR); oR := append(o,oR)}
+ else oR := append(xFP(n),oR);
+ };
+ switch memop {
+ case MemOp_STORE -> {
+ if rt_unknown then ()
+ else iR := append(xFP(t),iR);
+ iR := append(wMemIFP,iR);
+ ik := wmem_kind(acctype,false);
+ }
+ case MemOp_LOAD -> {
+ oR := append(xFP(t),oR);
+ ik := rmem_kind(acctype,false);
+ }
+ case MemOp_PREFETCH -> aR := [|| ||]
+ }
+ }
+ case (LoadStorePair(wback,postindex,n,t,t2,acctype,memop,_signed,datasize,offset)) -> {
+ (boolean) rt_unknown := false;
+ (boolean) wb_unknown := false;
+ if n == 31 then {
+ iR := append(CheckSPAlignmentIFP,iR);
+ iR := append(rSPIFP,iR);
+ aR := append(rSPIFP,aR);
+ }
+ else {
+ iR := append(xFP(n),iR);
+ aR := append(xFP(n),aR);
+ };
+ if wback then {
+ if n == 31 then let (i,o) = wSPFP in {iR := append(i,iR); oR := append(o,oR)}
+ else oR := append(xFP(n),oR);
+ };
+ switch memop {
+ case MemOp_STORE -> {
+ if rt_unknown & t == n then ()
+ else iR := append(xFP(t),iR);
+ if rt_unknown & t2 == n then ()
+ else iR := append(xFP(t2),iR);
+ iR := append(wMemIFP,iR);
+ ik := wmem_kind(acctype,false);
+ }
+ case MemOp_LOAD -> {
+ oR := append(xFP(t),oR);
+ oR := append(xFP(t2),oR);
+ ik := rmem_kind(acctype,false);
+ }
+ }
+ }
+ case (AddSubImmediate(d,n,datasize,sub_op,setflags,imm)) -> {
+ iR := append(if n == 31 then rSPIFP else xFP(n),iR);
+ if setflags then oR := append(NZCVfp,oR);
+ if d ==31 & ~(setflags) then
+ let (i,o) = wSPFP in
+ { iR := append(i,iR);
+ oR := append(o,oR) }
+ else oR := append(xFP(d),oR)
+ }
+ case (BitfieldMove(d,n,datasize,inzero,extend,R,S,wmask,tmask)) -> {
+ if inzero then () else iR:= append(xFP(d),iR);
+ iR := append(xFP(n),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (ExtractRegister(d,n,m,datasize,lsb)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ oR := append(xFP(d),oR);
+ }
+ case (LogicalImmediate(d,n,datasize,setflags,op,imm)) -> {
+ iR := append(xFP(n),iR);
+ if setflags then oR := append(NZCVfp,oR);
+ if d ==31 & ~(setflags) then let (i,o) = wSPFP in
+ { iR := append(i,iR); oR := append(o,oR) }
+ else oR := append(xFP(d),oR)
+ }
+ case (MoveWide(d,datasize,imm,pos,opcode)) -> {
+ if opcode == MoveWideOp_K then iR := append(xFP(d),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (Address(d,page,imm)) -> {
+ iR := _PCfp :: iR;
+ oR := append(xFP(d),oR);
+ }
+ case (AddSubExtendRegister(d,n,m,datasize,sub_op,setflags,extend_type,shift)) -> {
+ iR := append(if n == 31 then rSPIFP else xFP(n),iR);
+ iR := append(xFP(m),iR);
+ if setflags then oR := append(NZCVfp,oR);
+ if d ==31 & ~(setflags) then let (i,o) = wSPFP in
+ { iR := append(i,iR); oR := append(o,oR) }
+ else oR := append(xFP(d),oR)
+ }
+ case (AddSubShiftedRegister(d,n,m,datasize,sub_op,setflags,shift_type,shift_amount)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ if setflags then oR := append(NZCVfp,oR);
+ oR := append(xFP(d),oR);
+ }
+ case (AddSubCarry(d,n,m,datasize,sub_op,setflags)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ iR := PSTATE_Cfp :: iR;
+ if setflags then oR := append(NZCVfp,oR);
+ oR := append(xFP(d),oR);
+ }
+ case (ConditionalCompareImmediate(n,datasize,sub_op,condition,flags,imm)) -> {
+ iR := append(xFP(n),iR);
+ iR := append(ConditionHoldsIFP(condition),iR);
+ oR := append(NZCVfp,oR);
+ }
+ case (ConditionalCompareRegister(n,m,datasize,sub_op,condition,flags)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ iR := append(ConditionHoldsIFP(condition),iR);
+ oR := append(NZCVfp,oR);
+ }
+ case (ConditionalSelect(d,n,m,datasize,condition,else_inv,else_inc)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ iR := append(ConditionHoldsIFP(condition),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (Reverse(d,n,datasize,op)) -> {
+ iR := append(xFP(n),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (CountLeading(d,n,datasize,opcode)) -> {
+ iR := append(xFP(n),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (Division(d,n,m,datasize,_unsigned)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ oR := append(xFP(d),oR);
+ }
+ case (Shift(d,n,m,datasize,shift_type)) -> {
+ iR := append(xFP(m),iR);
+ iR := append(xFP(n),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (CRC(d,n,m,size,crc32c)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ oR := append(xFP(d),oR);
+ }
+ case (MultiplyAddSub(d,n,m,a,destsize,datasize,sub_op)) -> {
+ iR := append(xFP(n),iR);
+ iR := append(xFP(m),iR);
+ iR := append(xFP(a),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (MultiplyAddSubLong(d,n,m,a,destsize,datasize,sub_op,_unsigned)) -> {
+ iR := append(xFP(n),iR);
+ iR := append(xFP(m),iR);
+ iR := append(xFP(a),iR);
+ oR := append(xFP(d),oR);
+ }
+ case (MultiplyHigh(d,n,m,a,destsize,datasize,_unsigned)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ oR := append(xFP(d),oR);
+ }
+ case (LogicalShiftedRegister(d,n,m,datasize,setflags,op,shift_type,shift_amount,invert)) -> {
+ iR := append(xFP(n),append(xFP(m),iR));
+ if setflags then oR := append(NZCVfp,oR);
+ oR := append(xFP(d),oR);
+ }
+ };
+ (iR,oR,aR,Nias,Dia,ik)
+}
diff --git a/arm/armV8.h.sail b/arm/armV8.h.sail
index c788855a..9105f964 100644
--- a/arm/armV8.h.sail
+++ b/arm/armV8.h.sail
@@ -43,6 +43,27 @@ typedef SIMD_index = [|32|]
register (bit[64]) _PC
+(* transactional memory registers *)
+register (bit[8]) TxNestingLevel (* same size as TXIDR_EL0.DEPTH *)
+
+typedef TMSTATUS_type = register bits [63:0]
+{
+ (*63..17 : RES0;*)
+ 16 : IMP;
+ 15 : DBG;
+ 14 : MEM;
+ 13 : ERR;
+ 12 : INV;
+ 11 : SIZE;
+ 10 : NEST;
+ 9 : ABRT;
+ 8 : RTRY;
+ (*7..5 : RES0*)
+ 4..0 : REASON;
+}
+register (TMSTATUS_type) TMAbortEffect (* we abuse the register write to pass out the status value *)
+register (TMSTATUS_type) TMStartEffect (* we abuse the register read to pass in the status value *)
+
(* General purpose registers *)
register (bit[64]) R30
@@ -170,3 +191,6 @@ let IMPLEMENTATION_DEFINED =
(* FIXME: ask Kathy what should we do with this *)
let UNKNOWN = 0
+
+
+val extern unit -> bool effect {exmem} speculate_exclusive_success
diff --git a/arm/armV8.sail b/arm/armV8.sail
index 10c57d1e..2614c7a5 100644
--- a/arm/armV8.sail
+++ b/arm/armV8.sail
@@ -40,6 +40,12 @@ typedef ast = const union forall Nat 'R, 'R IN {32, 64}, (* register size *)
ImplementationDefinedStopFetching;
ImplementationDefinedThreadStart;
+ (* transactional memory, from the pre-alpha document *)
+ (reg_index) TMStart;
+ TMCommit;
+ (boolean,bit[5]) TMAbort;
+ TMTest;
+
(reg_index,[:'R:],boolean,bit[64]) CompareAndBranch;
(bit[64],bit[4]) BranchConditional;
(bit[16]) GenerateExceptionEL1; (* TODO: add to .hgen *)
@@ -64,7 +70,7 @@ typedef ast = const union forall Nat 'R, 'R IN {32, 64}, (* register size *)
(boolean,boolean,reg_index,reg_index,reg_index,AccType,MemOp,uinteger,[:'D:],bit[64]) LoadStorePairNonTemp;
(reg_index,reg_index,AccType,MemOp,boolean,boolean,boolean,bit[64],[:'R:],[:'D:]) LoadImmediate;
(reg_index,reg_index,reg_index,AccType,MemOp,boolean,boolean,boolean,ExtendType,uinteger,[:'R:],[:'D:]) LoadRegister;
- (boolean,boolean,reg_index,reg_index,reg_index,AccType,MemOp,boolean,uinteger,[:'D:],bit[64]) LoadStorePair;
+ (boolean,boolean,reg_index,reg_index,reg_index,AccType,MemOp,boolean,[:'D:],bit[64]) LoadStorePair;
(reg_index,reg_index,[:'R:],boolean,boolean,bit['R]) AddSubImmediate;
(reg_index,reg_index,[:'R:],boolean,boolean,uinteger,uinteger,bit['R],bit['R]) BitfieldMove;
(reg_index,reg_index,reg_index,[:'R:],uinteger) ExtractRegister;
@@ -86,12 +92,91 @@ typedef ast = const union forall Nat 'R, 'R IN {32, 64}, (* register size *)
(reg_index,reg_index,reg_index,reg_index,[:'R:],[:'D:],boolean,boolean) MultiplyAddSubLong;
(reg_index,reg_index,reg_index,reg_index,[:'R:],[:'D:],boolean) MultiplyHigh;
(reg_index,reg_index,reg_index,[:'R:],boolean,LogicalOp,ShiftType,[|63|],boolean) LogicalShiftedRegister;
-
}
-val forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}. ast<'R,'D> -> unit effect {rreg,wreg,rmem,barr,eamem,wmv,escape} execute
+val forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}. ast<'R,'D> -> unit effect {rreg,wreg,rmem,barr,eamem,wmv,exmem,escape} execute
scattered function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}. unit execute
+(* TSTART - dummy decoding *)
+function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
+ option<(ast<'R,'D>)> effect pure decodeTMStart ((bit[5]) Rt) =
+{
+ (reg_index) t := UInt_reg(Rt);
+
+ Some(TMStart(t));
+}
+
+(* transactional memory, from the pre-alpha document *)
+function clause execute (TMStart(t)) = {
+ (bit[8]) nesting := TxNestingLevel;
+
+ if nesting <_u TXIDR_EL0.DEPTH then {
+ TxNestingLevel := nesting + 1;
+ (bit[64]) status := 0;
+ if nesting == 0 then
+ status := TMStartEffect; (* fake effect *)
+ wX(t) := status;
+ } else {
+ (bit[64]) status := 0;
+ status[10] := 1; (* set the NEST bit *)
+ TMAbortEffect := status; (* fake effect *)
+ }
+}
+
+val extern unit -> unit effect {barr} TMCommitEffect
+
+(* TCOMMIT - dummy decoding *)
+function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
+ option<(ast<'R,'D>)> effect pure decodeTMCommit () =
+{
+ Some(TMCommit);
+}
+
+(* transactional memory, from the pre-alpha document *)
+function clause execute (TMCommit) = {
+ (bit[8]) nesting := TxNestingLevel;
+
+ if nesting == 1 then
+ TMCommitEffect() (* fake effect *)
+ else if nesting == 0 then
+ AArch64_UndefinedFault();
+
+ TxNestingLevel := nesting - 1;
+}
+
+(* TTEST - dummy decoding *)
+function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
+ option<(ast<'R,'D>)> effect pure decodeTMTest () =
+{
+ Some(TMTest);
+}
+
+(* transactional memory, from the pre-alpha document *)
+function clause execute (TMTest) = {
+ if TxNestingLevel > 0 then
+ wPSTATE_NZCV() := 0b0000
+ else
+ wPSTATE_NZCV() := 0b0100
+}
+
+(* TABORT - dummy decoding *)
+function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
+ option<(ast<'R,'D>)> effect pure decodeTMAbort ([R]:(bit[5]) imm5) =
+{
+ Some(TMAbort(R,imm5));
+}
+
+(* transactional memory, from the pre-alpha document *)
+function clause execute (TMAbort(retry,reason)) = {
+ if TxNestingLevel > 0 then {
+ (bit[64]) status := 0;
+ status[4..0] := reason; (* REASON *)
+ status[8] := retry; (* RTRY *)
+ status[9] := 1; (* ABRT *)
+ TMAbortEffect := status; (* fake effect *)
+ };
+}
+
(* CBNZ *)
(* CBZ *)
function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
@@ -517,16 +602,16 @@ function clause execute ( TestBitAndBranch(t,datasize,bit_pos,bit_val,offset) )
(* BL *)
function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
option<(ast<'R,'D>)> effect {escape} decodeUnconditionalBranchImmediate ([op]:0b00101:(bit[26]) imm26) = {
- (BranchType) _branch_type := if op == 1 then BranchType_CALL else BranchType_JMP;
+ (BranchType) branch_type := if op == 1 then BranchType_CALL else BranchType_JMP;
(bit[64]) offset := SignExtend(imm26:0b00);
- Some(BranchImmediate(_branch_type,offset));
+ Some(BranchImmediate(branch_type,offset));
}
-function clause execute (BranchImmediate(_branch_type,offset)) = {
- if _branch_type == BranchType_CALL then wX(30) := rPC() + 4;
+function clause execute (BranchImmediate(branch_type,offset)) = {
+ if branch_type == BranchType_CALL then wX(30) := rPC() + 4;
- BranchTo(rPC() + offset, _branch_type);
+ BranchTo(rPC() + offset, branch_type);
}
@@ -540,24 +625,24 @@ scattered function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
(* RET *)
function clause decodeUnconditionalBranchRegister (0b1101011:0b00:op:0b11111:0b000000:Rn:0b00000) = {
(reg_index) n := UInt_reg(Rn);
- (BranchType) _branch_type := 0; (* ARM: uninitialized *)
+ (BranchType) branch_type := 0; (* ARM: uninitialized *)
switch op {
- case 0b00 -> _branch_type := BranchType_JMP
- case 0b01 -> _branch_type := BranchType_CALL
- case 0b10 -> _branch_type := BranchType_RET
+ case 0b00 -> branch_type := BranchType_JMP
+ case 0b01 -> branch_type := BranchType_CALL
+ case 0b10 -> branch_type := BranchType_RET
case _ -> UnallocatedEncoding()
};
- Some(BranchRegister(n,_branch_type));
+ Some(BranchRegister(n,branch_type));
}
-function clause execute (BranchRegister(n,_branch_type)) =
+function clause execute (BranchRegister(n,branch_type)) =
{
(bit[64]) target := rX(n);
- if _branch_type == BranchType_CALL then wX(30) := rPC() + 4;
- BranchTo(target, _branch_type);
+ if branch_type == BranchType_CALL then wX(30) := rPC() + 4;
+ BranchTo(target, branch_type);
}
(* ERET *)
@@ -717,7 +802,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
Some(LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize));
}
-function clause execute ( LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) ) = {
+function clause execute ( LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,([:'D:]) datasize) ) = {
(bit[64]) address := 0; (* ARM: uninitialized *)
(bit['D]) data := 0; (* ARM: uninitialized *)
(*constant*) (uinteger) dbytes := datasize quot 8;
@@ -760,6 +845,19 @@ function clause execute ( LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsiz
};
};
+ (* this is a hack to allow the result of store-exclusive to be observed
+ before anything else *)
+ (bit) status := 0;
+ if memop == MemOp_STORE & excl then {
+ (*(bit)*) status := if speculate_exclusive_success() then 0 else 1;
+ wX(s) := (bit[32]) (ZeroExtend([status]));
+
+ (* should be:
+ if status == 1 then return ();
+ *)
+ };
+ if status == 1 then () else {
+
if n == 31 then {
CheckSPAlignment();
address := rSP();
@@ -781,7 +879,7 @@ function clause execute ( LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsiz
(bit['R]) el2 := rX(t2); (* ARM: bit[datasize / 2] see lemma in the decoding *)
data := if BigEndian() then el1:el2 else el2:el1;
} else
- data := rX(t);
+ (bit['D]) data := rX(t);
if excl then {
(* store {release} exclusive register|pair (atomic) *)
@@ -798,7 +896,9 @@ function clause execute ( LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsiz
wMem_exclusive(empty_write_buffer, address, dbytes, acctype, data)
);
};
+ (* ARM: the following code was moved up, see note there
wX(s) := (bit[32]) (ZeroExtend([status]));
+ *)
} else {
(* store release register (atomic) *)
flush_write_buffer(
@@ -860,6 +960,7 @@ function clause execute ( LoadStoreAcqExc(n,t,t2,s,acctype,excl,pair,memop,elsiz
};
}
};
+ };
}
(* LDNP *)
@@ -885,7 +986,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
Some(LoadStorePairNonTemp(wback,postindex,n,t,t2,acctype,memop,scale,datasize,offset));
}
-function clause execute ( LoadStorePairNonTemp(wback,postindex,n,t,t2,acctype,memop,scale,datasize,offset) ) = {
+function clause execute ( LoadStorePairNonTemp(wback,postindex,n,t,t2,acctype,memop,scale,([:'D:]) datasize,offset) ) = {
(bit[64]) address := 0; (* ARM: uninitialized *)
(bit['D]) data1 := 0; (* ARM: uninitialized *)
(bit['D]) data2 := 0; (* ARM: uninitialized *)
@@ -930,11 +1031,11 @@ function clause execute ( LoadStorePairNonTemp(wback,postindex,n,t,t2,acctype,me
switch memop {
case MemOp_STORE -> {
if rt_unknown & t == n then
- date1 := (bit['D]) UNKNOWN
+ data1 := (bit['D]) UNKNOWN
else
data1 := rX(t);
if rt_unknown & t2 == n then
- date2 := (bit['D]) UNKNOWN
+ data2 := (bit['D]) UNKNOWN
else
data2 := rX(t2);
@@ -951,7 +1052,7 @@ function clause execute ( LoadStorePairNonTemp(wback,postindex,n,t,t2,acctype,me
data2 := read_data[((datasize * 2) - 1)..datasize];
if rt_unknown then {
- date1 := (bit['D]) UNKNOWN;
+ data1 := (bit['D]) UNKNOWN;
data2 := (bit['D]) UNKNOWN;
};
wX(t) := data1;
@@ -1028,7 +1129,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
sharedDecodeLoadImmediate(opc,size,Rn,Rt,wback,postindex,scale,offset,AccType_NORMAL,false);
}
-function clause execute ( LoadImmediate(n,t,acctype,memop,_signed,wback,postindex,offset,regsize,datasize) ) = {
+function clause execute ( LoadImmediate(n,t,acctype,memop,_signed,wback,postindex,offset,regsize,([:'D:]) datasize) ) = {
(bit[64]) address := 0; (* ARM: uninitialized *)
(bit['D]) data := 0; (* ARM: uninitialized *)
(boolean) wb_unknown := false;
@@ -1191,7 +1292,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
sharedDecodeLoadRegister(Rn,Rt,Rm,opc,size,wback,postindex,scale,extend_type,shift);
}
-function clause execute ( LoadRegister(n,t,m,acctype,memop,_signed,wback,postindex,extend_type,shift,regsize,datasize) ) = {
+function clause execute ( LoadRegister(n,t,m,acctype,memop,_signed,wback,postindex,extend_type,shift,regsize,([:'D:]) datasize) ) = {
(bit[64]) offset := ExtendReg(m, extend_type, shift);
(bit[64]) address := 0; (* ARM: uninitialized *)
(bit['D]) data := 0; (* ARM: uninitialized *)
@@ -1352,7 +1453,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
([:'D:]) datasize := lsl(8, scale);
(bit[64]) offset := LSL(SignExtend(imm7), scale);
- Some(LoadStorePair(wback,postindex,n,t,t2,acctype,memop,_signed,scale,datasize,offset));
+ Some(LoadStorePair(wback,postindex,n,t,t2,acctype,memop,_signed,datasize,offset));
}
(* LDP signed offset *)
@@ -1367,7 +1468,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
sharedDecodeLoadStorePair(L,opc,imm7,Rn,Rt,Rt2,wback,postindex);
}
-function clause execute ( LoadStorePair(wback,postindex,n,t,t2,acctype,memop,_signed,scale,datasize,offset) ) = {
+function clause execute ( LoadStorePair(wback,postindex,n,t,t2,acctype,memop,_signed,([:'D:])datasize,offset) ) = {
(bit[64]) address := 0; (* ARM: uninitialized *)
(bit['D]) data1 := 0; (* ARM: uninitialized *)
(bit['D]) data2 := 0; (* ARM: uninitialized *)
@@ -1616,7 +1717,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
Some(ExtractRegister(d,n,m,datasize,lsb));
}
-function clause execute ( ExtractRegister(d,n,m,datasize,lsb) ) = {
+function clause execute ( ExtractRegister(d,n,m,([:'R:]) datasize,lsb) ) = {
(bit['R]) result := 0; (* ARM: uninitialized *)
(bit['R]) operand1 := rX(n);
(bit['R]) operand2 := rX(m);
@@ -1650,7 +1751,7 @@ function forall Nat 'R, 'R IN {32,64}, Nat 'D, 'D IN {8,16,32,64}.
Some(LogicalImmediate(d,n,datasize,setflags,op,imm));
}}
-function clause execute (LogicalImmediate(d,n,datasize,setflags,op,imm)) = {
+function clause execute (LogicalImmediate(d,n,([:'R:]) datasize,setflags,op,imm)) = {
(bit['R]) result := 0; (* ARM: uninitialized *)
(bit['R]) operand1 := rX(n);
(bit['R]) operand2 := imm;
diff --git a/arm/armV8_A64_lib.sail b/arm/armV8_A64_lib.sail
index 5a1b6ec3..2aa31d4f 100644
--- a/arm/armV8_A64_lib.sail
+++ b/arm/armV8_A64_lib.sail
@@ -730,6 +730,8 @@ function bit[64] System_Get((uinteger) op0, (uinteger) op1, (uinteger) crn, (uin
switch (op0,op1,crn,crm,op2) {
case (3,3,4,2,0) -> ZeroExtend(NZCV)
case (3,3,4,2,1) -> ZeroExtend(DAIF)
+ case (3, 3, 13, 0, 2) -> TPIDR_EL0
+ (* TODO FIXME: higher EL TPIDRs *)
(* case (3,0,1,0,1) -> ZeroExtend(ACTLR_EL1) *)
}
@@ -741,6 +743,8 @@ function unit effect {wreg} System_Put((uinteger) op0, (uinteger) op1, (uinteger
switch (op0,op1,crn,crm,op2) {
case (3,3,4,2,0) -> NZCV := _val[31..0]
case (3,3,4,2,1) -> DAIF := _val[31..0]
+ case (3, 3, 13, 0, 2) -> TPIDR_EL0 := _val[63..0]
+ (* TODO FIXME: higher EL TPIDRs *)
(* case (3,0,1,0,1) -> ACTLR_EL1 := _val[31..0] *)
}
@@ -756,7 +760,19 @@ function unit AArch64_ExceptionReturn((bit[64]) new_pc, (bit[32]) spsr) =
(** ENUMERATE:aarch64/instrs/countop/CountOp *)
(** FUNCTION:ExtendType DecodeRegExtend(bits(3) op) *)
-function ExtendType DecodeRegExtend ((bit[3]) op) = ([|8|]) op
+function ExtendType DecodeRegExtend ((bit[3]) op) =
+{
+ switch op {
+ case 0b000 -> ExtendType_UXTB
+ case 0b001 -> ExtendType_UXTH
+ case 0b010 -> ExtendType_UXTW
+ case 0b011 -> ExtendType_UXTX
+ case 0b100 -> ExtendType_SXTB
+ case 0b101 -> ExtendType_SXTH
+ case 0b110 -> ExtendType_SXTW
+ case 0b111 -> ExtendType_SXTX
+ }
+}
(** FUNCTION:aarch64/instrs/extendreg/ExtendReg *)
diff --git a/arm/armV8_A64_sys_regs.sail b/arm/armV8_A64_sys_regs.sail
index 50c150c6..95b5c710 100644
--- a/arm/armV8_A64_sys_regs.sail
+++ b/arm/armV8_A64_sys_regs.sail
@@ -35,162 +35,6 @@
(*************************************************************************)
(* General system control registers *)
-register (bit[32]) ACTLR_EL1 (* Auxiliary Control Register (EL1) *) (* UNUSED *)
-register (bit[32]) ACTLR_EL2 (* Auxiliary Control Register (EL2) *) (* UNUSED *)
-register (bit[32]) ACTLR_EL3 (* Auxiliary Control Register (EL3) *) (* UNUSED *)
-register (bit[32]) AFSR0_EL1 (* Auxiliary Fault Status Register 0 (EL1) *) (* UNUSED *)
-register (bit[32]) AFSR0_EL2 (* Auxiliary Fault Status Register 0 (EL2) *) (* UNUSED *)
-register (bit[32]) AFSR0_EL3 (* Auxiliary Fault Status Register 0 (EL3) *) (* UNUSED *)
-register (bit[32]) AFSR1_EL1 (* Auxiliary Fault Status Register 1 (EL1) *) (* UNUSED *)
-register (bit[32]) AFSR1_EL2 (* Auxiliary Fault Status Register 1 (EL2) *) (* UNUSED *)
-register (bit[32]) AFSR1_EL3 (* Auxiliary Fault Status Register 1 (EL3) *) (* UNUSED *)
-register (bit[32]) AIDR_EL1 (* Auxiliary ID Register *) (* UNUSED *)
-register (bit[64]) AMAIR_EL1 (* Auxiliary Memory Attribute Indirection Register (EL1) *) (* UNUSED *)
-register (bit[64]) AMAIR_EL2 (* Auxiliary Memory Attribute Indirection Register (EL2) *) (* UNUSED *)
-register (bit[64]) AMAIR_EL3 (* Auxiliary Memory Attribute Indirection Register (EL3) *) (* UNUSED *)
-
-typedef CCSIDR_type = register bits [31:0]
-{
- 31 : WT;
- 30 : WB;
- 29 : RA;
- 28 : WA;
- 27..13 : NumSets;
- 12..3 : Associativity;
- 2..0 : LineSize;
-}
-register (CCSIDR_type) CCSIDR_EL1 (* Current Cache Size ID Register *) (* UNUSED *)
-
-typedef CLIDR_type = register bits [63:0]
-{
- (*63..33 : RES0*)
- 32..30 : ICB;
- 29..27 : LoUU;
- 26..24 : LoC;
- 23..21 : LoUIS;
- 20..18 : Ctype7;
- 17..15 : Ctype6;
- 14..12 : Ctype5;
- 11..9 : Ctype4;
- 8..6 : Ctype3;
- 5..3 : Ctype2;
- 2..0 : Ctype1;
-}
-register (CLIDR_type) CLIDR_EL1 (* Cache Level ID Register *) (* UNUSED *)
-
-typedef CONTEXTIDR_type = register bits [31:0] { 31..0 : PROCID }
-register (CONTEXTIDR_type) CONTEXTIDR_EL1 (* Context ID Register *) (* UNUSED *)
-
-typedef CPACR_type = register bits [31:0]
-{
- (*31..29 : RES0;*)
- 28 : TTA;
- (*27..22 : RES0;*)
- 21..20 : FPEN;
- (*19..0 : RES0;*)
-}
-register (CPACR_type) CPACR_EL1 (* Architectural Feature Access Control Register *) (* UNUSED *)
-
-typedef CPTR_type = register bits [31:0]
-{
- (* in EL3 all the RES are RES0 *)
- 31 : TCPAC;
- (*30..21 : RES0;*)
- 20 : TTA;
- (*19..14 : RES0;*)
- (*13..12 : RES1;*)
- (*11 : RES0;*)
- 10 : TFP;
- (*9..0 : RES1;*)
-}
-register (CPTR_type) CPTR_EL2 (* Architectural Feature Trap Register (EL2) *) (* UNUSED *)
-register (CPTR_type) CPTR_EL3 (* Architectural Feature Trap Register (EL3) *) (* UNUSED *)
-
-typedef CSSELR_type = register bits [31:0]
-{
- (*31..4 : RES0;*)
- 3..1 : Level;
- 0 : InD;
-}
-register (CSSELR_type) CSSELR_EL1 (* Cache Size Selection Register *) (* UNUSED *)
-
-typedef CTR_type = register bits [31:0]
-{
- (*31 : RES1;*)
- (*30..28 : RES0;*)
- 27..24 : CWG;
- 23..20 : ERG;
- 19..16 : DminLine;
- 15..14 : L1Ip;
- (*13..4 : RES0;*)
- 3..0 : IminLine;
-}
-register (CTR_type) CTR_EL0 (* Cache Type Register *) (* UNUSED *)
-
-typedef DACR32_type = register bits [31:0]
-{
- 31..30 : D15;
- 29..28 : D14;
- 27..26 : D13;
- 25..24 : D12;
- 23..22 : D11;
- 21..20 : D10;
- 29..18 : D9;
- 17..16 : D8;
- 15..14 : D7;
- 13..12 : D6;
- 11..10 : D5;
- 9..8 : D4;
- 7..6 : D3;
- 5..4 : D2;
- 3..2 : D1;
- 1..0 : D0;
-}
-register (DACR32_type) DACR32_EL2 (* Domain Access Control Register *) (* UNUSED *)
-
-typedef DCZID_type = register bits [31:0]
-{
- (*31..5 : RES0;*)
- 4 : DZP;
- 3..0 : BS;
-}
-register (DCZID_type) DCZID_EL0 (* Data Cache Zero ID register *) (* UNUSED *)
-
-typedef ESR_type = register bits [31:0]
-{
- 31..26 : EC;
- 25 : IL;
- 24..0 : ISS;
-}
-register (ESR_type) ESR_EL1 (* Exception Syndrome Register (EL1) *) (* UNUSED *)
-register (ESR_type) ESR_EL2 (* Exception Syndrome Register (EL2) *) (* UNUSED *)
-register (ESR_type) ESR_EL3 (* Exception Syndrome Register (EL3) *) (* UNUSED *)
-
-register (bit[64]) FAR_EL1 (* Fault Address Register (EL1) *) (* UNUSED *)
-register (bit[64]) FAR_EL2 (* Fault Address Register (EL2) *) (* UNUSED *)
-register (bit[64]) FAR_EL3 (* Fault Address Register (EL3) *) (* UNUSED *)
-
-typedef FPEXC32_type = register bits [31:0]
-{
- 31 : EX;
- 30 : EN;
- 29 : DEX;
- 28 : FP2V;
- 27 : VV;
- 26 : TFV;
- (*25..21 : RES0;*)
- (*20..11 : IMPLEMENTATION DEFINED*)
- 10..8 : VECITR;
- 7 : IDF;
- (*6..5 : IMPLEMENTATION DEFINED*)
- 4 : IXF;
- 3 : UFF;
- 2 : OFF;
- 1 : DZF;
- 0 : IOF;
-}
-register (FPEXC32_type) FPEXC32_EL2 (* Floating-point Exception Control register *) (* UNUSED *)
-register (bit[32]) HACR_EL2 (* Hypervisor Auxiliary Control Register *) (* UNUSED *)
typedef HCR_type = register bits [63:0]
{
@@ -231,35 +75,6 @@ typedef HCR_type = register bits [63:0]
}
register (HCR_type) HCR_EL2 (* Hypervisor Configuration Register *)
-typedef HPFAR_type = register bits [63:0]
-{
- (*63..40 : RES0;*)
- 39..4 : FIPA; (* bits [47:12] of FIPA *)
- (*3..0 : RES0;*)
-}
-register (HPFAR_type) HPFAR_EL2 (* Hypervisor IPA Fault Address Register *) (* UNUSED *)
-
-typedef HSTR_type = register bits [31:0]
-{
- (*31..16 : RES0;*)
- 15 : T15;
- 14 : T14;
- 13 : T13;
- 12 : T12;
- 11 : T11;
- 10 : T10;
- 9 : T9;
- 8 : T8;
- 7 : T7;
- 6 : T6;
- 5 : T5;
- 4 : T4;
- 3 : T3;
- 2 : T2;
- 1 : T1;
- 0 : T0;
-}
-register (HSTR_type) HSTR_EL2 (* Hypervisor System Trap Register *) (* UNUSED *)
typedef ID_AA64MMFR0_type = register bits [63:0]
{
@@ -402,6 +217,11 @@ typedef TCR_type = register bits [31:0]
register (TCR_type) TCR_EL2 (* Translation Control Register (EL2) *)
register (TCR_type) TCR_EL3 (* Translation Control Register (EL3) *)
+register (bit[64]) TPIDR_EL0 (* EL0 Read/Write Software Thread ID Register *)
+register (bit[64]) TPIDR_EL1 (* EL1 Read/Write Software Thread ID Register *)
+register (bit[64]) TPIDR_EL2 (* EL2 Read/Write Software Thread ID Register *)
+register (bit[64]) TPIDR_EL3 (* EL3 Read/Write Software Thread ID Register *)
+
(*************************************************************************)
(* Debug registers *)
@@ -458,9 +278,17 @@ typedef EDSCR_type = register bits [31:0]
}
register (EDSCR_type) EDSCR (* External Debug Status and Control Register *)
+(* transactional memory, from the pre-alpha document *)
+typedef TXIDR_EL0_type = register bits [63:0]
+{
+ (*63..8 : RES0;*)
+ 7..0 : DEPTH;
+}
+register (TXIDR_EL0_type) TXIDR_EL0 (* Transaction ID Register *)
+
+
function unit effect pure AArch64_ResetControlRegisters((boolean) cold_reset) =
{
()
}
-
diff --git a/arm/armV8_common_lib.sail b/arm/armV8_common_lib.sail
index 3bae8070..9bea1cd1 100644
--- a/arm/armV8_common_lib.sail
+++ b/arm/armV8_common_lib.sail
@@ -513,8 +513,8 @@ val extern unit -> unit effect {barr} DataMemoryBarrier_All
function unit effect {barr} DataMemoryBarrier((MBReqDomain) domain, (MBReqTypes) types) =
{
- if domain != MBReqDomain_FullSystem then
- not_implemented("DataMemoryBarrier: not MBReqDomain_FullSystem");
+ if domain != MBReqDomain_FullSystem & domain != MBReqDomain_InnerShareable then
+ not_implemented("DataMemoryBarrier: not MBReqDomain_FullSystem or _InnerShareable");
switch types {
case MBReqTypes_Reads -> DataMemoryBarrier_Reads()
@@ -725,10 +725,10 @@ function bool effect {wmv} flush_write_buffer_exclusive((write_buffer_type) writ
(** FUNCTION:BranchTo(bits(N) target, BranchType branch_type) *)
-function forall Nat 'N, 'N IN {32,64}. unit effect {rreg,wreg} BranchTo((bit['N]) target, (BranchType) _branch_type) = {
+function forall Nat 'N, 'N IN {32,64}. unit effect {rreg,wreg} BranchTo((bit['N]) target, (BranchType) branch_type) = {
(bit['N]) target' := target; (* Sail does not let you change parameter vector *)
- Hint_Branch(_branch_type);
+ Hint_Branch(branch_type);
if length(target) == 32 then {
assert( UsingAArch32(), None );
_PC := ZeroExtend(target);
@@ -831,7 +831,7 @@ function boolean effect {rreg} ConditionHolds((bit[4]) _cond) =
case 0b111 -> result := true (* AL *)
};
- (* Condition flag valuesin the set '111x' indicate always true *)
+ (* Condition flag values in the set '111x' indicate always true *)
(* Otherwise, invert condition if necessary. *)
if _cond[0] == 1 & _cond != 0b1111 then
result := ~(result);
diff --git a/arm/armV8_extras.lem b/arm/armV8_extras.lem
new file mode 100644
index 00000000..9a187ecb
--- /dev/null
+++ b/arm/armV8_extras.lem
@@ -0,0 +1,77 @@
+open import Pervasives
+open import Interp_ast
+open import Interp_interface
+open import Sail_impl_base
+open import Interp_inter_imp
+import Set_extra
+
+let memory_parameter_transformer mode v =
+ match v with
+ | Interp_ast.V_tuple [location;length] ->
+ let (v,loc_regs) = extern_with_track mode extern_vector_value location in
+
+ match length with
+ | Interp_ast.V_lit (L_aux (L_num len) _) ->
+ (v,(natFromInteger len),loc_regs)
+
+ | Interp_ast.V_track (Interp_ast.V_lit (L_aux (L_num len) _)) size_regs ->
+ match loc_regs with
+ | Nothing -> (v,(natFromInteger len),Just (List.map (fun r -> extern_reg r Nothing) (Set_extra.toList size_regs)))
+ | Just loc_regs -> (v,(natFromInteger len),Just (loc_regs++(List.map (fun r -> extern_reg r Nothing) (Set_extra.toList size_regs))))
+ end
+
+ | _ -> Assert_extra.failwith "expected 'V_lit (L_aux (L_num _) _)' or 'V_track (V_lit (L_aux (L_num len) _)) _'"
+ end
+ | _ -> Assert_extra.failwith "expected 'V_tuple [_;_]'"
+ end
+
+let aArch64_read_memory_functions : memory_reads =
+ [ ("rMem_NORMAL", (MR Read_plain memory_parameter_transformer));
+ ("rMem_STREAM", (MR Read_stream memory_parameter_transformer));
+ ("rMem_ORDERED", (MR Read_acquire memory_parameter_transformer));
+ ("rMem_ATOMIC", (MR Read_exclusive memory_parameter_transformer));
+ ("rMem_ATOMIC_ORDERED", (MR Read_exclusive_acquire memory_parameter_transformer));
+ ]
+
+let aArch64_memory_writes : memory_writes = []
+ (* [ ("wMem_NORMAL", (MW Write_plain memory_parameter_transformer Nothing));
+ ("wMem_ORDERED", (MW Write_release memory_parameter_transformer Nothing));
+ ("wMem_ATOMIC", (MW Write_exclusive memory_parameter_transformer Nothing));
+ ("wMem_ATOMIC_ORDERED", (MW Write_exclusive_release memory_parameter_transformer Nothing));
+ ] *)
+
+let aArch64_memory_eas : memory_write_eas =
+ [ ("wMem_Addr_NORMAL", (MEA Write_plain memory_parameter_transformer));
+ ("wMem_Addr_ORDERED", (MEA Write_release memory_parameter_transformer));
+ ("wMem_Addr_ATOMIC", (MEA Write_exclusive memory_parameter_transformer));
+ ("wMem_Addr_ATOMIC_ORDERED", (MEA Write_exclusive_release memory_parameter_transformer));
+ ]
+
+let aArch64_memory_vals : memory_write_vals =
+ [ ("wMem_Val_NORMAL", (MV (fun mode v -> Nothing) Nothing));
+ ("wMem_Val_ATOMIC", (MV (fun mode v -> Nothing)
+ (Just
+ (fun (IState interp context) b ->
+ (*ppcmem2 provides true for success and false for failure; but the status for ARM is reversed*)
+ let bit = Interp_ast.V_lit (L_aux (if b then L_zero else L_one) Interp_ast.Unknown)in
+ (IState (Interp.add_answer_to_stack interp bit) context)))));
+ ]
+
+let aArch64_excl_res : excl_res =
+ let f = fun (IState interp context) b ->
+ let bool_res = Interp_ast.V_lit (L_aux (if b then L_one else L_zero) Interp_ast.Unknown) in
+ IState (Interp.add_answer_to_stack interp bool_res) context
+ in
+ Just ("speculate_exclusive_success", (ER (Just f)))
+
+let aArch64_barrier_functions =
+ [ ("DataMemoryBarrier_Reads", Barrier_DMB_LD);
+ ("DataMemoryBarrier_Writes", Barrier_DMB_ST);
+ ("DataMemoryBarrier_All", Barrier_DMB);
+ ("DataSynchronizationBarrier_Reads", Barrier_DSB_LD);
+ ("DataSynchronizationBarrier_Writes", Barrier_DSB_ST);
+ ("DataSynchronizationBarrier_All", Barrier_DSB);
+ ("InstructionSynchronizationBarrier", Barrier_ISB);
+
+ ("TMCommitEffect", Barrier_TM_COMMIT);
+ ]
diff --git a/arm/armV8_extras_embed.lem b/arm/armV8_extras_embed.lem
new file mode 100644
index 00000000..86570fc4
--- /dev/null
+++ b/arm/armV8_extras_embed.lem
@@ -0,0 +1,59 @@
+open import Pervasives
+open import Sail_impl_base
+open import Sail_values
+open import Prompt
+
+val rMem_NORMAL : (vector bitU * integer) -> M (vector bitU)
+val rMem_STREAM : (vector bitU * integer) -> M (vector bitU)
+val rMem_ORDERED : (vector bitU * integer) -> M (vector bitU)
+val rMem_ATOMICL : (vector bitU * integer) -> M (vector bitU)
+val rMem_ATOMIC_ORDERED : (vector bitU * integer) -> M (vector bitU)
+
+let rMem_NORMAL (addr,size) = read_mem false Read_plain addr size
+let rMem_STREAM (addr,size) = read_mem false Read_stream addr size
+let rMem_ORDERED (addr,size) = read_mem false Read_acquire addr size
+let rMem_ATOMIC (addr,size) = read_mem false Read_exclusive addr size
+let rMem_ATOMIC_ORDERED (addr,size) = read_mem false Read_exclusive_acquire addr size
+
+val wMem_Addr_NORMAL : (vector bitU * integer) -> M unit
+val wMem_Addr_ORDERED : (vector bitU * integer) -> M unit
+val wMem_Addr_ATOMIC : (vector bitU * integer) -> M unit
+val wMem_Addr_ATOMIC_ORDERED : (vector bitU * integer) -> M unit
+
+let wMem_Addr_NORMAL (addr,size) = write_mem_ea Write_plain addr size
+let wMem_Addr_ORDERED (addr,size) = write_mem_ea Write_release addr size
+let wMem_Addr_ATOMIC (addr,size) = write_mem_ea Write_exclusive addr size
+let wMem_Addr_ATOMIC_ORDERED (addr,size) = write_mem_ea Write_exclusive_release addr size
+
+
+val wMem_Val_NORMAL : (integer * vector bitU) -> M unit
+val wMem_Val_ATOMIC : (integer * vector bitU) -> M bitU
+
+let wMem_Val_NORMAL (_,v) = write_mem_val v >>= fun _ -> return ()
+(* in ARM the status returned is inversed *)
+let wMem_Val_ATOMIC (_,v) = write_mem_val v >>= fun b -> return (if b then B0 else B1)
+
+let speculate_exclusive_success () = excl_result () >>= fun b -> return (if b then B1 else B0)
+
+val DataMemoryBarrier_Reads : unit -> M unit
+val DataMemoryBarrier_Writes : unit -> M unit
+val DataMemoryBarrier_All : unit -> M unit
+val DataSynchronizationBarrier_Reads : unit -> M unit
+val DataSynchronizationBarrier_Writes : unit -> M unit
+val DataSynchronizationBarrier_All : unit -> M unit
+val InstructionSynchronizationBarrier : unit -> M unit
+
+let DataMemoryBarrier_Reads () = barrier Barrier_DMB_LD
+let DataMemoryBarrier_Writes () = barrier Barrier_DMB_ST
+let DataMemoryBarrier_All () = barrier Barrier_DMB
+let DataSynchronizationBarrier_Reads () = barrier Barrier_DSB_LD
+let DataSynchronizationBarrier_Writes () = barrier Barrier_DSB_ST
+let DataSynchronizationBarrier_All () = barrier Barrier_DSB
+let InstructionSynchronizationBarrier () = barrier Barrier_ISB
+
+val TMCommitEffect : unit -> M unit
+let TMCommitEffect () = barrier Barrier_TM_COMMIT
+
+let duplicate_bits (Vector bits start direction,len) =
+ let bits' = repeat bits len in
+ Vector bits' start direction
diff --git a/arm/armV8_extras_embed_sequential.lem b/arm/armV8_extras_embed_sequential.lem
new file mode 100644
index 00000000..d2bb8330
--- /dev/null
+++ b/arm/armV8_extras_embed_sequential.lem
@@ -0,0 +1,59 @@
+open import Pervasives
+open import Sail_impl_base
+open import Sail_values
+open import State
+
+val rMem_NORMAL : (vector bitU * integer) -> M (vector bitU)
+val rMem_STREAM : (vector bitU * integer) -> M (vector bitU)
+val rMem_ORDERED : (vector bitU * integer) -> M (vector bitU)
+val rMem_ATOMICL : (vector bitU * integer) -> M (vector bitU)
+val rMem_ATOMIC_ORDERED : (vector bitU * integer) -> M (vector bitU)
+
+let rMem_NORMAL (addr,size) = read_mem false Read_plain addr size
+let rMem_STREAM (addr,size) = read_mem false Read_stream addr size
+let rMem_ORDERED (addr,size) = read_mem false Read_acquire addr size
+let rMem_ATOMIC (addr,size) = read_mem false Read_exclusive addr size
+let rMem_ATOMIC_ORDERED (addr,size) = read_mem false Read_exclusive_acquire addr size
+
+val wMem_Addr_NORMAL : (vector bitU * integer) -> M unit
+val wMem_Addr_ORDERED : (vector bitU * integer) -> M unit
+val wMem_Addr_ATOMIC : (vector bitU * integer) -> M unit
+val wMem_Addr_ATOMIC_ORDERED : (vector bitU * integer) -> M unit
+
+let wMem_Addr_NORMAL (addr,size) = write_mem_ea Write_plain addr size
+let wMem_Addr_ORDERED (addr,size) = write_mem_ea Write_release addr size
+let wMem_Addr_ATOMIC (addr,size) = write_mem_ea Write_exclusive addr size
+let wMem_Addr_ATOMIC_ORDERED (addr,size) = write_mem_ea Write_exclusive_release addr size
+
+
+val wMem_Val_NORMAL : (integer * vector bitU) -> M unit
+val wMem_Val_ATOMIC : (integer * vector bitU) -> M bitU
+
+let wMem_Val_NORMAL (_,v) = write_mem_val v >>= fun _ -> return ()
+(* in ARM the status returned is inversed *)
+let wMem_Val_ATOMIC (_,v) = write_mem_val v >>= fun b -> return (if b then B0 else B1)
+
+let speculate_exclusive_success () = excl_result () >>= fun b -> return (if b then B1 else B0)
+
+val DataMemoryBarrier_Reads : unit -> M unit
+val DataMemoryBarrier_Writes : unit -> M unit
+val DataMemoryBarrier_All : unit -> M unit
+val DataSynchronizationBarrier_Reads : unit -> M unit
+val DataSynchronizationBarrier_Writes : unit -> M unit
+val DataSynchronizationBarrier_All : unit -> M unit
+val InstructionSynchronizationBarrier : unit -> M unit
+
+let DataMemoryBarrier_Reads () = barrier Barrier_DMB_LD
+let DataMemoryBarrier_Writes () = barrier Barrier_DMB_ST
+let DataMemoryBarrier_All () = barrier Barrier_DMB
+let DataSynchronizationBarrier_Reads () = barrier Barrier_DSB_LD
+let DataSynchronizationBarrier_Writes () = barrier Barrier_DSB_ST
+let DataSynchronizationBarrier_All () = barrier Barrier_DSB
+let InstructionSynchronizationBarrier () = barrier Barrier_ISB
+
+val TMCommitEffect : unit -> M unit
+let TMCommitEffect () = barrier Barrier_TM_COMMIT
+
+let duplicate_bits (Vector bits start direction,len) =
+ let bits' = repeat bits len in
+ Vector bits' start direction
diff --git a/arm/armV8_lib.h.sail b/arm/armV8_lib.h.sail
index 849472e1..d52cc5d5 100644
--- a/arm/armV8_lib.h.sail
+++ b/arm/armV8_lib.h.sail
@@ -187,9 +187,8 @@ typedef CountOp =
enumerate {CountOp_CLZ; CountOp_CLS; CountOp_CNT}
typedef ExtendType =
- (* the oreder is important for decoding *)
- enumerate { ExtendType_UXTB; ExtendType_UXTH; ExtendType_UXTW; ExtendType_UXTX;
- ExtendType_SXTB; ExtendType_SXTH; ExtendType_SXTW; ExtendType_SXTX }
+ enumerate { ExtendType_SXTB; ExtendType_SXTH; ExtendType_SXTW; ExtendType_SXTX;
+ ExtendType_UXTB; ExtendType_UXTH; ExtendType_UXTW; ExtendType_UXTX }
typedef RevOp =
enumerate {RevOp_RBIT; RevOp_REV16; RevOp_REV32; RevOp_REV64}
diff --git a/arm/gen/ast.hgen b/arm/gen/ast.hgen
new file mode 100644
index 00000000..60f130d7
--- /dev/null
+++ b/arm/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/arm/gen/fold.hgen b/arm/gen/fold.hgen
new file mode 100644
index 00000000..4062d8e6
--- /dev/null
+++ b/arm/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/arm/gen/herdtools_ast_to_shallow_ast.hgen b/arm/gen/herdtools_ast_to_shallow_ast.hgen
new file mode 100644
index 00000000..5a19e483
--- /dev/null
+++ b/arm/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) ->
+ Barrier2
+ (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/arm/gen/herdtools_types_to_shallow_types.hgen b/arm/gen/herdtools_types_to_shallow_types.hgen
new file mode 100644
index 00000000..e14a37e3
--- /dev/null
+++ b/arm/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/arm/gen/lexer.hgen b/arm/gen/lexer.hgen
new file mode 100644
index 00000000..6ff24317
--- /dev/null
+++ b/arm/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/arm/gen/map.hgen b/arm/gen/map.hgen
new file mode 100644
index 00000000..62899c91
--- /dev/null
+++ b/arm/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/arm/gen/parser.hgen b/arm/gen/parser.hgen
new file mode 100644
index 00000000..94ce6fcf
--- /dev/null
+++ b/arm/gen/parser.hgen
@@ -0,0 +1,1396 @@
+ /* 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 `AArch64ConditionalSelect($2,W ZR,W ZR,Set32,$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 `AArch64ConditionalSelect($2,X ZR,X ZR,Set64,$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 wreg COMMA wreg
+ { if not (isregsp $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Wd|WSP>, <Wn|WSP>")
+ else `AArch64AddSubImmediate($2,$4,Set32,false,false,reg_size_bits_R32_of_int 0) }
+ | MOV xreg COMMA xreg
+ { if not (isregsp $2 && isregsp $4) then error_registers ("expected " ^ $1.txt ^ " <Xd|SP>, <Xn|SP>")
+ else `AArch64AddSubImmediate($2,$4,Set64,false,false,reg_size_bits_R64_of_int 0) }
+
+ /* 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}
+
+ /* MOV (register) alias of ORR (shifted register) */
+
+ | MOV wreg COMMA wreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Wd>, <Wm>")
+ else `AArch64LogicalShiftedRegister($2,W ZR,$4,Set32,false,LogicalOp_ORR,ShiftType_LSL,0,false) }
+ | MOV xreg COMMA xreg
+ { if not (isregzr $2 && isregzr $4) then error_registers ("expected " ^ $1.txt ^ " <Xd>, <Xm>")
+ else `AArch64LogicalShiftedRegister($2,X ZR,$4,Set64,false,LogicalOp_ORR,ShiftType_LSL,0,false) }
+
+ /* 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/arm/gen/pretty.hgen b/arm/gen/pretty.hgen
new file mode 100644
index 00000000..2bbf7af7
--- /dev/null
+++ b/arm/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/arm/gen/regs_out_in.hgen b/arm/gen/regs_out_in.hgen
new file mode 100644
index 00000000..724a574b
--- /dev/null
+++ b/arm/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/arm/gen/sail_trans_out.hgen b/arm/gen/sail_trans_out.hgen
new file mode 100644
index 00000000..9595f00c
--- /dev/null
+++ b/arm/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_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/arm/gen/shallow_ast_to_herdtools_ast.hgen b/arm/gen/shallow_ast_to_herdtools_ast.hgen
new file mode 100644
index 00000000..aa989e95
--- /dev/null
+++ b/arm/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_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)
+
+| Barrier2 (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/arm/gen/shallow_types_to_herdtools_types.hgen b/arm/gen/shallow_types_to_herdtools_types.hgen
new file mode 100644
index 00000000..771f52ac
--- /dev/null
+++ b/arm/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/arm/gen/token_types.hgen b/arm/gen/token_types.hgen
new file mode 100644
index 00000000..411dddf9
--- /dev/null
+++ b/arm/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/arm/gen/tokens.hgen b/arm/gen/tokens.hgen
new file mode 100644
index 00000000..bf49e463
--- /dev/null
+++ b/arm/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/arm/gen/trans_sail.hgen b/arm/gen/trans_sail.hgen
new file mode 100644
index 00000000..2b176308
--- /dev/null
+++ b/arm/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/arm/gen/types.hgen b/arm/gen/types.hgen
new file mode 100644
index 00000000..d581a233
--- /dev/null
+++ b/arm/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/arm/gen/types_sail_trans_out.hgen b/arm/gen/types_sail_trans_out.hgen
new file mode 100644
index 00000000..082a5464
--- /dev/null
+++ b/arm/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/arm/gen/types_trans_sail.hgen b/arm/gen/types_trans_sail.hgen
new file mode 100644
index 00000000..7f2d5fe7
--- /dev/null
+++ b/arm/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]