// Copyright 2013, ARM Limited // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * 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. // * Neither the name of ARM Limited nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. #ifndef VIXL_A64_CONSTANTS_A64_H_ #define VIXL_A64_CONSTANTS_A64_H_ namespace vixl { const unsigned kNumberOfRegisters = 32; const unsigned kNumberOfFPRegisters = 32; // Callee saved registers are x21-x30(lr). const int kNumberOfCalleeSavedRegisters = 10; const int kFirstCalleeSavedRegisterIndex = 21; // Callee saved FP registers are d8-d15. const int kNumberOfCalleeSavedFPRegisters = 8; const int kFirstCalleeSavedFPRegisterIndex = 8; #define REGISTER_CODE_LIST(R) \ R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) #define INSTRUCTION_FIELDS_LIST(V_) \ /* Register fields */ \ V_(Rd, 4, 0, Bits) /* Destination register. */ \ V_(Rn, 9, 5, Bits) /* First source register. */ \ V_(Rm, 20, 16, Bits) /* Second source register. */ \ V_(Ra, 14, 10, Bits) /* Third source register. */ \ V_(Rt, 4, 0, Bits) /* Load dest / store source. */ \ V_(Rt2, 14, 10, Bits) /* Load second dest / */ \ /* store second source. */ \ V_(PrefetchMode, 4, 0, Bits) \ \ /* Common bits */ \ V_(SixtyFourBits, 31, 31, Bits) \ V_(FlagsUpdate, 29, 29, Bits) \ \ /* PC relative addressing */ \ V_(ImmPCRelHi, 23, 5, SignedBits) \ V_(ImmPCRelLo, 30, 29, Bits) \ \ /* Add/subtract/logical shift register */ \ V_(ShiftDP, 23, 22, Bits) \ V_(ImmDPShift, 15, 10, Bits) \ \ /* Add/subtract immediate */ \ V_(ImmAddSub, 21, 10, Bits) \ V_(ShiftAddSub, 23, 22, Bits) \ \ /* Add/substract extend */ \ V_(ImmExtendShift, 12, 10, Bits) \ V_(ExtendMode, 15, 13, Bits) \ \ /* Move wide */ \ V_(ImmMoveWide, 20, 5, Bits) \ V_(ShiftMoveWide, 22, 21, Bits) \ \ /* Logical immediate, bitfield and extract */ \ V_(BitN, 22, 22, Bits) \ V_(ImmRotate, 21, 16, Bits) \ V_(ImmSetBits, 15, 10, Bits) \ V_(ImmR, 21, 16, Bits) \ V_(ImmS, 15, 10, Bits) \ \ /* Test and branch immediate */ \ V_(ImmTestBranch, 18, 5, SignedBits) \ V_(ImmTestBranchBit40, 23, 19, Bits) \ V_(ImmTestBranchBit5, 31, 31, Bits) \ \ /* Conditionals */ \ V_(Condition, 15, 12, Bits) \ V_(ConditionBranch, 3, 0, Bits) \ V_(Nzcv, 3, 0, Bits) \ V_(ImmCondCmp, 20, 16, Bits) \ V_(ImmCondBranch, 23, 5, SignedBits) \ \ /* Floating point */ \ V_(FPType, 23, 22, Bits) \ V_(ImmFP, 20, 13, Bits) \ V_(FPScale, 15, 10, Bits) \ \ /* Load Store */ \ V_(ImmLS, 20, 12, SignedBits) \ V_(ImmLSUnsigned, 21, 10, Bits) \ V_(ImmLSPair, 21, 15, SignedBits) \ V_(SizeLS, 31, 30, Bits) \ V_(ImmShiftLS, 12, 12, Bits) \ \ /* Other immediates */ \ V_(ImmUncondBranch, 25, 0, SignedBits) \ V_(ImmCmpBranch, 23, 5, SignedBits) \ V_(ImmLLiteral, 23, 5, SignedBits) \ V_(ImmException, 20, 5, Bits) \ V_(ImmHint, 11, 5, Bits) \ V_(ImmBarrierDomain, 11, 10, Bits) \ V_(ImmBarrierType, 9, 8, Bits) \ \ /* System (MRS, MSR) */ \ V_(ImmSystemRegister, 19, 5, Bits) \ V_(SysO0, 19, 19, Bits) \ V_(SysOp1, 18, 16, Bits) \ V_(SysOp2, 7, 5, Bits) \ V_(CRn, 15, 12, Bits) \ V_(CRm, 11, 8, Bits) \ #define SYSTEM_REGISTER_FIELDS_LIST(V_, M_) \ /* NZCV */ \ V_(Flags, 31, 28, Bits) \ V_(N, 31, 31, Bits) \ V_(Z, 30, 30, Bits) \ V_(C, 29, 29, Bits) \ V_(V, 28, 28, Bits) \ M_(NZCV, Flags_mask) \ \ /* FPCR */ \ V_(AHP, 26, 26, Bits) \ V_(DN, 25, 25, Bits) \ V_(FZ, 24, 24, Bits) \ V_(RMode, 23, 22, Bits) \ M_(FPCR, AHP_mask | DN_mask | FZ_mask | RMode_mask) // Fields offsets. #define DECLARE_FIELDS_OFFSETS(Name, HighBit, LowBit, X) \ const int Name##_offset = LowBit; \ const int Name##_width = HighBit - LowBit + 1; \ const uint32_t Name##_mask = ((1 << Name##_width) - 1) << LowBit; #define NOTHING(A, B) INSTRUCTION_FIELDS_LIST(DECLARE_FIELDS_OFFSETS) SYSTEM_REGISTER_FIELDS_LIST(DECLARE_FIELDS_OFFSETS, NOTHING) #undef NOTHING #undef DECLARE_FIELDS_BITS // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), formed // from ImmPCRelLo and ImmPCRelHi. const int ImmPCRel_mask = ImmPCRelLo_mask | ImmPCRelHi_mask; // Condition codes. enum Condition { eq = 0, ne = 1, hs = 2, lo = 3, mi = 4, pl = 5, vs = 6, vc = 7, hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14, nv = 15 // Behaves as always/al. }; inline Condition InvertCondition(Condition cond) { // Conditions al and nv behave identically, as "always true". They can't be // inverted, because there is no "always false" condition. VIXL_ASSERT((cond != al) && (cond != nv)); return static_cast<Condition>(cond ^ 1); } enum FlagsUpdate { SetFlags = 1, LeaveFlags = 0 }; enum StatusFlags { NoFlag = 0, // Derive the flag combinations from the system register bit descriptions. NFlag = N_mask, ZFlag = Z_mask, CFlag = C_mask, VFlag = V_mask, NZFlag = NFlag | ZFlag, NCFlag = NFlag | CFlag, NVFlag = NFlag | VFlag, ZCFlag = ZFlag | CFlag, ZVFlag = ZFlag | VFlag, CVFlag = CFlag | VFlag, NZCFlag = NFlag | ZFlag | CFlag, NZVFlag = NFlag | ZFlag | VFlag, NCVFlag = NFlag | CFlag | VFlag, ZCVFlag = ZFlag | CFlag | VFlag, NZCVFlag = NFlag | ZFlag | CFlag | VFlag, // Floating-point comparison results. FPEqualFlag = ZCFlag, FPLessThanFlag = NFlag, FPGreaterThanFlag = CFlag, FPUnorderedFlag = CVFlag }; enum Shift { NO_SHIFT = -1, LSL = 0x0, LSR = 0x1, ASR = 0x2, ROR = 0x3 }; enum Extend { NO_EXTEND = -1, UXTB = 0, UXTH = 1, UXTW = 2, UXTX = 3, SXTB = 4, SXTH = 5, SXTW = 6, SXTX = 7 }; enum SystemHint { NOP = 0, YIELD = 1, WFE = 2, WFI = 3, SEV = 4, SEVL = 5 }; enum BarrierDomain { OuterShareable = 0, NonShareable = 1, InnerShareable = 2, FullSystem = 3 }; enum BarrierType { BarrierOther = 0, BarrierReads = 1, BarrierWrites = 2, BarrierAll = 3 }; // System/special register names. // This information is not encoded as one field but as the concatenation of // multiple fields (Op0<0>, Op1, Crn, Crm, Op2). enum SystemRegister { NZCV = ((0x1 << SysO0_offset) | (0x3 << SysOp1_offset) | (0x4 << CRn_offset) | (0x2 << CRm_offset) | (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset, FPCR = ((0x1 << SysO0_offset) | (0x3 << SysOp1_offset) | (0x4 << CRn_offset) | (0x4 << CRm_offset) | (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset }; // Instruction enumerations. // // These are the masks that define a class of instructions, and the list of // instructions within each class. Each enumeration has a Fixed, FMask and // Mask value. // // Fixed: The fixed bits in this instruction class. // FMask: The mask used to extract the fixed bits in the class. // Mask: The mask used to identify the instructions within a class. // // The enumerations can be used like this: // // VIXL_ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed); // switch(instr->Mask(PCRelAddressingMask)) { // case ADR: Format("adr 'Xd, 'AddrPCRelByte"); break; // case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break; // default: printf("Unknown instruction\n"); // } // Generic fields. enum GenericInstrField { SixtyFourBits = 0x80000000, ThirtyTwoBits = 0x00000000, FP32 = 0x00000000, FP64 = 0x00400000 }; // PC relative addressing. enum PCRelAddressingOp { PCRelAddressingFixed = 0x10000000, PCRelAddressingFMask = 0x1F000000, PCRelAddressingMask = 0x9F000000, ADR = PCRelAddressingFixed | 0x00000000, ADRP = PCRelAddressingFixed | 0x80000000 }; // Add/sub (immediate, shifted and extended.) const int kSFOffset = 31; enum AddSubOp { AddSubOpMask = 0x60000000, AddSubSetFlagsBit = 0x20000000, ADD = 0x00000000, ADDS = ADD | AddSubSetFlagsBit, SUB = 0x40000000, SUBS = SUB | AddSubSetFlagsBit }; #define ADD_SUB_OP_LIST(V) \ V(ADD), \ V(ADDS), \ V(SUB), \ V(SUBS) enum AddSubImmediateOp { AddSubImmediateFixed = 0x11000000, AddSubImmediateFMask = 0x1F000000, AddSubImmediateMask = 0xFF000000, #define ADD_SUB_IMMEDIATE(A) \ A##_w_imm = AddSubImmediateFixed | A, \ A##_x_imm = AddSubImmediateFixed | A | SixtyFourBits ADD_SUB_OP_LIST(ADD_SUB_IMMEDIATE) #undef ADD_SUB_IMMEDIATE }; enum AddSubShiftedOp { AddSubShiftedFixed = 0x0B000000, AddSubShiftedFMask = 0x1F200000, AddSubShiftedMask = 0xFF200000, #define ADD_SUB_SHIFTED(A) \ A##_w_shift = AddSubShiftedFixed | A, \ A##_x_shift = AddSubShiftedFixed | A | SixtyFourBits ADD_SUB_OP_LIST(ADD_SUB_SHIFTED) #undef ADD_SUB_SHIFTED }; enum AddSubExtendedOp { AddSubExtendedFixed = 0x0B200000, AddSubExtendedFMask = 0x1F200000, AddSubExtendedMask = 0xFFE00000, #define ADD_SUB_EXTENDED(A) \ A##_w_ext = AddSubExtendedFixed | A, \ A##_x_ext = AddSubExtendedFixed | A | SixtyFourBits ADD_SUB_OP_LIST(ADD_SUB_EXTENDED) #undef ADD_SUB_EXTENDED }; // Add/sub with carry. enum AddSubWithCarryOp { AddSubWithCarryFixed = 0x1A000000, AddSubWithCarryFMask = 0x1FE00000, AddSubWithCarryMask = 0xFFE0FC00, ADC_w = AddSubWithCarryFixed | ADD, ADC_x = AddSubWithCarryFixed | ADD | SixtyFourBits, ADC = ADC_w, ADCS_w = AddSubWithCarryFixed | ADDS, ADCS_x = AddSubWithCarryFixed | ADDS | SixtyFourBits, SBC_w = AddSubWithCarryFixed | SUB, SBC_x = AddSubWithCarryFixed | SUB | SixtyFourBits, SBC = SBC_w, SBCS_w = AddSubWithCarryFixed | SUBS, SBCS_x = AddSubWithCarryFixed | SUBS | SixtyFourBits }; // Logical (immediate and shifted register). enum LogicalOp { LogicalOpMask = 0x60200000, NOT = 0x00200000, AND = 0x00000000, BIC = AND | NOT, ORR = 0x20000000, ORN = ORR | NOT, EOR = 0x40000000, EON = EOR | NOT, ANDS = 0x60000000, BICS = ANDS | NOT }; // Logical immediate. enum LogicalImmediateOp { LogicalImmediateFixed = 0x12000000, LogicalImmediateFMask = 0x1F800000, LogicalImmediateMask = 0xFF800000, AND_w_imm = LogicalImmediateFixed | AND, AND_x_imm = LogicalImmediateFixed | AND | SixtyFourBits, ORR_w_imm = LogicalImmediateFixed | ORR, ORR_x_imm = LogicalImmediateFixed | ORR | SixtyFourBits, EOR_w_imm = LogicalImmediateFixed | EOR, EOR_x_imm = LogicalImmediateFixed | EOR | SixtyFourBits, ANDS_w_imm = LogicalImmediateFixed | ANDS, ANDS_x_imm = LogicalImmediateFixed | ANDS | SixtyFourBits }; // Logical shifted register. enum LogicalShiftedOp { LogicalShiftedFixed = 0x0A000000, LogicalShiftedFMask = 0x1F000000, LogicalShiftedMask = 0xFF200000, AND_w = LogicalShiftedFixed | AND, AND_x = LogicalShiftedFixed | AND | SixtyFourBits, AND_shift = AND_w, BIC_w = LogicalShiftedFixed | BIC, BIC_x = LogicalShiftedFixed | BIC | SixtyFourBits, BIC_shift = BIC_w, ORR_w = LogicalShiftedFixed | ORR, ORR_x = LogicalShiftedFixed | ORR | SixtyFourBits, ORR_shift = ORR_w, ORN_w = LogicalShiftedFixed | ORN, ORN_x = LogicalShiftedFixed | ORN | SixtyFourBits, ORN_shift = ORN_w, EOR_w = LogicalShiftedFixed | EOR, EOR_x = LogicalShiftedFixed | EOR | SixtyFourBits, EOR_shift = EOR_w, EON_w = LogicalShiftedFixed | EON, EON_x = LogicalShiftedFixed | EON | SixtyFourBits, EON_shift = EON_w, ANDS_w = LogicalShiftedFixed | ANDS, ANDS_x = LogicalShiftedFixed | ANDS | SixtyFourBits, ANDS_shift = ANDS_w, BICS_w = LogicalShiftedFixed | BICS, BICS_x = LogicalShiftedFixed | BICS | SixtyFourBits, BICS_shift = BICS_w }; // Move wide immediate. enum MoveWideImmediateOp { MoveWideImmediateFixed = 0x12800000, MoveWideImmediateFMask = 0x1F800000, MoveWideImmediateMask = 0xFF800000, MOVN = 0x00000000, MOVZ = 0x40000000, MOVK = 0x60000000, MOVN_w = MoveWideImmediateFixed | MOVN, MOVN_x = MoveWideImmediateFixed | MOVN | SixtyFourBits, MOVZ_w = MoveWideImmediateFixed | MOVZ, MOVZ_x = MoveWideImmediateFixed | MOVZ | SixtyFourBits, MOVK_w = MoveWideImmediateFixed | MOVK, MOVK_x = MoveWideImmediateFixed | MOVK | SixtyFourBits }; // Bitfield. const int kBitfieldNOffset = 22; enum BitfieldOp { BitfieldFixed = 0x13000000, BitfieldFMask = 0x1F800000, BitfieldMask = 0xFF800000, SBFM_w = BitfieldFixed | 0x00000000, SBFM_x = BitfieldFixed | 0x80000000, SBFM = SBFM_w, BFM_w = BitfieldFixed | 0x20000000, BFM_x = BitfieldFixed | 0xA0000000, BFM = BFM_w, UBFM_w = BitfieldFixed | 0x40000000, UBFM_x = BitfieldFixed | 0xC0000000, UBFM = UBFM_w // Bitfield N field. }; // Extract. enum ExtractOp { ExtractFixed = 0x13800000, ExtractFMask = 0x1F800000, ExtractMask = 0xFFA00000, EXTR_w = ExtractFixed | 0x00000000, EXTR_x = ExtractFixed | 0x80000000, EXTR = EXTR_w }; // Unconditional branch. enum UnconditionalBranchOp { UnconditionalBranchFixed = 0x14000000, UnconditionalBranchFMask = 0x7C000000, UnconditionalBranchMask = 0xFC000000, B = UnconditionalBranchFixed | 0x00000000, BL = UnconditionalBranchFixed | 0x80000000 }; // Unconditional branch to register. enum UnconditionalBranchToRegisterOp { UnconditionalBranchToRegisterFixed = 0xD6000000, UnconditionalBranchToRegisterFMask = 0xFE000000, UnconditionalBranchToRegisterMask = 0xFFFFFC1F, BR = UnconditionalBranchToRegisterFixed | 0x001F0000, BLR = UnconditionalBranchToRegisterFixed | 0x003F0000, RET = UnconditionalBranchToRegisterFixed | 0x005F0000 }; // Compare and branch. enum CompareBranchOp { CompareBranchFixed = 0x34000000, CompareBranchFMask = 0x7E000000, CompareBranchMask = 0xFF000000, CBZ_w = CompareBranchFixed | 0x00000000, CBZ_x = CompareBranchFixed | 0x80000000, CBZ = CBZ_w, CBNZ_w = CompareBranchFixed | 0x01000000, CBNZ_x = CompareBranchFixed | 0x81000000, CBNZ = CBNZ_w }; // Test and branch. enum TestBranchOp { TestBranchFixed = 0x36000000, TestBranchFMask = 0x7E000000, TestBranchMask = 0x7F000000, TBZ = TestBranchFixed | 0x00000000, TBNZ = TestBranchFixed | 0x01000000 }; // Conditional branch. enum ConditionalBranchOp { ConditionalBranchFixed = 0x54000000, ConditionalBranchFMask = 0xFE000000, ConditionalBranchMask = 0xFF000010, B_cond = ConditionalBranchFixed | 0x00000000 }; // System. // System instruction encoding is complicated because some instructions use op // and CR fields to encode parameters. To handle this cleanly, the system // instructions are split into more than one enum. enum SystemOp { SystemFixed = 0xD5000000, SystemFMask = 0xFFC00000 }; enum SystemSysRegOp { SystemSysRegFixed = 0xD5100000, SystemSysRegFMask = 0xFFD00000, SystemSysRegMask = 0xFFF00000, MRS = SystemSysRegFixed | 0x00200000, MSR = SystemSysRegFixed | 0x00000000 }; enum SystemHintOp { SystemHintFixed = 0xD503201F, SystemHintFMask = 0xFFFFF01F, SystemHintMask = 0xFFFFF01F, HINT = SystemHintFixed | 0x00000000 }; // Exception. enum ExceptionOp { ExceptionFixed = 0xD4000000, ExceptionFMask = 0xFF000000, ExceptionMask = 0xFFE0001F, HLT = ExceptionFixed | 0x00400000, BRK = ExceptionFixed | 0x00200000, SVC = ExceptionFixed | 0x00000001, HVC = ExceptionFixed | 0x00000002, SMC = ExceptionFixed | 0x00000003, DCPS1 = ExceptionFixed | 0x00A00001, DCPS2 = ExceptionFixed | 0x00A00002, DCPS3 = ExceptionFixed | 0x00A00003 }; enum MemBarrierOp { MemBarrierFixed = 0xD503309F, MemBarrierFMask = 0xFFFFF09F, MemBarrierMask = 0xFFFFF0FF, DSB = MemBarrierFixed | 0x00000000, DMB = MemBarrierFixed | 0x00000020, ISB = MemBarrierFixed | 0x00000040 }; // Any load or store. enum LoadStoreAnyOp { LoadStoreAnyFMask = 0x0a000000, LoadStoreAnyFixed = 0x08000000 }; #define LOAD_STORE_PAIR_OP_LIST(V) \ V(STP, w, 0x00000000), \ V(LDP, w, 0x00400000), \ V(LDPSW, x, 0x40400000), \ V(STP, x, 0x80000000), \ V(LDP, x, 0x80400000), \ V(STP, s, 0x04000000), \ V(LDP, s, 0x04400000), \ V(STP, d, 0x44000000), \ V(LDP, d, 0x44400000) // Load/store pair (post, pre and offset.) enum LoadStorePairOp { LoadStorePairMask = 0xC4400000, LoadStorePairLBit = 1 << 22, #define LOAD_STORE_PAIR(A, B, C) \ A##_##B = C LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR) #undef LOAD_STORE_PAIR }; enum LoadStorePairPostIndexOp { LoadStorePairPostIndexFixed = 0x28800000, LoadStorePairPostIndexFMask = 0x3B800000, LoadStorePairPostIndexMask = 0xFFC00000, #define LOAD_STORE_PAIR_POST_INDEX(A, B, C) \ A##_##B##_post = LoadStorePairPostIndexFixed | A##_##B LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_POST_INDEX) #undef LOAD_STORE_PAIR_POST_INDEX }; enum LoadStorePairPreIndexOp { LoadStorePairPreIndexFixed = 0x29800000, LoadStorePairPreIndexFMask = 0x3B800000, LoadStorePairPreIndexMask = 0xFFC00000, #define LOAD_STORE_PAIR_PRE_INDEX(A, B, C) \ A##_##B##_pre = LoadStorePairPreIndexFixed | A##_##B LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_PRE_INDEX) #undef LOAD_STORE_PAIR_PRE_INDEX }; enum LoadStorePairOffsetOp { LoadStorePairOffsetFixed = 0x29000000, LoadStorePairOffsetFMask = 0x3B800000, LoadStorePairOffsetMask = 0xFFC00000, #define LOAD_STORE_PAIR_OFFSET(A, B, C) \ A##_##B##_off = LoadStorePairOffsetFixed | A##_##B LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_OFFSET) #undef LOAD_STORE_PAIR_OFFSET }; enum LoadStorePairNonTemporalOp { LoadStorePairNonTemporalFixed = 0x28000000, LoadStorePairNonTemporalFMask = 0x3B800000, LoadStorePairNonTemporalMask = 0xFFC00000, STNP_w = LoadStorePairNonTemporalFixed | STP_w, LDNP_w = LoadStorePairNonTemporalFixed | LDP_w, STNP_x = LoadStorePairNonTemporalFixed | STP_x, LDNP_x = LoadStorePairNonTemporalFixed | LDP_x, STNP_s = LoadStorePairNonTemporalFixed | STP_s, LDNP_s = LoadStorePairNonTemporalFixed | LDP_s, STNP_d = LoadStorePairNonTemporalFixed | STP_d, LDNP_d = LoadStorePairNonTemporalFixed | LDP_d }; // Load literal. enum LoadLiteralOp { LoadLiteralFixed = 0x18000000, LoadLiteralFMask = 0x3B000000, LoadLiteralMask = 0xFF000000, LDR_w_lit = LoadLiteralFixed | 0x00000000, LDR_x_lit = LoadLiteralFixed | 0x40000000, LDRSW_x_lit = LoadLiteralFixed | 0x80000000, PRFM_lit = LoadLiteralFixed | 0xC0000000, LDR_s_lit = LoadLiteralFixed | 0x04000000, LDR_d_lit = LoadLiteralFixed | 0x44000000 }; #define LOAD_STORE_OP_LIST(V) \ V(ST, RB, w, 0x00000000), \ V(ST, RH, w, 0x40000000), \ V(ST, R, w, 0x80000000), \ V(ST, R, x, 0xC0000000), \ V(LD, RB, w, 0x00400000), \ V(LD, RH, w, 0x40400000), \ V(LD, R, w, 0x80400000), \ V(LD, R, x, 0xC0400000), \ V(LD, RSB, x, 0x00800000), \ V(LD, RSH, x, 0x40800000), \ V(LD, RSW, x, 0x80800000), \ V(LD, RSB, w, 0x00C00000), \ V(LD, RSH, w, 0x40C00000), \ V(ST, R, s, 0x84000000), \ V(ST, R, d, 0xC4000000), \ V(LD, R, s, 0x84400000), \ V(LD, R, d, 0xC4400000) // Load/store unscaled offset. enum LoadStoreUnscaledOffsetOp { LoadStoreUnscaledOffsetFixed = 0x38000000, LoadStoreUnscaledOffsetFMask = 0x3B200C00, LoadStoreUnscaledOffsetMask = 0xFFE00C00, #define LOAD_STORE_UNSCALED(A, B, C, D) \ A##U##B##_##C = LoadStoreUnscaledOffsetFixed | D LOAD_STORE_OP_LIST(LOAD_STORE_UNSCALED) #undef LOAD_STORE_UNSCALED }; // Load/store (post, pre, offset and unsigned.) enum LoadStoreOp { LoadStoreOpMask = 0xC4C00000, #define LOAD_STORE(A, B, C, D) \ A##B##_##C = D LOAD_STORE_OP_LIST(LOAD_STORE), #undef LOAD_STORE PRFM = 0xC0800000 }; // Load/store post index. enum LoadStorePostIndex { LoadStorePostIndexFixed = 0x38000400, LoadStorePostIndexFMask = 0x3B200C00, LoadStorePostIndexMask = 0xFFE00C00, #define LOAD_STORE_POST_INDEX(A, B, C, D) \ A##B##_##C##_post = LoadStorePostIndexFixed | D LOAD_STORE_OP_LIST(LOAD_STORE_POST_INDEX) #undef LOAD_STORE_POST_INDEX }; // Load/store pre index. enum LoadStorePreIndex { LoadStorePreIndexFixed = 0x38000C00, LoadStorePreIndexFMask = 0x3B200C00, LoadStorePreIndexMask = 0xFFE00C00, #define LOAD_STORE_PRE_INDEX(A, B, C, D) \ A##B##_##C##_pre = LoadStorePreIndexFixed | D LOAD_STORE_OP_LIST(LOAD_STORE_PRE_INDEX) #undef LOAD_STORE_PRE_INDEX }; // Load/store unsigned offset. enum LoadStoreUnsignedOffset { LoadStoreUnsignedOffsetFixed = 0x39000000, LoadStoreUnsignedOffsetFMask = 0x3B000000, LoadStoreUnsignedOffsetMask = 0xFFC00000, PRFM_unsigned = LoadStoreUnsignedOffsetFixed | PRFM, #define LOAD_STORE_UNSIGNED_OFFSET(A, B, C, D) \ A##B##_##C##_unsigned = LoadStoreUnsignedOffsetFixed | D LOAD_STORE_OP_LIST(LOAD_STORE_UNSIGNED_OFFSET) #undef LOAD_STORE_UNSIGNED_OFFSET }; // Load/store register offset. enum LoadStoreRegisterOffset { LoadStoreRegisterOffsetFixed = 0x38200800, LoadStoreRegisterOffsetFMask = 0x3B200C00, LoadStoreRegisterOffsetMask = 0xFFE00C00, PRFM_reg = LoadStoreRegisterOffsetFixed | PRFM, #define LOAD_STORE_REGISTER_OFFSET(A, B, C, D) \ A##B##_##C##_reg = LoadStoreRegisterOffsetFixed | D LOAD_STORE_OP_LIST(LOAD_STORE_REGISTER_OFFSET) #undef LOAD_STORE_REGISTER_OFFSET }; // Conditional compare. enum ConditionalCompareOp { ConditionalCompareMask = 0x60000000, CCMN = 0x20000000, CCMP = 0x60000000 }; // Conditional compare register. enum ConditionalCompareRegisterOp { ConditionalCompareRegisterFixed = 0x1A400000, ConditionalCompareRegisterFMask = 0x1FE00800, ConditionalCompareRegisterMask = 0xFFE00C10, CCMN_w = ConditionalCompareRegisterFixed | CCMN, CCMN_x = ConditionalCompareRegisterFixed | SixtyFourBits | CCMN, CCMP_w = ConditionalCompareRegisterFixed | CCMP, CCMP_x = ConditionalCompareRegisterFixed | SixtyFourBits | CCMP }; // Conditional compare immediate. enum ConditionalCompareImmediateOp { ConditionalCompareImmediateFixed = 0x1A400800, ConditionalCompareImmediateFMask = 0x1FE00800, ConditionalCompareImmediateMask = 0xFFE00C10, CCMN_w_imm = ConditionalCompareImmediateFixed | CCMN, CCMN_x_imm = ConditionalCompareImmediateFixed | SixtyFourBits | CCMN, CCMP_w_imm = ConditionalCompareImmediateFixed | CCMP, CCMP_x_imm = ConditionalCompareImmediateFixed | SixtyFourBits | CCMP }; // Conditional select. enum ConditionalSelectOp { ConditionalSelectFixed = 0x1A800000, ConditionalSelectFMask = 0x1FE00000, ConditionalSelectMask = 0xFFE00C00, CSEL_w = ConditionalSelectFixed | 0x00000000, CSEL_x = ConditionalSelectFixed | 0x80000000, CSEL = CSEL_w, CSINC_w = ConditionalSelectFixed | 0x00000400, CSINC_x = ConditionalSelectFixed | 0x80000400, CSINC = CSINC_w, CSINV_w = ConditionalSelectFixed | 0x40000000, CSINV_x = ConditionalSelectFixed | 0xC0000000, CSINV = CSINV_w, CSNEG_w = ConditionalSelectFixed | 0x40000400, CSNEG_x = ConditionalSelectFixed | 0xC0000400, CSNEG = CSNEG_w }; // Data processing 1 source. enum DataProcessing1SourceOp { DataProcessing1SourceFixed = 0x5AC00000, DataProcessing1SourceFMask = 0x5FE00000, DataProcessing1SourceMask = 0xFFFFFC00, RBIT = DataProcessing1SourceFixed | 0x00000000, RBIT_w = RBIT, RBIT_x = RBIT | SixtyFourBits, REV16 = DataProcessing1SourceFixed | 0x00000400, REV16_w = REV16, REV16_x = REV16 | SixtyFourBits, REV = DataProcessing1SourceFixed | 0x00000800, REV_w = REV, REV32_x = REV | SixtyFourBits, REV_x = DataProcessing1SourceFixed | SixtyFourBits | 0x00000C00, CLZ = DataProcessing1SourceFixed | 0x00001000, CLZ_w = CLZ, CLZ_x = CLZ | SixtyFourBits, CLS = DataProcessing1SourceFixed | 0x00001400, CLS_w = CLS, CLS_x = CLS | SixtyFourBits }; // Data processing 2 source. enum DataProcessing2SourceOp { DataProcessing2SourceFixed = 0x1AC00000, DataProcessing2SourceFMask = 0x5FE00000, DataProcessing2SourceMask = 0xFFE0FC00, UDIV_w = DataProcessing2SourceFixed | 0x00000800, UDIV_x = DataProcessing2SourceFixed | 0x80000800, UDIV = UDIV_w, SDIV_w = DataProcessing2SourceFixed | 0x00000C00, SDIV_x = DataProcessing2SourceFixed | 0x80000C00, SDIV = SDIV_w, LSLV_w = DataProcessing2SourceFixed | 0x00002000, LSLV_x = DataProcessing2SourceFixed | 0x80002000, LSLV = LSLV_w, LSRV_w = DataProcessing2SourceFixed | 0x00002400, LSRV_x = DataProcessing2SourceFixed | 0x80002400, LSRV = LSRV_w, ASRV_w = DataProcessing2SourceFixed | 0x00002800, ASRV_x = DataProcessing2SourceFixed | 0x80002800, ASRV = ASRV_w, RORV_w = DataProcessing2SourceFixed | 0x00002C00, RORV_x = DataProcessing2SourceFixed | 0x80002C00, RORV = RORV_w, CRC32B = DataProcessing2SourceFixed | 0x00004000, CRC32H = DataProcessing2SourceFixed | 0x00004400, CRC32W = DataProcessing2SourceFixed | 0x00004800, CRC32X = DataProcessing2SourceFixed | SixtyFourBits | 0x00004C00, CRC32CB = DataProcessing2SourceFixed | 0x00005000, CRC32CH = DataProcessing2SourceFixed | 0x00005400, CRC32CW = DataProcessing2SourceFixed | 0x00005800, CRC32CX = DataProcessing2SourceFixed | SixtyFourBits | 0x00005C00 }; // Data processing 3 source. enum DataProcessing3SourceOp { DataProcessing3SourceFixed = 0x1B000000, DataProcessing3SourceFMask = 0x1F000000, DataProcessing3SourceMask = 0xFFE08000, MADD_w = DataProcessing3SourceFixed | 0x00000000, MADD_x = DataProcessing3SourceFixed | 0x80000000, MADD = MADD_w, MSUB_w = DataProcessing3SourceFixed | 0x00008000, MSUB_x = DataProcessing3SourceFixed | 0x80008000, MSUB = MSUB_w, SMADDL_x = DataProcessing3SourceFixed | 0x80200000, SMSUBL_x = DataProcessing3SourceFixed | 0x80208000, SMULH_x = DataProcessing3SourceFixed | 0x80400000, UMADDL_x = DataProcessing3SourceFixed | 0x80A00000, UMSUBL_x = DataProcessing3SourceFixed | 0x80A08000, UMULH_x = DataProcessing3SourceFixed | 0x80C00000 }; // Floating point compare. enum FPCompareOp { FPCompareFixed = 0x1E202000, FPCompareFMask = 0x5F203C00, FPCompareMask = 0xFFE0FC1F, FCMP_s = FPCompareFixed | 0x00000000, FCMP_d = FPCompareFixed | FP64 | 0x00000000, FCMP = FCMP_s, FCMP_s_zero = FPCompareFixed | 0x00000008, FCMP_d_zero = FPCompareFixed | FP64 | 0x00000008, FCMP_zero = FCMP_s_zero, FCMPE_s = FPCompareFixed | 0x00000010, FCMPE_d = FPCompareFixed | FP64 | 0x00000010, FCMPE_s_zero = FPCompareFixed | 0x00000018, FCMPE_d_zero = FPCompareFixed | FP64 | 0x00000018 }; // Floating point conditional compare. enum FPConditionalCompareOp { FPConditionalCompareFixed = 0x1E200400, FPConditionalCompareFMask = 0x5F200C00, FPConditionalCompareMask = 0xFFE00C10, FCCMP_s = FPConditionalCompareFixed | 0x00000000, FCCMP_d = FPConditionalCompareFixed | FP64 | 0x00000000, FCCMP = FCCMP_s, FCCMPE_s = FPConditionalCompareFixed | 0x00000010, FCCMPE_d = FPConditionalCompareFixed | FP64 | 0x00000010, FCCMPE = FCCMPE_s }; // Floating point conditional select. enum FPConditionalSelectOp { FPConditionalSelectFixed = 0x1E200C00, FPConditionalSelectFMask = 0x5F200C00, FPConditionalSelectMask = 0xFFE00C00, FCSEL_s = FPConditionalSelectFixed | 0x00000000, FCSEL_d = FPConditionalSelectFixed | FP64 | 0x00000000, FCSEL = FCSEL_s }; // Floating point immediate. enum FPImmediateOp { FPImmediateFixed = 0x1E201000, FPImmediateFMask = 0x5F201C00, FPImmediateMask = 0xFFE01C00, FMOV_s_imm = FPImmediateFixed | 0x00000000, FMOV_d_imm = FPImmediateFixed | FP64 | 0x00000000 }; // Floating point data processing 1 source. enum FPDataProcessing1SourceOp { FPDataProcessing1SourceFixed = 0x1E204000, FPDataProcessing1SourceFMask = 0x5F207C00, FPDataProcessing1SourceMask = 0xFFFFFC00, FMOV_s = FPDataProcessing1SourceFixed | 0x00000000, FMOV_d = FPDataProcessing1SourceFixed | FP64 | 0x00000000, FMOV = FMOV_s, FABS_s = FPDataProcessing1SourceFixed | 0x00008000, FABS_d = FPDataProcessing1SourceFixed | FP64 | 0x00008000, FABS = FABS_s, FNEG_s = FPDataProcessing1SourceFixed | 0x00010000, FNEG_d = FPDataProcessing1SourceFixed | FP64 | 0x00010000, FNEG = FNEG_s, FSQRT_s = FPDataProcessing1SourceFixed | 0x00018000, FSQRT_d = FPDataProcessing1SourceFixed | FP64 | 0x00018000, FSQRT = FSQRT_s, FCVT_ds = FPDataProcessing1SourceFixed | 0x00028000, FCVT_sd = FPDataProcessing1SourceFixed | FP64 | 0x00020000, FRINTN_s = FPDataProcessing1SourceFixed | 0x00040000, FRINTN_d = FPDataProcessing1SourceFixed | FP64 | 0x00040000, FRINTN = FRINTN_s, FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000, FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000, FRINTP = FRINTP_s, FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000, FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000, FRINTM = FRINTM_s, FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000, FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000, FRINTZ = FRINTZ_s, FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000, FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000, FRINTA = FRINTA_s, FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000, FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000, FRINTX = FRINTX_s, FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000, FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000, FRINTI = FRINTI_s }; // Floating point data processing 2 source. enum FPDataProcessing2SourceOp { FPDataProcessing2SourceFixed = 0x1E200800, FPDataProcessing2SourceFMask = 0x5F200C00, FPDataProcessing2SourceMask = 0xFFE0FC00, FMUL = FPDataProcessing2SourceFixed | 0x00000000, FMUL_s = FMUL, FMUL_d = FMUL | FP64, FDIV = FPDataProcessing2SourceFixed | 0x00001000, FDIV_s = FDIV, FDIV_d = FDIV | FP64, FADD = FPDataProcessing2SourceFixed | 0x00002000, FADD_s = FADD, FADD_d = FADD | FP64, FSUB = FPDataProcessing2SourceFixed | 0x00003000, FSUB_s = FSUB, FSUB_d = FSUB | FP64, FMAX = FPDataProcessing2SourceFixed | 0x00004000, FMAX_s = FMAX, FMAX_d = FMAX | FP64, FMIN = FPDataProcessing2SourceFixed | 0x00005000, FMIN_s = FMIN, FMIN_d = FMIN | FP64, FMAXNM = FPDataProcessing2SourceFixed | 0x00006000, FMAXNM_s = FMAXNM, FMAXNM_d = FMAXNM | FP64, FMINNM = FPDataProcessing2SourceFixed | 0x00007000, FMINNM_s = FMINNM, FMINNM_d = FMINNM | FP64, FNMUL = FPDataProcessing2SourceFixed | 0x00008000, FNMUL_s = FNMUL, FNMUL_d = FNMUL | FP64 }; // Floating point data processing 3 source. enum FPDataProcessing3SourceOp { FPDataProcessing3SourceFixed = 0x1F000000, FPDataProcessing3SourceFMask = 0x5F000000, FPDataProcessing3SourceMask = 0xFFE08000, FMADD_s = FPDataProcessing3SourceFixed | 0x00000000, FMSUB_s = FPDataProcessing3SourceFixed | 0x00008000, FNMADD_s = FPDataProcessing3SourceFixed | 0x00200000, FNMSUB_s = FPDataProcessing3SourceFixed | 0x00208000, FMADD_d = FPDataProcessing3SourceFixed | 0x00400000, FMSUB_d = FPDataProcessing3SourceFixed | 0x00408000, FNMADD_d = FPDataProcessing3SourceFixed | 0x00600000, FNMSUB_d = FPDataProcessing3SourceFixed | 0x00608000 }; // Conversion between floating point and integer. enum FPIntegerConvertOp { FPIntegerConvertFixed = 0x1E200000, FPIntegerConvertFMask = 0x5F20FC00, FPIntegerConvertMask = 0xFFFFFC00, FCVTNS = FPIntegerConvertFixed | 0x00000000, FCVTNS_ws = FCVTNS, FCVTNS_xs = FCVTNS | SixtyFourBits, FCVTNS_wd = FCVTNS | FP64, FCVTNS_xd = FCVTNS | SixtyFourBits | FP64, FCVTNU = FPIntegerConvertFixed | 0x00010000, FCVTNU_ws = FCVTNU, FCVTNU_xs = FCVTNU | SixtyFourBits, FCVTNU_wd = FCVTNU | FP64, FCVTNU_xd = FCVTNU | SixtyFourBits | FP64, FCVTPS = FPIntegerConvertFixed | 0x00080000, FCVTPS_ws = FCVTPS, FCVTPS_xs = FCVTPS | SixtyFourBits, FCVTPS_wd = FCVTPS | FP64, FCVTPS_xd = FCVTPS | SixtyFourBits | FP64, FCVTPU = FPIntegerConvertFixed | 0x00090000, FCVTPU_ws = FCVTPU, FCVTPU_xs = FCVTPU | SixtyFourBits, FCVTPU_wd = FCVTPU | FP64, FCVTPU_xd = FCVTPU | SixtyFourBits | FP64, FCVTMS = FPIntegerConvertFixed | 0x00100000, FCVTMS_ws = FCVTMS, FCVTMS_xs = FCVTMS | SixtyFourBits, FCVTMS_wd = FCVTMS | FP64, FCVTMS_xd = FCVTMS | SixtyFourBits | FP64, FCVTMU = FPIntegerConvertFixed | 0x00110000, FCVTMU_ws = FCVTMU, FCVTMU_xs = FCVTMU | SixtyFourBits, FCVTMU_wd = FCVTMU | FP64, FCVTMU_xd = FCVTMU | SixtyFourBits | FP64, FCVTZS = FPIntegerConvertFixed | 0x00180000, FCVTZS_ws = FCVTZS, FCVTZS_xs = FCVTZS | SixtyFourBits, FCVTZS_wd = FCVTZS | FP64, FCVTZS_xd = FCVTZS | SixtyFourBits | FP64, FCVTZU = FPIntegerConvertFixed | 0x00190000, FCVTZU_ws = FCVTZU, FCVTZU_xs = FCVTZU | SixtyFourBits, FCVTZU_wd = FCVTZU | FP64, FCVTZU_xd = FCVTZU | SixtyFourBits | FP64, SCVTF = FPIntegerConvertFixed | 0x00020000, SCVTF_sw = SCVTF, SCVTF_sx = SCVTF | SixtyFourBits, SCVTF_dw = SCVTF | FP64, SCVTF_dx = SCVTF | SixtyFourBits | FP64, UCVTF = FPIntegerConvertFixed | 0x00030000, UCVTF_sw = UCVTF, UCVTF_sx = UCVTF | SixtyFourBits, UCVTF_dw = UCVTF | FP64, UCVTF_dx = UCVTF | SixtyFourBits | FP64, FCVTAS = FPIntegerConvertFixed | 0x00040000, FCVTAS_ws = FCVTAS, FCVTAS_xs = FCVTAS | SixtyFourBits, FCVTAS_wd = FCVTAS | FP64, FCVTAS_xd = FCVTAS | SixtyFourBits | FP64, FCVTAU = FPIntegerConvertFixed | 0x00050000, FCVTAU_ws = FCVTAU, FCVTAU_xs = FCVTAU | SixtyFourBits, FCVTAU_wd = FCVTAU | FP64, FCVTAU_xd = FCVTAU | SixtyFourBits | FP64, FMOV_ws = FPIntegerConvertFixed | 0x00060000, FMOV_sw = FPIntegerConvertFixed | 0x00070000, FMOV_xd = FMOV_ws | SixtyFourBits | FP64, FMOV_dx = FMOV_sw | SixtyFourBits | FP64 }; // Conversion between fixed point and floating point. enum FPFixedPointConvertOp { FPFixedPointConvertFixed = 0x1E000000, FPFixedPointConvertFMask = 0x5F200000, FPFixedPointConvertMask = 0xFFFF0000, FCVTZS_fixed = FPFixedPointConvertFixed | 0x00180000, FCVTZS_ws_fixed = FCVTZS_fixed, FCVTZS_xs_fixed = FCVTZS_fixed | SixtyFourBits, FCVTZS_wd_fixed = FCVTZS_fixed | FP64, FCVTZS_xd_fixed = FCVTZS_fixed | SixtyFourBits | FP64, FCVTZU_fixed = FPFixedPointConvertFixed | 0x00190000, FCVTZU_ws_fixed = FCVTZU_fixed, FCVTZU_xs_fixed = FCVTZU_fixed | SixtyFourBits, FCVTZU_wd_fixed = FCVTZU_fixed | FP64, FCVTZU_xd_fixed = FCVTZU_fixed | SixtyFourBits | FP64, SCVTF_fixed = FPFixedPointConvertFixed | 0x00020000, SCVTF_sw_fixed = SCVTF_fixed, SCVTF_sx_fixed = SCVTF_fixed | SixtyFourBits, SCVTF_dw_fixed = SCVTF_fixed | FP64, SCVTF_dx_fixed = SCVTF_fixed | SixtyFourBits | FP64, UCVTF_fixed = FPFixedPointConvertFixed | 0x00030000, UCVTF_sw_fixed = UCVTF_fixed, UCVTF_sx_fixed = UCVTF_fixed | SixtyFourBits, UCVTF_dw_fixed = UCVTF_fixed | FP64, UCVTF_dx_fixed = UCVTF_fixed | SixtyFourBits | FP64 }; // Unimplemented and unallocated instructions. These are defined to make fixed // bit assertion easier. enum UnimplementedOp { UnimplementedFixed = 0x00000000, UnimplementedFMask = 0x00000000 }; enum UnallocatedOp { UnallocatedFixed = 0x00000000, UnallocatedFMask = 0x00000000 }; } // namespace vixl #endif // VIXL_A64_CONSTANTS_A64_H_