1 /*
   2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.asm.aarch64;
  24 
  25 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD;
  26 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS;
  27 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR;
  28 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.AND;
  29 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ANDS;
  30 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ASRV;
  31 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BFM;
  32 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BIC;
  33 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BICS;
  34 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BLR;
  35 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BR;
  36 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BRK;
  37 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX;
  38 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS;
  39 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ;
  40 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSEL;
  41 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSINC;
  42 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSNEG;
  43 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.DMB;
  44 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EON;
  45 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EOR;
  46 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EXTR;
  47 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FABS;
  48 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FADD;
  49 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCCMP;
  50 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCMP;
  51 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCMPZERO;
  52 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCSEL;
  53 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCVTDS;
  54 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCVTSD;
  55 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FCVTZS;
  56 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FDIV;
  57 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FMADD;
  58 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FMOV;
  59 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FMSUB;
  60 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FMUL;
  61 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FNEG;
  62 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FRINTZ;
  63 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FSQRT;
  64 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.FSUB;
  65 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.HINT;
  66 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.HLT;
  67 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDAR;
  68 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDAXR;
  69 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDP;
  70 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDR;
  71 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDRS;
  72 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LDXR;
  73 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LSLV;
  74 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.LSRV;
  75 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MADD;
  76 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MOVK;
  77 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MOVN;
  78 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MOVZ;
  79 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MSUB;
  80 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ORN;
  81 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ORR;
  82 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.RBIT;
  83 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.RET;
  84 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.REVW;
  85 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.REVX;
  86 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.RORV;
  87 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SBFM;
  88 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SCVTF;
  89 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SDIV;
  90 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STLR;
  91 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STLXR;
  92 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STP;
  93 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STR;
  94 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STXR;
  95 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUB;
  96 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUBS;
  97 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UBFM;
  98 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UDIV;
  99 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP32;
 100 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP64;
 101 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.General32;
 102 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.General64;
 103 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.floatFromSize;
 104 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.generalFromSize;
 105 import static jdk.vm.ci.aarch64.AArch64.CPU;
 106 import static jdk.vm.ci.aarch64.AArch64.SIMD;
 107 import static jdk.vm.ci.aarch64.AArch64.r0;
 108 import static jdk.vm.ci.aarch64.AArch64.sp;
 109 import static jdk.vm.ci.aarch64.AArch64.zr;
 110 
 111 import java.util.Arrays;
 112 
 113 import org.graalvm.compiler.asm.Assembler;
 114 import org.graalvm.compiler.asm.NumUtil;
 115 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
 116 import org.graalvm.compiler.debug.GraalError;
 117 
 118 import jdk.vm.ci.code.Register;
 119 import jdk.vm.ci.code.TargetDescription;
 120 
 121 public abstract class AArch64Assembler extends Assembler {
 122 
 123     public static class LogicalImmediateTable {
 124 
 125         private static final Immediate[] IMMEDIATE_TABLE = buildImmediateTable();
 126 
 127         private static final int ImmediateOffset = 10;
 128         private static final int ImmediateRotateOffset = 16;
 129         private static final int ImmediateSizeOffset = 22;
 130 
 131         /**
 132          * Specifies whether immediate can be represented in all cases (YES), as a 64bit instruction
 133          * (SIXTY_FOUR_BIT_ONLY) or not at all (NO).
 134          */
 135         enum Representable {
 136             YES,
 137             SIXTY_FOUR_BIT_ONLY,
 138             NO
 139         }
 140 
 141         /**
 142          * Tests whether an immediate can be encoded for logical instructions.
 143          *
 144          * @param is64bit if true immediate is considered a 64-bit pattern. If false we may use a
 145          *            64-bit instruction to load the 32-bit pattern into a register.
 146          * @return enum specifying whether immediate can be used for 32- and 64-bit logical
 147          *         instructions ({@code #Representable.YES}), for 64-bit instructions only (
 148          *         {@link Representable#SIXTY_FOUR_BIT_ONLY}) or not at all (
 149          *         {@link Representable#NO}).
 150          */
 151         public static Representable isRepresentable(boolean is64bit, long immediate) {
 152             int pos = getLogicalImmTablePos(is64bit, immediate);
 153             if (pos < 0) {
 154                 // if 32bit instruction we can try again as 64bit immediate which may succeed.
 155                 // i.e. 0xffffffff fails as a 32bit immediate but works as 64bit one.
 156                 if (!is64bit) {
 157                     assert NumUtil.isUnsignedNbit(32, immediate);
 158                     pos = getLogicalImmTablePos(true, immediate);
 159                     return pos >= 0 ? Representable.SIXTY_FOUR_BIT_ONLY : Representable.NO;
 160                 }
 161                 return Representable.NO;
 162             }
 163             Immediate imm = IMMEDIATE_TABLE[pos];
 164             return imm.only64bit() ? Representable.SIXTY_FOUR_BIT_ONLY : Representable.YES;
 165         }
 166 
 167         public static Representable isRepresentable(int immediate) {
 168             return isRepresentable(false, immediate & 0xFFFF_FFFFL);
 169         }
 170 
 171         public static int getLogicalImmEncoding(boolean is64bit, long value) {
 172             int pos = getLogicalImmTablePos(is64bit, value);
 173             assert pos >= 0 : "Value cannot be represented as logical immediate: " + value + ", is64bit=" + is64bit;
 174             Immediate imm = IMMEDIATE_TABLE[pos];
 175             assert is64bit || !imm.only64bit() : "Immediate can only be represented for 64bit, but 32bit instruction specified";
 176             return IMMEDIATE_TABLE[pos].encoding;
 177         }
 178 
 179         /**
 180          * @param is64bit if true also allow 64-bit only encodings to be returned.
 181          * @return If positive the return value is the position into the IMMEDIATE_TABLE for the
 182          *         given immediate, if negative the immediate cannot be encoded.
 183          */
 184         private static int getLogicalImmTablePos(boolean is64bit, long value) {
 185             Immediate imm;
 186             if (!is64bit) {
 187                 // 32bit instructions can only have 32bit immediates.
 188                 if (!NumUtil.isUnsignedNbit(32, value)) {
 189                     return -1;
 190                 }
 191                 // If we have a 32bit instruction (and therefore immediate) we have to duplicate it
 192                 // across 64bit to find it in the table.
 193                 imm = new Immediate(value << 32 | value);
 194             } else {
 195                 imm = new Immediate(value);
 196             }
 197             int pos = Arrays.binarySearch(IMMEDIATE_TABLE, imm);
 198             if (pos < 0) {
 199                 return -1;
 200             }
 201             if (!is64bit && IMMEDIATE_TABLE[pos].only64bit()) {
 202                 return -1;
 203             }
 204             return pos;
 205         }
 206 
 207         /**
 208          * To quote 5.4.2: [..] an immediate is a 32 or 64 bit pattern viewed as a vector of
 209          * identical elements of size e = 2, 4, 8, 16, 32 or (in the case of bimm64) 64 bits. Each
 210          * element contains the same sub-pattern: a single run of 1 to e-1 non-zero bits, rotated by
 211          * 0 to e-1 bits. It is encoded in the following: 10-16: rotation amount (6bit) starting
 212          * from 1s in the LSB (i.e. 0111->1011->1101->1110) 16-22: This stores a combination of the
 213          * number of set bits and the pattern size. The pattern size is encoded as follows (x is
 214          * used to store the number of 1 bits - 1) e pattern 2 1111xx 4 1110xx 8 110xxx 16 10xxxx 32
 215          * 0xxxxx 64 xxxxxx 22: if set we have an instruction with 64bit pattern?
 216          */
 217         private static final class Immediate implements Comparable<Immediate> {
 218             public final long imm;
 219             public final int encoding;
 220 
 221             Immediate(long imm, boolean is64, int s, int r) {
 222                 this.imm = imm;
 223                 this.encoding = computeEncoding(is64, s, r);
 224             }
 225 
 226             // Used to be able to binary search for an immediate in the table.
 227             Immediate(long imm) {
 228                 this(imm, false, 0, 0);
 229             }
 230 
 231             /**
 232              * Returns true if this pattern is only representable as 64bit.
 233              */
 234             public boolean only64bit() {
 235                 return (encoding & (1 << ImmediateSizeOffset)) != 0;
 236             }
 237 
 238             private static int computeEncoding(boolean is64, int s, int r) {
 239                 int sf = is64 ? 1 : 0;
 240                 return sf << ImmediateSizeOffset | r << ImmediateRotateOffset | s << ImmediateOffset;
 241             }
 242 
 243             @Override
 244             public int compareTo(Immediate o) {
 245                 return Long.compare(imm, o.imm);
 246             }
 247         }
 248 
 249         private static Immediate[] buildImmediateTable() {
 250             final int nrImmediates = 5334;
 251             final Immediate[] table = new Immediate[nrImmediates];
 252             int nrImms = 0;
 253             for (int logE = 1; logE <= 6; logE++) {
 254                 int e = 1 << logE;
 255                 long mask = NumUtil.getNbitNumberLong(e);
 256                 for (int nrOnes = 1; nrOnes < e; nrOnes++) {
 257                     long val = (1L << nrOnes) - 1;
 258                     // r specifies how much we rotate the value
 259                     for (int r = 0; r < e; r++) {
 260                         long immediate = (val >>> r | val << (e - r)) & mask;
 261                         // Duplicate pattern to fill whole 64bit range.
 262                         switch (logE) {
 263                             case 1:
 264                                 immediate |= immediate << 2;
 265                                 immediate |= immediate << 4;
 266                                 immediate |= immediate << 8;
 267                                 immediate |= immediate << 16;
 268                                 immediate |= immediate << 32;
 269                                 break;
 270                             case 2:
 271                                 immediate |= immediate << 4;
 272                                 immediate |= immediate << 8;
 273                                 immediate |= immediate << 16;
 274                                 immediate |= immediate << 32;
 275                                 break;
 276                             case 3:
 277                                 immediate |= immediate << 8;
 278                                 immediate |= immediate << 16;
 279                                 immediate |= immediate << 32;
 280                                 break;
 281                             case 4:
 282                                 immediate |= immediate << 16;
 283                                 immediate |= immediate << 32;
 284                                 break;
 285                             case 5:
 286                                 immediate |= immediate << 32;
 287                                 break;
 288                         }
 289                         // 5 - logE can underflow to -1, but we shift this bogus result
 290                         // out of the masked area.
 291                         int sizeEncoding = (1 << (5 - logE)) - 1;
 292                         int s = ((sizeEncoding << (logE + 1)) & 0x3f) | (nrOnes - 1);
 293                         table[nrImms++] = new Immediate(immediate, /* is64bit */e == 64, s, r);
 294                     }
 295                 }
 296             }
 297             Arrays.sort(table);
 298             assert nrImms == nrImmediates : nrImms + " instead of " + nrImmediates + " in table.";
 299             assert checkDuplicates(table) : "Duplicate values in table.";
 300             return table;
 301         }
 302 
 303         private static boolean checkDuplicates(Immediate[] table) {
 304             for (int i = 0; i < table.length - 1; i++) {
 305                 if (table[i].imm >= table[i + 1].imm) {
 306                     return false;
 307                 }
 308             }
 309             return true;
 310         }
 311     }
 312 
 313     private static final int RdOffset = 0;
 314     private static final int Rs1Offset = 5;
 315     private static final int Rs2Offset = 16;
 316     private static final int Rs3Offset = 10;
 317     private static final int RtOffset = 0;
 318     private static final int RnOffset = 5;
 319     private static final int Rt2Offset = 10;
 320 
 321     /* Helper functions */
 322     private static int rd(Register reg) {
 323         return reg.encoding << RdOffset;
 324     }
 325 
 326     private static int rs1(Register reg) {
 327         return reg.encoding << Rs1Offset;
 328     }
 329 
 330     private static int rs2(Register reg) {
 331         return reg.encoding << Rs2Offset;
 332     }
 333 
 334     private static int rs3(Register reg) {
 335         return reg.encoding << Rs3Offset;
 336     }
 337 
 338     private static int rt(Register reg) {
 339         return reg.encoding << RtOffset;
 340     }
 341 
 342     private static int rt2(Register reg) {
 343         return reg.encoding << Rt2Offset;
 344     }
 345 
 346     private static int rn(Register reg) {
 347         return reg.encoding << RnOffset;
 348     }
 349 
 350     /**
 351      * Enumeration of all different instruction kinds: General32/64 are the general instructions
 352      * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for
 353      * the 32/64bit float operations
 354      */
 355     protected enum InstructionType {
 356         General32(0b00 << 30, 32, true),
 357         General64(0b10 << 30, 64, true),
 358         FP32(0x00000000, 32, false),
 359         FP64(0x00400000, 64, false);
 360 
 361         public final int encoding;
 362         public final int width;
 363         public final boolean isGeneral;
 364 
 365         InstructionType(int encoding, int width, boolean isGeneral) {
 366             this.encoding = encoding;
 367             this.width = width;
 368             this.isGeneral = isGeneral;
 369         }
 370 
 371         public static InstructionType generalFromSize(int size) {
 372             assert size == 32 || size == 64;
 373             return size == 32 ? General32 : General64;
 374         }
 375 
 376         public static InstructionType floatFromSize(int size) {
 377             assert size == 32 || size == 64;
 378             return size == 32 ? FP32 : FP64;
 379         }
 380 
 381     }
 382 
 383     private static final int ImmediateOffset = 10;
 384     private static final int ImmediateRotateOffset = 16;
 385     private static final int ImmediateSizeOffset = 22;
 386     private static final int ExtendTypeOffset = 13;
 387 
 388     private static final int AddSubImmOp = 0x11000000;
 389     private static final int AddSubShift12 = 0b01 << 22;
 390     private static final int AddSubSetFlag = 0x20000000;
 391 
 392     private static final int LogicalImmOp = 0x12000000;
 393 
 394     private static final int MoveWideImmOp = 0x12800000;
 395     private static final int MoveWideImmOffset = 5;
 396     private static final int MoveWideShiftOffset = 21;
 397 
 398     private static final int BitfieldImmOp = 0x13000000;
 399 
 400     private static final int AddSubShiftedOp = 0x0B000000;
 401     private static final int ShiftTypeOffset = 22;
 402 
 403     private static final int AddSubExtendedOp = 0x0B200000;
 404 
 405     private static final int MulOp = 0x1B000000;
 406     private static final int DataProcessing1SourceOp = 0x5AC00000;
 407     private static final int DataProcessing2SourceOp = 0x1AC00000;
 408 
 409     private static final int Fp1SourceOp = 0x1E204000;
 410     private static final int Fp2SourceOp = 0x1E200800;
 411     private static final int Fp3SourceOp = 0x1F000000;
 412 
 413     private static final int FpConvertOp = 0x1E200000;
 414     private static final int FpImmOp = 0x1E201000;
 415     private static final int FpImmOffset = 13;
 416 
 417     private static final int FpCmpOp = 0x1E202000;
 418 
 419     private static final int PcRelImmHiOffset = 5;
 420     private static final int PcRelImmLoOffset = 29;
 421 
 422     private static final int PcRelImmOp = 0x10000000;
 423 
 424     private static final int UnconditionalBranchImmOp = 0x14000000;
 425     private static final int UnconditionalBranchRegOp = 0xD6000000;
 426     private static final int CompareBranchOp = 0x34000000;
 427 
 428     private static final int ConditionalBranchImmOffset = 5;
 429 
 430     private static final int ConditionalSelectOp = 0x1A800000;
 431     private static final int ConditionalConditionOffset = 12;
 432 
 433     private static final int LoadStoreScaledOp = 0b111_0_01_00 << 22;
 434     private static final int LoadStoreUnscaledOp = 0b111_0_00_00 << 22;
 435 
 436     private static final int LoadStoreRegisterOp = 0b111_0_00_00_1 << 21 | 0b10 << 10;
 437 
 438     private static final int LoadLiteralOp = 0x18000000;
 439 
 440     private static final int LoadStorePostIndexedOp = 0b111_0_00_00_0 << 21 | 0b01 << 10;
 441     private static final int LoadStorePreIndexedOp = 0b111_0_00_00_0 << 21 | 0b11 << 10;
 442 
 443     private static final int LoadStoreUnscaledImmOffset = 12;
 444     private static final int LoadStoreScaledImmOffset = 10;
 445     private static final int LoadStoreScaledRegOffset = 12;
 446     private static final int LoadStoreIndexedImmOffset = 12;
 447     private static final int LoadStoreTransferSizeOffset = 30;
 448     private static final int LoadStoreFpFlagOffset = 26;
 449     private static final int LoadLiteralImmeOffset = 5;
 450 
 451     private static final int LoadStorePairOp = 0b101_0_010 << 23;
 452     @SuppressWarnings("unused") private static final int LoadStorePairPostIndexOp = 0b101_0_001 << 23;
 453     @SuppressWarnings("unused") private static final int LoadStorePairPreIndexOp = 0b101_0_011 << 23;
 454     private static final int LoadStorePairImm7Offset = 15;
 455 
 456     private static final int LogicalShiftOp = 0x0A000000;
 457 
 458     private static final int ExceptionOp = 0xD4000000;
 459     private static final int SystemImmediateOffset = 5;
 460 
 461     @SuppressWarnings("unused") private static final int SimdImmediateOffset = 16;
 462 
 463     private static final int BarrierOp = 0xD503301F;
 464     private static final int BarrierKindOffset = 8;
 465 
 466     /**
 467      * Encoding for all instructions.
 468      */
 469     public enum Instruction {
 470         BCOND(0x54000000),
 471         CBNZ(0x01000000),
 472         CBZ(0x00000000),
 473 
 474         B(0x00000000),
 475         BL(0x80000000),
 476         BR(0x001F0000),
 477         BLR(0x003F0000),
 478         RET(0x005F0000),
 479 
 480         LDR(0x00000000),
 481         LDRS(0x00800000),
 482         LDXR(0x081f7c00),
 483         LDAR(0x8dffc00),
 484         LDAXR(0x85ffc00),
 485 
 486         STR(0x00000000),
 487         STXR(0x08007c00),
 488         STLR(0x089ffc00),
 489         STLXR(0x0800fc00),
 490 
 491         LDP(0b1 << 22),
 492         STP(0b0 << 22),
 493 
 494         ADR(0x00000000),
 495         ADRP(0x80000000),
 496 
 497         ADD(0x00000000),
 498         ADDS(ADD.encoding | AddSubSetFlag),
 499         SUB(0x40000000),
 500         SUBS(SUB.encoding | AddSubSetFlag),
 501 
 502         NOT(0x00200000),
 503         AND(0x00000000),
 504         BIC(AND.encoding | NOT.encoding),
 505         ORR(0x20000000),
 506         ORN(ORR.encoding | NOT.encoding),
 507         EOR(0x40000000),
 508         EON(EOR.encoding | NOT.encoding),
 509         ANDS(0x60000000),
 510         BICS(ANDS.encoding | NOT.encoding),
 511 
 512         ASRV(0x00002800),
 513         RORV(0x00002C00),
 514         LSRV(0x00002400),
 515         LSLV(0x00002000),
 516 
 517         CLS(0x00001400),
 518         CLZ(0x00001000),
 519         RBIT(0x00000000),
 520         REVX(0x00000C00),
 521         REVW(0x00000800),
 522 
 523         MOVN(0x00000000),
 524         MOVZ(0x40000000),
 525         MOVK(0x60000000),
 526 
 527         CSEL(0x00000000),
 528         CSNEG(0x40000400),
 529         CSINC(0x00000400),
 530 
 531         BFM(0x20000000),
 532         SBFM(0x00000000),
 533         UBFM(0x40000000),
 534         EXTR(0x13800000),
 535 
 536         MADD(0x00000000),
 537         MSUB(0x00008000),
 538         SDIV(0x00000C00),
 539         UDIV(0x00000800),
 540 
 541         FMOV(0x00000000),
 542         FMOVCPU2FPU(0x00070000),
 543         FMOVFPU2CPU(0x00060000),
 544 
 545         FCVTDS(0x00028000),
 546         FCVTSD(0x00020000),
 547 
 548         FCVTZS(0x00180000),
 549         SCVTF(0x00020000),
 550 
 551         FABS(0x00008000),
 552         FSQRT(0x00018000),
 553         FNEG(0x00010000),
 554 
 555         FRINTZ(0x00058000),
 556 
 557         FADD(0x00002000),
 558         FSUB(0x00003000),
 559         FMUL(0x00000000),
 560         FDIV(0x00001000),
 561         FMAX(0x00004000),
 562         FMIN(0x00005000),
 563 
 564         FMADD(0x00000000),
 565         FMSUB(0x00008000),
 566 
 567         FCMP(0x00000000),
 568         FCMPZERO(0x00000008),
 569         FCCMP(0x1E200400),
 570         FCSEL(0x1E200C00),
 571 
 572         INS(0x4e081c00),
 573         UMOV(0x4e083c00),
 574 
 575         CNT(0xe205800),
 576         USRA(0x6f001400),
 577 
 578         HLT(0x00400000),
 579         BRK(0x00200000),
 580 
 581         CLREX(0xd5033f5f),
 582         HINT(0xD503201F),
 583         DMB(0x000000A0),
 584 
 585         BLR_NATIVE(0xc0000000);
 586 
 587         public final int encoding;
 588 
 589         Instruction(int encoding) {
 590             this.encoding = encoding;
 591         }
 592 
 593     }
 594 
 595     public enum ShiftType {
 596         LSL(0),
 597         LSR(1),
 598         ASR(2),
 599         ROR(3);
 600 
 601         public final int encoding;
 602 
 603         ShiftType(int encoding) {
 604             this.encoding = encoding;
 605         }
 606     }
 607 
 608     public enum ExtendType {
 609         UXTB(0),
 610         UXTH(1),
 611         UXTW(2),
 612         UXTX(3),
 613         SXTB(4),
 614         SXTH(5),
 615         SXTW(6),
 616         SXTX(7);
 617 
 618         public final int encoding;
 619 
 620         ExtendType(int encoding) {
 621             this.encoding = encoding;
 622         }
 623     }
 624 
 625     /**
 626      * Condition Flags for branches. See 4.3
 627      */
 628     public enum ConditionFlag {
 629         // Integer | Floating-point meanings
 630         /** Equal | Equal. */
 631         EQ(0x0),
 632 
 633         /** Not Equal | Not equal or unordered. */
 634         NE(0x1),
 635 
 636         /** Unsigned Higher or Same | Greater than, equal or unordered. */
 637         HS(0x2),
 638 
 639         /** Unsigned lower | less than. */
 640         LO(0x3),
 641 
 642         /** Minus (negative) | less than. */
 643         MI(0x4),
 644 
 645         /** Plus (positive or zero) | greater than, equal or unordered. */
 646         PL(0x5),
 647 
 648         /** Overflow set | unordered. */
 649         VS(0x6),
 650 
 651         /** Overflow clear | ordered. */
 652         VC(0x7),
 653 
 654         /** Unsigned higher | greater than or unordered. */
 655         HI(0x8),
 656 
 657         /** Unsigned lower or same | less than or equal. */
 658         LS(0x9),
 659 
 660         /** Signed greater than or equal | greater than or equal. */
 661         GE(0xA),
 662 
 663         /** Signed less than | less than or unordered. */
 664         LT(0xB),
 665 
 666         /** Signed greater than | greater than. */
 667         GT(0xC),
 668 
 669         /** Signed less than or equal | less than, equal or unordered. */
 670         LE(0xD),
 671 
 672         /** Always | always. */
 673         AL(0xE),
 674 
 675         /** Always | always (identical to AL, just to have valid 0b1111 encoding). */
 676         NV(0xF);
 677 
 678         public final int encoding;
 679 
 680         ConditionFlag(int encoding) {
 681             this.encoding = encoding;
 682         }
 683 
 684         /**
 685          * @return ConditionFlag specified by decoding.
 686          */
 687         public static ConditionFlag fromEncoding(int encoding) {
 688             return values()[encoding];
 689         }
 690 
 691         public ConditionFlag negate() {
 692             switch (this) {
 693                 case EQ:
 694                     return NE;
 695                 case NE:
 696                     return EQ;
 697                 case HS:
 698                     return LO;
 699                 case LO:
 700                     return HS;
 701                 case MI:
 702                     return PL;
 703                 case PL:
 704                     return MI;
 705                 case VS:
 706                     return VC;
 707                 case VC:
 708                     return VS;
 709                 case HI:
 710                     return LS;
 711                 case LS:
 712                     return HI;
 713                 case GE:
 714                     return LT;
 715                 case LT:
 716                     return GE;
 717                 case GT:
 718                     return LE;
 719                 case LE:
 720                     return GT;
 721                 case AL:
 722                 case NV:
 723                 default:
 724                     throw GraalError.shouldNotReachHere();
 725             }
 726         }
 727     }
 728 
 729     public AArch64Assembler(TargetDescription target) {
 730         super(target);
 731     }
 732 
 733     /* Conditional Branch (5.2.1) */
 734 
 735     /**
 736      * Branch conditionally.
 737      *
 738      * @param condition may not be null.
 739      * @param imm21 Signed 21-bit offset, has to be word aligned.
 740      */
 741     protected void b(ConditionFlag condition, int imm21) {
 742         b(condition, imm21, -1);
 743     }
 744 
 745     /**
 746      * Branch conditionally. Inserts instruction into code buffer at pos.
 747      *
 748      * @param condition may not be null.
 749      * @param imm21 Signed 21-bit offset, has to be word aligned.
 750      * @param pos Position at which instruction is inserted into buffer. -1 means insert at end.
 751      */
 752     protected void b(ConditionFlag condition, int imm21, int pos) {
 753         if (pos == -1) {
 754             emitInt(Instruction.BCOND.encoding | getConditionalBranchImm(imm21) | condition.encoding);
 755         } else {
 756             emitInt(Instruction.BCOND.encoding | getConditionalBranchImm(imm21) | condition.encoding, pos);
 757         }
 758     }
 759 
 760     /**
 761      * Compare register and branch if non-zero.
 762      *
 763      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 764      * @param size Instruction size in bits. Should be either 32 or 64.
 765      * @param imm21 Signed 21-bit offset, has to be word aligned.
 766      */
 767     protected void cbnz(int size, Register reg, int imm21) {
 768         conditionalBranchInstruction(reg, imm21, generalFromSize(size), Instruction.CBNZ, -1);
 769     }
 770 
 771     /**
 772      * Compare register and branch if non-zero.
 773      *
 774      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 775      * @param size Instruction size in bits. Should be either 32 or 64.
 776      * @param imm21 Signed 21-bit offset, has to be word aligned.
 777      * @param pos Position at which instruction is inserted into buffer. -1 means insert at end.
 778      */
 779     protected void cbnz(int size, Register reg, int imm21, int pos) {
 780         conditionalBranchInstruction(reg, imm21, generalFromSize(size), Instruction.CBNZ, pos);
 781     }
 782 
 783     /**
 784      * Compare and branch if zero.
 785      *
 786      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 787      * @param size Instruction size in bits. Should be either 32 or 64.
 788      * @param imm21 Signed 21-bit offset, has to be word aligned.
 789      */
 790     protected void cbz(int size, Register reg, int imm21) {
 791         conditionalBranchInstruction(reg, imm21, generalFromSize(size), Instruction.CBZ, -1);
 792     }
 793 
 794     /**
 795      * Compare register and branch if zero.
 796      *
 797      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 798      * @param size Instruction size in bits. Should be either 32 or 64.
 799      * @param imm21 Signed 21-bit offset, has to be word aligned.
 800      * @param pos Position at which instruction is inserted into buffer. -1 means insert at end.
 801      */
 802     protected void cbz(int size, Register reg, int imm21, int pos) {
 803         conditionalBranchInstruction(reg, imm21, generalFromSize(size), Instruction.CBZ, pos);
 804     }
 805 
 806     private void conditionalBranchInstruction(Register reg, int imm21, InstructionType type, Instruction instr, int pos) {
 807         assert reg.getRegisterCategory().equals(CPU);
 808         int instrEncoding = instr.encoding | CompareBranchOp;
 809         if (pos == -1) {
 810             emitInt(type.encoding | instrEncoding | getConditionalBranchImm(imm21) | rd(reg));
 811         } else {
 812             emitInt(type.encoding | instrEncoding | getConditionalBranchImm(imm21) | rd(reg), pos);
 813         }
 814     }
 815 
 816     private static int getConditionalBranchImm(int imm21) {
 817         assert NumUtil.isSignedNbit(21, imm21) && (imm21 & 0x3) == 0 : "Immediate has to be 21bit signed number and word aligned";
 818         int imm = (imm21 & NumUtil.getNbitNumberInt(21)) >> 2;
 819         return imm << ConditionalBranchImmOffset;
 820     }
 821 
 822     /* Unconditional Branch (immediate) (5.2.2) */
 823 
 824     /**
 825      * @param imm28 Signed 28-bit offset, has to be word aligned.
 826      */
 827     protected void b(int imm28) {
 828         unconditionalBranchImmInstruction(imm28, Instruction.B, -1);
 829     }
 830 
 831     /**
 832      *
 833      * @param imm28 Signed 28-bit offset, has to be word aligned.
 834      * @param pos Position where instruction is inserted into code buffer.
 835      */
 836     protected void b(int imm28, int pos) {
 837         unconditionalBranchImmInstruction(imm28, Instruction.B, pos);
 838     }
 839 
 840     /**
 841      * Branch and link return address to register X30.
 842      *
 843      * @param imm28 Signed 28-bit offset, has to be word aligned.
 844      */
 845     public void bl(int imm28) {
 846         unconditionalBranchImmInstruction(imm28, Instruction.BL, -1);
 847     }
 848 
 849     private void unconditionalBranchImmInstruction(int imm28, Instruction instr, int pos) {
 850         assert NumUtil.isSignedNbit(28, imm28) && (imm28 & 0x3) == 0 : "Immediate has to be 28bit signed number and word aligned";
 851         int imm = (imm28 & NumUtil.getNbitNumberInt(28)) >> 2;
 852         int instrEncoding = instr.encoding | UnconditionalBranchImmOp;
 853         if (pos == -1) {
 854             emitInt(instrEncoding | imm);
 855         } else {
 856             emitInt(instrEncoding | imm, pos);
 857         }
 858     }
 859 
 860     /* Unconditional Branch (register) (5.2.3) */
 861 
 862     /**
 863      * Branches to address in register and writes return address into register X30.
 864      *
 865      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 866      */
 867     public void blr(Register reg) {
 868         unconditionalBranchRegInstruction(BLR, reg);
 869     }
 870 
 871     /**
 872      * Branches to address in register.
 873      *
 874      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 875      */
 876     protected void br(Register reg) {
 877         unconditionalBranchRegInstruction(BR, reg);
 878     }
 879 
 880     /**
 881      * Return to address in register.
 882      *
 883      * @param reg general purpose register. May not be null, zero-register or stackpointer.
 884      */
 885     public void ret(Register reg) {
 886         unconditionalBranchRegInstruction(RET, reg);
 887     }
 888 
 889     private void unconditionalBranchRegInstruction(Instruction instr, Register reg) {
 890         assert reg.getRegisterCategory().equals(CPU);
 891         assert !reg.equals(zr);
 892         assert !reg.equals(sp);
 893         emitInt(instr.encoding | UnconditionalBranchRegOp | rs1(reg));
 894     }
 895 
 896     /* Load-Store Single Register (5.3.1) */
 897 
 898     /**
 899      * Loads a srcSize value from address into rt zero-extending it.
 900      *
 901      * @param srcSize size of memory read in bits. Must be 8, 16, 32 or 64.
 902      * @param rt general purpose register. May not be null or stackpointer.
 903      * @param address all addressing modes allowed. May not be null.
 904      */
 905     public void ldr(int srcSize, Register rt, AArch64Address address) {
 906         assert rt.getRegisterCategory().equals(CPU);
 907         assert srcSize == 8 || srcSize == 16 || srcSize == 32 || srcSize == 64;
 908         int transferSize = NumUtil.log2Ceil(srcSize / 8);
 909         loadStoreInstruction(LDR, rt, address, General32, transferSize);
 910     }
 911 
 912     /**
 913      * Loads a srcSize value from address into rt sign-extending it.
 914      *
 915      * @param targetSize size of target register in bits. Must be 32 or 64.
 916      * @param srcSize size of memory read in bits. Must be 8, 16 or 32, but may not be equivalent to
 917      *            targetSize.
 918      * @param rt general purpose register. May not be null or stackpointer.
 919      * @param address all addressing modes allowed. May not be null.
 920      */
 921     protected void ldrs(int targetSize, int srcSize, Register rt, AArch64Address address) {
 922         assert rt.getRegisterCategory().equals(CPU);
 923         assert (srcSize == 8 || srcSize == 16 || srcSize == 32) && srcSize != targetSize;
 924         int transferSize = NumUtil.log2Ceil(srcSize / 8);
 925         loadStoreInstruction(LDRS, rt, address, generalFromSize(targetSize), transferSize);
 926     }
 927 
 928     /**
 929      * Stores register rt into memory pointed by address.
 930      *
 931      * @param destSize number of bits written to memory. Must be 8, 16, 32 or 64.
 932      * @param rt general purpose register. May not be null or stackpointer.
 933      * @param address all addressing modes allowed. May not be null.
 934      */
 935     public void str(int destSize, Register rt, AArch64Address address) {
 936         assert rt.getRegisterCategory().equals(CPU);
 937         assert destSize == 8 || destSize == 16 || destSize == 32 || destSize == 64;
 938         int transferSize = NumUtil.log2Ceil(destSize / 8);
 939         loadStoreInstruction(STR, rt, address, General64, transferSize);
 940     }
 941 
 942     private void loadStoreInstruction(Instruction instr, Register reg, AArch64Address address, InstructionType type, int log2TransferSize) {
 943         assert log2TransferSize >= 0 && log2TransferSize < 4;
 944         int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
 945         int is32Bit = type.width == 32 ? 1 << ImmediateSizeOffset : 0;
 946         int isFloat = !type.isGeneral ? 1 << LoadStoreFpFlagOffset : 0;
 947         int memop = instr.encoding | transferSizeEncoding | is32Bit | isFloat | rt(reg);
 948         switch (address.getAddressingMode()) {
 949             case IMMEDIATE_SCALED:
 950                 emitInt(memop | LoadStoreScaledOp | address.getImmediate() << LoadStoreScaledImmOffset | rs1(address.getBase()));
 951                 break;
 952             case IMMEDIATE_UNSCALED:
 953                 emitInt(memop | LoadStoreUnscaledOp | address.getImmediate() << LoadStoreUnscaledImmOffset | rs1(address.getBase()));
 954                 break;
 955             case BASE_REGISTER_ONLY:
 956                 emitInt(memop | LoadStoreScaledOp | rs1(address.getBase()));
 957                 break;
 958             case EXTENDED_REGISTER_OFFSET:
 959             case REGISTER_OFFSET:
 960                 ExtendType extendType = address.getAddressingMode() == AddressingMode.EXTENDED_REGISTER_OFFSET ? address.getExtendType() : ExtendType.UXTX;
 961                 boolean shouldScale = address.isScaled() && log2TransferSize != 0;
 962                 emitInt(memop | LoadStoreRegisterOp | rs2(address.getOffset()) | extendType.encoding << ExtendTypeOffset | (shouldScale ? 1 : 0) << LoadStoreScaledRegOffset | rs1(address.getBase()));
 963                 break;
 964             case PC_LITERAL:
 965                 assert log2TransferSize >= 2 : "PC literal loads only works for load/stores of 32-bit and larger";
 966                 transferSizeEncoding = (log2TransferSize - 2) << LoadStoreTransferSizeOffset;
 967                 emitInt(transferSizeEncoding | isFloat | LoadLiteralOp | rd(reg) | address.getImmediate() << LoadLiteralImmeOffset);
 968                 break;
 969             case IMMEDIATE_POST_INDEXED:
 970                 emitInt(memop | LoadStorePostIndexedOp | rs1(address.getBase()) | address.getImmediate() << LoadStoreIndexedImmOffset);
 971                 break;
 972             case IMMEDIATE_PRE_INDEXED:
 973                 emitInt(memop | LoadStorePreIndexedOp | rs1(address.getBase()) | address.getImmediate() << LoadStoreIndexedImmOffset);
 974                 break;
 975             default:
 976                 throw GraalError.shouldNotReachHere("Unhandled addressing mode: " + address.getAddressingMode());
 977         }
 978     }
 979 
 980     /**
 981      *
 982      */
 983     public void ldp(int size, Register rt, Register rt2, AArch64Address address) {
 984         assert size == 32 || size == 64;
 985         loadStorePairInstruction(LDP, rt, rt2, address, generalFromSize(size));
 986     }
 987 
 988     /**
 989      * Store Pair of Registers calculates an address from a base register value and an immediate
 990      * offset, and stores two 32-bit words or two 64-bit doublewords to the calculated address, from
 991      * two registers.
 992      */
 993     public void stp(int size, Register rt, Register rt2, AArch64Address address) {
 994         assert size == 32 || size == 64;
 995         loadStorePairInstruction(STP, rt, rt2, address, generalFromSize(size));
 996     }
 997 
 998     private void loadStorePairInstruction(Instruction instr, Register rt, Register rt2, AArch64Address address, InstructionType type) {
 999         int memop = type.encoding | instr.encoding | address.getImmediate() << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt);
1000         switch (address.getAddressingMode()) {
1001             case IMMEDIATE_UNSCALED:
1002                 emitInt(memop | LoadStorePairOp);
1003                 break;
1004             default:
1005                 throw GraalError.shouldNotReachHere("Unhandled addressing mode: " + address.getAddressingMode());
1006         }
1007     }
1008 
1009     /* Load-Store Exclusive (5.3.6) */
1010 
1011     /**
1012      * Load address exclusive. Natural alignment of address is required.
1013      *
1014      * @param size size of memory read in bits. Must be 8, 16, 32 or 64.
1015      * @param rt general purpose register. May not be null or stackpointer.
1016      * @param rn general purpose register.
1017      */
1018     protected void ldxr(int size, Register rt, Register rn) {
1019         assert size == 8 || size == 16 || size == 32 || size == 64;
1020         int transferSize = NumUtil.log2Ceil(size / 8);
1021         exclusiveLoadInstruction(LDXR, rt, rn, transferSize);
1022     }
1023 
1024     /**
1025      * Store address exclusive. Natural alignment of address is required. rs and rt may not point to
1026      * the same register.
1027      *
1028      * @param size size of bits written to memory. Must be 8, 16, 32 or 64.
1029      * @param rs general purpose register. Set to exclusive access status. 0 means success,
1030      *            everything else failure. May not be null, or stackpointer.
1031      * @param rt general purpose register. May not be null or stackpointer.
1032      * @param rn general purpose register.
1033      */
1034     protected void stxr(int size, Register rs, Register rt, Register rn) {
1035         assert size == 8 || size == 16 || size == 32 || size == 64;
1036         int transferSize = NumUtil.log2Ceil(size / 8);
1037         exclusiveStoreInstruction(STXR, rs, rt, rn, transferSize);
1038     }
1039 
1040     /* Load-Acquire/Store-Release (5.3.7) */
1041 
1042     /* non exclusive access */
1043     /**
1044      * Load acquire. Natural alignment of address is required.
1045      *
1046      * @param size size of memory read in bits. Must be 8, 16, 32 or 64.
1047      * @param rt general purpose register. May not be null or stackpointer.
1048      * @param rn general purpose register.
1049      */
1050     protected void ldar(int size, Register rt, Register rn) {
1051         assert size == 8 || size == 16 || size == 32 || size == 64;
1052         int transferSize = NumUtil.log2Ceil(size / 8);
1053         exclusiveLoadInstruction(LDAR, rt, rn, transferSize);
1054     }
1055 
1056     /**
1057      * Store-release. Natural alignment of address is required.
1058      *
1059      * @param size size of bits written to memory. Must be 8, 16, 32 or 64.
1060      * @param rt general purpose register. May not be null or stackpointer.
1061      * @param rn general purpose register.
1062      */
1063     protected void stlr(int size, Register rt, Register rn) {
1064         assert size == 8 || size == 16 || size == 32 || size == 64;
1065         int transferSize = NumUtil.log2Ceil(size / 8);
1066         // Hack: Passing the zero-register means it is ignored when building the encoding.
1067         exclusiveStoreInstruction(STLR, r0, rt, rn, transferSize);
1068     }
1069 
1070     /* exclusive access */
1071     /**
1072      * Load acquire exclusive. Natural alignment of address is required.
1073      *
1074      * @param size size of memory read in bits. Must be 8, 16, 32 or 64.
1075      * @param rt general purpose register. May not be null or stackpointer.
1076      * @param rn general purpose register.
1077      */
1078     public void ldaxr(int size, Register rt, Register rn) {
1079         assert size == 8 || size == 16 || size == 32 || size == 64;
1080         int transferSize = NumUtil.log2Ceil(size / 8);
1081         exclusiveLoadInstruction(LDAXR, rt, rn, transferSize);
1082     }
1083 
1084     /**
1085      * Store-release exclusive. Natural alignment of address is required. rs and rt may not point to
1086      * the same register.
1087      *
1088      * @param size size of bits written to memory. Must be 8, 16, 32 or 64.
1089      * @param rs general purpose register. Set to exclusive access status. 0 means success,
1090      *            everything else failure. May not be null, or stackpointer.
1091      * @param rt general purpose register. May not be null or stackpointer.
1092      * @param rn general purpose register.
1093      */
1094     public void stlxr(int size, Register rs, Register rt, Register rn) {
1095         assert size == 8 || size == 16 || size == 32 || size == 64;
1096         int transferSize = NumUtil.log2Ceil(size / 8);
1097         exclusiveStoreInstruction(STLXR, rs, rt, rn, transferSize);
1098     }
1099 
1100     private void exclusiveLoadInstruction(Instruction instr, Register reg, Register rn, int log2TransferSize) {
1101         assert log2TransferSize >= 0 && log2TransferSize < 4;
1102         assert reg.getRegisterCategory().equals(CPU);
1103         int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
1104         emitInt(transferSizeEncoding | instr.encoding | 1 << ImmediateSizeOffset | rn(rn) | rt(reg));
1105     }
1106 
1107     /**
1108      * Stores data from rt into address and sets rs to the returned exclusive access status.
1109      *
1110      * @param rs general purpose register into which the exclusive access status is written. May not
1111      *            be null.
1112      * @param rt general purpose register containing data to be written to memory at address. May
1113      *            not be null
1114      * @param rn general purpose register containing the address specifying where rt is written to.
1115      * @param log2TransferSize log2Ceil of memory transfer size.
1116      */
1117     private void exclusiveStoreInstruction(Instruction instr, Register rs, Register rt, Register rn, int log2TransferSize) {
1118         assert log2TransferSize >= 0 && log2TransferSize < 4;
1119         assert rt.getRegisterCategory().equals(CPU) && rs.getRegisterCategory().equals(CPU) && !rs.equals(rt);
1120         int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
1121         emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt));
1122     }
1123 
1124     /* PC-relative Address Calculation (5.4.4) */
1125 
1126     /**
1127      * Address of page: sign extends 21-bit offset, shifts if left by 12 and adds it to the value of
1128      * the PC with its bottom 12-bits cleared, writing the result to dst.
1129      *
1130      * @param dst general purpose register. May not be null, zero-register or stackpointer.
1131      * @param imm Signed 33-bit offset with lower 12bits clear.
1132      */
1133     // protected void adrp(Register dst, long imm) {
1134     // assert (imm & NumUtil.getNbitNumberInt(12)) == 0 : "Lower 12-bit of immediate must be zero.";
1135     // assert NumUtil.isSignedNbit(33, imm);
1136     // addressCalculationInstruction(dst, (int) (imm >>> 12), Instruction.ADRP);
1137     // }
1138 
1139     /**
1140      * Adds a 21-bit signed offset to the program counter and writes the result to dst.
1141      *
1142      * @param dst general purpose register. May not be null, zero-register or stackpointer.
1143      * @param imm21 Signed 21-bit offset.
1144      */
1145     public void adr(Register dst, int imm21) {
1146         emitInt(ADR.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(imm21));
1147     }
1148 
1149     public void adr(Register dst, int imm21, int pos) {
1150         emitInt(ADR.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(imm21), pos);
1151     }
1152 
1153     private static int getPcRelativeImmEncoding(int imm21) {
1154         assert NumUtil.isSignedNbit(21, imm21);
1155         int imm = imm21 & NumUtil.getNbitNumberInt(21);
1156         // higher 19 bit
1157         int immHi = (imm >> 2) << PcRelImmHiOffset;
1158         // lower 2 bit
1159         int immLo = (imm & 0x3) << PcRelImmLoOffset;
1160         return immHi | immLo;
1161     }
1162 
1163     /* Arithmetic (Immediate) (5.4.1) */
1164 
1165     /**
1166      * dst = src + aimm.
1167      *
1168      * @param size register size. Has to be 32 or 64.
1169      * @param dst general purpose register. May not be null or zero-register.
1170      * @param src general purpose register. May not be null or zero-register.
1171      * @param aimm arithmetic immediate. Either unsigned 12-bit value or unsigned 24-bit value with
1172      *            the lower 12-bit cleared.
1173      */
1174     protected void add(int size, Register dst, Register src, int aimm) {
1175         assert !dst.equals(zr);
1176         assert !src.equals(zr);
1177         addSubImmInstruction(ADD, dst, src, aimm, generalFromSize(size));
1178     }
1179 
1180     /**
1181      * dst = src + aimm and sets condition flags.
1182      *
1183      * @param size register size. Has to be 32 or 64.
1184      * @param dst general purpose register. May not be null or stackpointer.
1185      * @param src general purpose register. May not be null or zero-register.
1186      * @param aimm arithmetic immediate. Either unsigned 12-bit value or unsigned 24-bit value with
1187      *            the lower 12-bit cleared.
1188      */
1189     protected void adds(int size, Register dst, Register src, int aimm) {
1190         assert !dst.equals(sp);
1191         assert !src.equals(zr);
1192         addSubImmInstruction(ADDS, dst, src, aimm, generalFromSize(size));
1193     }
1194 
1195     /**
1196      * dst = src - aimm.
1197      *
1198      * @param size register size. Has to be 32 or 64.
1199      * @param dst general purpose register. May not be null or zero-register.
1200      * @param src general purpose register. May not be null or zero-register.
1201      * @param aimm arithmetic immediate. Either unsigned 12-bit value or unsigned 24-bit value with
1202      *            the lower 12-bit cleared.
1203      */
1204     protected void sub(int size, Register dst, Register src, int aimm) {
1205         assert !dst.equals(zr);
1206         assert !src.equals(zr);
1207         addSubImmInstruction(SUB, dst, src, aimm, generalFromSize(size));
1208     }
1209 
1210     /**
1211      * dst = src - aimm and sets condition flags.
1212      *
1213      * @param size register size. Has to be 32 or 64.
1214      * @param dst general purpose register. May not be null or stackpointer.
1215      * @param src general purpose register. May not be null or zero-register.
1216      * @param aimm arithmetic immediate. Either unsigned 12-bit value or unsigned 24-bit value with
1217      *            the lower 12-bit cleared.
1218      */
1219     protected void subs(int size, Register dst, Register src, int aimm) {
1220         assert !dst.equals(sp);
1221         assert !src.equals(zr);
1222         addSubImmInstruction(SUBS, dst, src, aimm, generalFromSize(size));
1223     }
1224 
1225     private void addSubImmInstruction(Instruction instr, Register dst, Register src, int aimm, InstructionType type) {
1226         emitInt(type.encoding | instr.encoding | AddSubImmOp | encodeAimm(aimm) | rd(dst) | rs1(src));
1227     }
1228 
1229     /**
1230      * Encodes arithmetic immediate.
1231      *
1232      * @param imm Immediate has to be either an unsigned 12-bit value or an unsigned 24-bit value
1233      *            with the lower 12 bits zero.
1234      * @return Representation of immediate for use with arithmetic instructions.
1235      */
1236     private static int encodeAimm(int imm) {
1237         assert isAimm(imm) : "Immediate has to be legal arithmetic immediate value " + imm;
1238         if (NumUtil.isUnsignedNbit(12, imm)) {
1239             return imm << ImmediateOffset;
1240         } else {
1241             // First 12-bit are zero, so shift immediate 12-bit and set flag to indicate
1242             // shifted immediate value.
1243             return (imm >>> 12 << ImmediateOffset) | AddSubShift12;
1244         }
1245     }
1246 
1247     /**
1248      * Checks whether immediate can be encoded as an arithmetic immediate.
1249      *
1250      * @param imm Immediate has to be either an unsigned 12bit value or un unsigned 24bit value with
1251      *            the lower 12 bits 0.
1252      * @return true if valid arithmetic immediate, false otherwise.
1253      */
1254     protected static boolean isAimm(int imm) {
1255         return NumUtil.isUnsignedNbit(12, imm) || NumUtil.isUnsignedNbit(12, imm >>> 12) && (imm & 0xfff) == 0;
1256     }
1257 
1258     /* Logical (immediate) (5.4.2) */
1259 
1260     /**
1261      * dst = src & bimm.
1262      *
1263      * @param size register size. Has to be 32 or 64.
1264      * @param dst general purpose register. May not be null or zero-register.
1265      * @param src general purpose register. May not be null or stack-pointer.
1266      * @param bimm logical immediate. See {@link LogicalImmediateTable} for exact definition.
1267      */
1268     public void and(int size, Register dst, Register src, long bimm) {
1269         assert !dst.equals(zr);
1270         assert !src.equals(sp);
1271         logicalImmInstruction(AND, dst, src, bimm, generalFromSize(size));
1272     }
1273 
1274     /**
1275      * dst = src & bimm and sets condition flags.
1276      *
1277      * @param size register size. Has to be 32 or 64.
1278      * @param dst general purpose register. May not be null or stack-pointer.
1279      * @param src general purpose register. May not be null or stack-pointer.
1280      * @param bimm logical immediate. See {@link LogicalImmediateTable} for exact definition.
1281      */
1282     public void ands(int size, Register dst, Register src, long bimm) {
1283         assert !dst.equals(sp);
1284         assert !src.equals(sp);
1285         logicalImmInstruction(ANDS, dst, src, bimm, generalFromSize(size));
1286     }
1287 
1288     /**
1289      * dst = src ^ bimm.
1290      *
1291      * @param size register size. Has to be 32 or 64.
1292      * @param dst general purpose register. May not be null or zero-register.
1293      * @param src general purpose register. May not be null or stack-pointer.
1294      * @param bimm logical immediate. See {@link LogicalImmediateTable} for exact definition.
1295      */
1296     public void eor(int size, Register dst, Register src, long bimm) {
1297         assert !dst.equals(zr);
1298         assert !src.equals(sp);
1299         logicalImmInstruction(EOR, dst, src, bimm, generalFromSize(size));
1300     }
1301 
1302     /**
1303      * dst = src | bimm.
1304      *
1305      * @param size register size. Has to be 32 or 64.
1306      * @param dst general purpose register. May not be null or zero-register.
1307      * @param src general purpose register. May not be null or stack-pointer.
1308      * @param bimm logical immediate. See {@link LogicalImmediateTable} for exact definition.
1309      */
1310     protected void orr(int size, Register dst, Register src, long bimm) {
1311         assert !dst.equals(zr);
1312         assert !src.equals(sp);
1313         logicalImmInstruction(ORR, dst, src, bimm, generalFromSize(size));
1314     }
1315 
1316     private void logicalImmInstruction(Instruction instr, Register dst, Register src, long bimm, InstructionType type) {
1317         // Mask higher bits off, since we always pass longs around even for the 32-bit instruction.
1318         long bimmValue;
1319         if (type == General32) {
1320             assert (bimm >> 32) == 0 || (bimm >> 32) == -1L : "Higher order bits for 32-bit instruction must either all be 0 or 1.";
1321             bimmValue = bimm & NumUtil.getNbitNumberLong(32);
1322         } else {
1323             bimmValue = bimm;
1324         }
1325         int immEncoding = LogicalImmediateTable.getLogicalImmEncoding(type == General64, bimmValue);
1326         emitInt(type.encoding | instr.encoding | LogicalImmOp | immEncoding | rd(dst) | rs1(src));
1327     }
1328 
1329     /* Move (wide immediate) (5.4.3) */
1330 
1331     /**
1332      * dst = uimm16 << shiftAmt.
1333      *
1334      * @param size register size. Has to be 32 or 64.
1335      * @param dst general purpose register. May not be null, stackpointer or zero-register.
1336      * @param uimm16 16-bit unsigned immediate
1337      * @param shiftAmt amount by which uimm16 is left shifted. Can be any multiple of 16 smaller
1338      *            than size.
1339      */
1340     protected void movz(int size, Register dst, int uimm16, int shiftAmt) {
1341         moveWideImmInstruction(MOVZ, dst, uimm16, shiftAmt, generalFromSize(size));
1342     }
1343 
1344     /**
1345      * dst = ~(uimm16 << shiftAmt).
1346      *
1347      * @param size register size. Has to be 32 or 64.
1348      * @param dst general purpose register. May not be null, stackpointer or zero-register.
1349      * @param uimm16 16-bit unsigned immediate
1350      * @param shiftAmt amount by which uimm16 is left shifted. Can be any multiple of 16 smaller
1351      *            than size.
1352      */
1353     protected void movn(int size, Register dst, int uimm16, int shiftAmt) {
1354         moveWideImmInstruction(MOVN, dst, uimm16, shiftAmt, generalFromSize(size));
1355     }
1356 
1357     /**
1358      * dst<pos+15:pos> = uimm16.
1359      *
1360      * @param size register size. Has to be 32 or 64.
1361      * @param dst general purpose register. May not be null, stackpointer or zero-register.
1362      * @param uimm16 16-bit unsigned immediate
1363      * @param pos position into which uimm16 is inserted. Can be any multiple of 16 smaller than
1364      *            size.
1365      */
1366     protected void movk(int size, Register dst, int uimm16, int pos) {
1367         moveWideImmInstruction(MOVK, dst, uimm16, pos, generalFromSize(size));
1368     }
1369 
1370     private void moveWideImmInstruction(Instruction instr, Register dst, int uimm16, int shiftAmt, InstructionType type) {
1371         assert dst.getRegisterCategory().equals(CPU);
1372         assert NumUtil.isUnsignedNbit(16, uimm16) : "Immediate has to be unsigned 16bit";
1373         assert shiftAmt == 0 || shiftAmt == 16 || (type == InstructionType.General64 && (shiftAmt == 32 || shiftAmt == 48)) : "Invalid shift amount: " + shiftAmt;
1374         int shiftValue = shiftAmt >> 4;
1375         emitInt(type.encoding | instr.encoding | MoveWideImmOp | rd(dst) | uimm16 << MoveWideImmOffset | shiftValue << MoveWideShiftOffset);
1376     }
1377 
1378     /* Bitfield Operations (5.4.5) */
1379 
1380     /**
1381      * Bitfield move.
1382      *
1383      * @param size register size. Has to be 32 or 64.
1384      * @param dst general purpose register. May not be null, stackpointer or zero-register.
1385      * @param src general purpose register. May not be null, stackpointer or zero-register.
1386      * @param r must be in the range 0 to size - 1
1387      * @param s must be in the range 0 to size - 1
1388      */
1389     protected void bfm(int size, Register dst, Register src, int r, int s) {
1390         bitfieldInstruction(BFM, dst, src, r, s, generalFromSize(size));
1391     }
1392 
1393     /**
1394      * Unsigned bitfield move.
1395      *
1396      * @param size register size. Has to be 32 or 64.
1397      * @param dst general purpose register. May not be null, stackpointer or zero-register.
1398      * @param src general purpose register. May not be null, stackpointer or zero-register.
1399      * @param r must be in the range 0 to size - 1
1400      * @param s must be in the range 0 to size - 1
1401      */
1402     protected void ubfm(int size, Register dst, Register src, int r, int s) {
1403         bitfieldInstruction(UBFM, dst, src, r, s, generalFromSize(size));
1404     }
1405 
1406     /**
1407      * Signed bitfield move.
1408      *
1409      * @param size register size. Has to be 32 or 64.
1410      * @param dst general purpose register. May not be null, stackpointer or zero-register.
1411      * @param src general purpose register. May not be null, stackpointer or zero-register.
1412      * @param r must be in the range 0 to size - 1
1413      * @param s must be in the range 0 to size - 1
1414      */
1415     protected void sbfm(int size, Register dst, Register src, int r, int s) {
1416         bitfieldInstruction(SBFM, dst, src, r, s, generalFromSize(size));
1417     }
1418 
1419     private void bitfieldInstruction(Instruction instr, Register dst, Register src, int r, int s, InstructionType type) {
1420         assert !dst.equals(sp) && !dst.equals(zr);
1421         assert !src.equals(sp) && !src.equals(zr);
1422         assert s >= 0 && s < type.width && r >= 0 && r < type.width;
1423         int sf = type == General64 ? 1 << ImmediateSizeOffset : 0;
1424         emitInt(type.encoding | instr.encoding | BitfieldImmOp | sf | r << ImmediateRotateOffset | s << ImmediateOffset | rd(dst) | rs1(src));
1425     }
1426 
1427     /* Extract (Immediate) (5.4.6) */
1428 
1429     /**
1430      * Extract. dst = src1:src2<lsb+31:lsb>
1431      *
1432      * @param size register size. Has to be 32 or 64.
1433      * @param dst general purpose register. May not be null or stackpointer.
1434      * @param src1 general purpose register. May not be null or stackpointer.
1435      * @param src2 general purpose register. May not be null or stackpointer.
1436      * @param lsb must be in range 0 to size - 1.
1437      */
1438     protected void extr(int size, Register dst, Register src1, Register src2, int lsb) {
1439         assert !dst.equals(sp);
1440         assert !src1.equals(sp);
1441         assert !src2.equals(sp);
1442         InstructionType type = generalFromSize(size);
1443         assert lsb >= 0 && lsb < type.width;
1444         int sf = type == General64 ? 1 << ImmediateSizeOffset : 0;
1445         emitInt(type.encoding | EXTR.encoding | sf | lsb << ImmediateOffset | rd(dst) | rs1(src1) | rs2(src2));
1446     }
1447 
1448     /* Arithmetic (shifted register) (5.5.1) */
1449 
1450     /**
1451      * dst = src1 + shiftType(src2, imm).
1452      *
1453      * @param size register size. Has to be 32 or 64.
1454      * @param dst general purpose register. May not be null or stackpointer.
1455      * @param src1 general purpose register. May not be null or stackpointer.
1456      * @param src2 general purpose register. May not be null or stackpointer.
1457      * @param shiftType any type but ROR.
1458      * @param imm must be in range 0 to size - 1.
1459      */
1460     protected void add(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
1461         addSubShiftedInstruction(ADD, dst, src1, src2, shiftType, imm, generalFromSize(size));
1462     }
1463 
1464     /**
1465      * dst = src1 + shiftType(src2, imm) and sets condition flags.
1466      *
1467      * @param size register size. Has to be 32 or 64.
1468      * @param dst general purpose register. May not be null or stackpointer.
1469      * @param src1 general purpose register. May not be null or stackpointer.
1470      * @param src2 general purpose register. May not be null or stackpointer.
1471      * @param shiftType any type but ROR.
1472      * @param imm must be in range 0 to size - 1.
1473      */
1474     protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
1475         addSubShiftedInstruction(ADDS, dst, src1, src2, shiftType, imm, generalFromSize(size));
1476     }
1477 
1478     /**
1479      * dst = src1 - shiftType(src2, imm).
1480      *
1481      * @param size register size. Has to be 32 or 64.
1482      * @param dst general purpose register. May not be null or stackpointer.
1483      * @param src1 general purpose register. May not be null or stackpointer.
1484      * @param src2 general purpose register. May not be null or stackpointer.
1485      * @param shiftType any type but ROR.
1486      * @param imm must be in range 0 to size - 1.
1487      */
1488     protected void sub(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
1489         addSubShiftedInstruction(SUB, dst, src1, src2, shiftType, imm, generalFromSize(size));
1490     }
1491 
1492     /**
1493      * dst = src1 - shiftType(src2, imm) and sets condition flags.
1494      *
1495      * @param size register size. Has to be 32 or 64.
1496      * @param dst general purpose register. May not be null or stackpointer.
1497      * @param src1 general purpose register. May not be null or stackpointer.
1498      * @param src2 general purpose register. May not be null or stackpointer.
1499      * @param shiftType any type but ROR.
1500      * @param imm must be in range 0 to size - 1.
1501      */
1502     protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
1503         addSubShiftedInstruction(SUBS, dst, src1, src2, shiftType, imm, generalFromSize(size));
1504     }
1505 
1506     private void addSubShiftedInstruction(Instruction instr, Register dst, Register src1, Register src2, ShiftType shiftType, int imm, InstructionType type) {
1507         assert shiftType != ShiftType.ROR;
1508         assert imm >= 0 && imm < type.width;
1509         emitInt(type.encoding | instr.encoding | AddSubShiftedOp | imm << ImmediateOffset | shiftType.encoding << ShiftTypeOffset | rd(dst) | rs1(src1) | rs2(src2));
1510     }
1511 
1512     /* Arithmetic (extended register) (5.5.2) */
1513     /**
1514      * dst = src1 + extendType(src2) << imm.
1515      *
1516      * @param size register size. Has to be 32 or 64.
1517      * @param dst general purpose register. May not be null or zero-register..
1518      * @param src1 general purpose register. May not be null or zero-register.
1519      * @param src2 general purpose register. May not be null or stackpointer.
1520      * @param extendType defines how src2 is extended to the same size as src1.
1521      * @param shiftAmt must be in range 0 to 4.
1522      */
1523     public void add(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
1524         assert !dst.equals(zr);
1525         assert !src1.equals(zr);
1526         assert !src2.equals(sp);
1527         addSubExtendedInstruction(ADD, dst, src1, src2, extendType, shiftAmt, generalFromSize(size));
1528     }
1529 
1530     /**
1531      * dst = src1 + extendType(src2) << imm and sets condition flags.
1532      *
1533      * @param size register size. Has to be 32 or 64.
1534      * @param dst general purpose register. May not be null or stackpointer..
1535      * @param src1 general purpose register. May not be null or zero-register.
1536      * @param src2 general purpose register. May not be null or stackpointer.
1537      * @param extendType defines how src2 is extended to the same size as src1.
1538      * @param shiftAmt must be in range 0 to 4.
1539      */
1540     protected void adds(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
1541         assert !dst.equals(sp);
1542         assert !src1.equals(zr);
1543         assert !src2.equals(sp);
1544         addSubExtendedInstruction(ADDS, dst, src1, src2, extendType, shiftAmt, generalFromSize(size));
1545     }
1546 
1547     /**
1548      * dst = src1 - extendType(src2) << imm.
1549      *
1550      * @param size register size. Has to be 32 or 64.
1551      * @param dst general purpose register. May not be null or zero-register..
1552      * @param src1 general purpose register. May not be null or zero-register.
1553      * @param src2 general purpose register. May not be null or stackpointer.
1554      * @param extendType defines how src2 is extended to the same size as src1.
1555      * @param shiftAmt must be in range 0 to 4.
1556      */
1557     protected void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
1558         assert !dst.equals(zr);
1559         assert !src1.equals(zr);
1560         assert !src2.equals(sp);
1561         addSubExtendedInstruction(SUB, dst, src1, src2, extendType, shiftAmt, generalFromSize(size));
1562     }
1563 
1564     /**
1565      * dst = src1 - extendType(src2) << imm and sets flags.
1566      *
1567      * @param size register size. Has to be 32 or 64.
1568      * @param dst general purpose register. May not be null or stackpointer..
1569      * @param src1 general purpose register. May not be null or zero-register.
1570      * @param src2 general purpose register. May not be null or stackpointer.
1571      * @param extendType defines how src2 is extended to the same size as src1.
1572      * @param shiftAmt must be in range 0 to 4.
1573      */
1574     protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
1575         assert !dst.equals(sp);
1576         assert !src1.equals(zr);
1577         assert !src2.equals(sp);
1578         addSubExtendedInstruction(SUBS, dst, src1, src2, extendType, shiftAmt, generalFromSize(size));
1579     }
1580 
1581     private void addSubExtendedInstruction(Instruction instr, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt, InstructionType type) {
1582         assert shiftAmt >= 0 && shiftAmt <= 4;
1583         emitInt(type.encoding | instr.encoding | AddSubExtendedOp | shiftAmt << ImmediateOffset | extendType.encoding << ExtendTypeOffset | rd(dst) | rs1(src1) | rs2(src2));
1584     }
1585 
1586     /* Logical (shifted register) (5.5.3) */
1587     /**
1588      * dst = src1 & shiftType(src2, imm).
1589      *
1590      * @param size register size. Has to be 32 or 64.
1591      * @param dst general purpose register. May not be null or stackpointer.
1592      * @param src1 general purpose register. May not be null or stackpointer.
1593      * @param src2 general purpose register. May not be null or stackpointer.
1594      * @param shiftType all types allowed, may not be null.
1595      * @param shiftAmt must be in range 0 to size - 1.
1596      */
1597     protected void and(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1598         logicalRegInstruction(AND, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1599     }
1600 
1601     /**
1602      * dst = src1 & shiftType(src2, imm) and sets condition flags.
1603      *
1604      * @param size register size. Has to be 32 or 64.
1605      * @param dst general purpose register. May not be null or stackpointer.
1606      * @param src1 general purpose register. May not be null or stackpointer.
1607      * @param src2 general purpose register. May not be null or stackpointer.
1608      * @param shiftType all types allowed, may not be null.
1609      * @param shiftAmt must be in range 0 to size - 1.
1610      */
1611     protected void ands(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1612         logicalRegInstruction(ANDS, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1613     }
1614 
1615     /**
1616      * dst = src1 & ~(shiftType(src2, imm)).
1617      *
1618      * @param size register size. Has to be 32 or 64.
1619      * @param dst general purpose register. May not be null or stackpointer.
1620      * @param src1 general purpose register. May not be null or stackpointer.
1621      * @param src2 general purpose register. May not be null or stackpointer.
1622      * @param shiftType all types allowed, may not be null.
1623      * @param shiftAmt must be in range 0 to size - 1.
1624      */
1625     protected void bic(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1626         logicalRegInstruction(BIC, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1627     }
1628 
1629     /**
1630      * dst = src1 & ~(shiftType(src2, imm)) and sets condition flags.
1631      *
1632      * @param size register size. Has to be 32 or 64.
1633      * @param dst general purpose register. May not be null or stackpointer.
1634      * @param src1 general purpose register. May not be null or stackpointer.
1635      * @param src2 general purpose register. May not be null or stackpointer.
1636      * @param shiftType all types allowed, may not be null.
1637      * @param shiftAmt must be in range 0 to size - 1.
1638      */
1639     protected void bics(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1640         logicalRegInstruction(BICS, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1641     }
1642 
1643     /**
1644      * dst = src1 ^ ~(shiftType(src2, imm)).
1645      *
1646      * @param size register size. Has to be 32 or 64.
1647      * @param dst general purpose register. May not be null or stackpointer.
1648      * @param src1 general purpose register. May not be null or stackpointer.
1649      * @param src2 general purpose register. May not be null or stackpointer.
1650      * @param shiftType all types allowed, may not be null.
1651      * @param shiftAmt must be in range 0 to size - 1.
1652      */
1653     protected void eon(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1654         logicalRegInstruction(EON, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1655     }
1656 
1657     /**
1658      * dst = src1 ^ shiftType(src2, imm).
1659      *
1660      * @param size register size. Has to be 32 or 64.
1661      * @param dst general purpose register. May not be null or stackpointer.
1662      * @param src1 general purpose register. May not be null or stackpointer.
1663      * @param src2 general purpose register. May not be null or stackpointer.
1664      * @param shiftType all types allowed, may not be null.
1665      * @param shiftAmt must be in range 0 to size - 1.
1666      */
1667     protected void eor(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1668         logicalRegInstruction(EOR, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1669     }
1670 
1671     /**
1672      * dst = src1 | shiftType(src2, imm).
1673      *
1674      * @param size register size. Has to be 32 or 64.
1675      * @param dst general purpose register. May not be null or stackpointer.
1676      * @param src1 general purpose register. May not be null or stackpointer.
1677      * @param src2 general purpose register. May not be null or stackpointer.
1678      * @param shiftType all types allowed, may not be null.
1679      * @param shiftAmt must be in range 0 to size - 1.
1680      */
1681     protected void orr(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1682         logicalRegInstruction(ORR, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1683     }
1684 
1685     /**
1686      * dst = src1 | ~(shiftType(src2, imm)).
1687      *
1688      * @param size register size. Has to be 32 or 64.
1689      * @param dst general purpose register. May not be null or stackpointer.
1690      * @param src1 general purpose register. May not be null or stackpointer.
1691      * @param src2 general purpose register. May not be null or stackpointer.
1692      * @param shiftType all types allowed, may not be null.
1693      * @param shiftAmt must be in range 0 to size - 1.
1694      */
1695     protected void orn(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt) {
1696         logicalRegInstruction(ORN, dst, src1, src2, shiftType, shiftAmt, generalFromSize(size));
1697     }
1698 
1699     private void logicalRegInstruction(Instruction instr, Register dst, Register src1, Register src2, ShiftType shiftType, int shiftAmt, InstructionType type) {
1700         assert !dst.equals(sp);
1701         assert !src1.equals(sp);
1702         assert !src2.equals(sp);
1703         assert shiftAmt >= 0 && shiftAmt < type.width;
1704         emitInt(type.encoding | instr.encoding | LogicalShiftOp | shiftAmt << ImmediateOffset | shiftType.encoding << ShiftTypeOffset | rd(dst) | rs1(src1) | rs2(src2));
1705     }
1706 
1707     /* Variable Shift (5.5.4) */
1708     /**
1709      * dst = src1 >> (src2 & log2(size)).
1710      *
1711      * @param size register size. Has to be 32 or 64.
1712      * @param dst general purpose register. May not be null or stackpointer.
1713      * @param src1 general purpose register. May not be null or stackpointer.
1714      * @param src2 general purpose register. May not be null or stackpointer.
1715      */
1716     protected void asr(int size, Register dst, Register src1, Register src2) {
1717         dataProcessing2SourceOp(ASRV, dst, src1, src2, generalFromSize(size));
1718     }
1719 
1720     /**
1721      * dst = src1 << (src2 & log2(size)).
1722      *
1723      * @param size register size. Has to be 32 or 64.
1724      * @param dst general purpose register. May not be null or stackpointer.
1725      * @param src1 general purpose register. May not be null or stackpointer.
1726      * @param src2 general purpose register. May not be null or stackpointer.
1727      */
1728     protected void lsl(int size, Register dst, Register src1, Register src2) {
1729         dataProcessing2SourceOp(LSLV, dst, src1, src2, generalFromSize(size));
1730     }
1731 
1732     /**
1733      * dst = src1 >>> (src2 & log2(size)).
1734      *
1735      * @param size register size. Has to be 32 or 64.
1736      * @param dst general purpose register. May not be null or stackpointer.
1737      * @param src1 general purpose register. May not be null or stackpointer.
1738      * @param src2 general purpose register. May not be null or stackpointer.
1739      */
1740     protected void lsr(int size, Register dst, Register src1, Register src2) {
1741         dataProcessing2SourceOp(LSRV, dst, src1, src2, generalFromSize(size));
1742     }
1743 
1744     /**
1745      * dst = rotateRight(src1, (src2 & log2(size))).
1746      *
1747      * @param size register size. Has to be 32 or 64.
1748      * @param dst general purpose register. May not be null or stackpointer.
1749      * @param src1 general purpose register. May not be null or stackpointer.
1750      * @param src2 general purpose register. May not be null or stackpointer.
1751      */
1752     protected void ror(int size, Register dst, Register src1, Register src2) {
1753         dataProcessing2SourceOp(RORV, dst, src1, src2, generalFromSize(size));
1754     }
1755 
1756     /* Bit Operations (5.5.5) */
1757 
1758     /**
1759      * Counts leading sign bits. Sets Wd to the number of consecutive bits following the topmost bit
1760      * in dst, that are the same as the topmost bit. The count does not include the topmost bit
1761      * itself , so the result will be in the range 0 to size-1 inclusive.
1762      *
1763      * @param size register size. Has to be 32 or 64.
1764      * @param dst general purpose register. May not be null, zero-register or the stackpointer.
1765      * @param src source register. May not be null, zero-register or the stackpointer.
1766      */
1767     protected void cls(int size, Register dst, Register src) {
1768         dataProcessing1SourceOp(CLS, dst, src, generalFromSize(size));
1769     }
1770 
1771     /**
1772      * Counts leading zeros.
1773      *
1774      * @param size register size. Has to be 32 or 64.
1775      * @param dst general purpose register. May not be null, zero-register or the stackpointer.
1776      * @param src source register. May not be null, zero-register or the stackpointer.
1777      */
1778     public void clz(int size, Register dst, Register src) {
1779         dataProcessing1SourceOp(CLZ, dst, src, generalFromSize(size));
1780     }
1781 
1782     /**
1783      * Reverses bits.
1784      *
1785      * @param size register size. Has to be 32 or 64.
1786      * @param dst general purpose register. May not be null, zero-register or the stackpointer.
1787      * @param src source register. May not be null, zero-register or the stackpointer.
1788      */
1789     protected void rbit(int size, Register dst, Register src) {
1790         dataProcessing1SourceOp(RBIT, dst, src, generalFromSize(size));
1791     }
1792 
1793     /**
1794      * Reverses bytes.
1795      *
1796      * @param size register size. Has to be 32 or 64.
1797      * @param dst general purpose register. May not be null or the stackpointer.
1798      * @param src source register. May not be null or the stackpointer.
1799      */
1800     public void rev(int size, Register dst, Register src) {
1801         if (size == 64) {
1802             dataProcessing1SourceOp(REVX, dst, src, generalFromSize(size));
1803         } else {
1804             assert size == 32;
1805             dataProcessing1SourceOp(REVW, dst, src, generalFromSize(size));
1806         }
1807     }
1808 
1809     /* Conditional Data Processing (5.5.6) */
1810 
1811     /**
1812      * Conditional select. dst = src1 if condition else src2.
1813      *
1814      * @param size register size. Has to be 32 or 64.
1815      * @param dst general purpose register. May not be null or the stackpointer.
1816      * @param src1 general purpose register. May not be null or the stackpointer.
1817      * @param src2 general purpose register. May not be null or the stackpointer.
1818      * @param condition any condition flag. May not be null.
1819      */
1820     protected void csel(int size, Register dst, Register src1, Register src2, ConditionFlag condition) {
1821         conditionalSelectInstruction(CSEL, dst, src1, src2, condition, generalFromSize(size));
1822     }
1823 
1824     /**
1825      * Conditional select negate. dst = src1 if condition else -src2.
1826      *
1827      * @param size register size. Has to be 32 or 64.
1828      * @param dst general purpose register. May not be null or the stackpointer.
1829      * @param src1 general purpose register. May not be null or the stackpointer.
1830      * @param src2 general purpose register. May not be null or the stackpointer.
1831      * @param condition any condition flag. May not be null.
1832      */
1833     protected void csneg(int size, Register dst, Register src1, Register src2, ConditionFlag condition) {
1834         conditionalSelectInstruction(CSNEG, dst, src1, src2, condition, generalFromSize(size));
1835     }
1836 
1837     /**
1838      * Conditional increase. dst = src1 if condition else src2 + 1.
1839      *
1840      * @param size register size. Has to be 32 or 64.
1841      * @param dst general purpose register. May not be null or the stackpointer.
1842      * @param src1 general purpose register. May not be null or the stackpointer.
1843      * @param src2 general purpose register. May not be null or the stackpointer.
1844      * @param condition any condition flag. May not be null.
1845      */
1846     protected void csinc(int size, Register dst, Register src1, Register src2, ConditionFlag condition) {
1847         conditionalSelectInstruction(CSINC, dst, src1, src2, condition, generalFromSize(size));
1848     }
1849 
1850     private void conditionalSelectInstruction(Instruction instr, Register dst, Register src1, Register src2, ConditionFlag condition, InstructionType type) {
1851         assert !dst.equals(sp);
1852         assert !src1.equals(sp);
1853         assert !src2.equals(sp);
1854         emitInt(type.encoding | instr.encoding | ConditionalSelectOp | rd(dst) | rs1(src1) | rs2(src2) | condition.encoding << ConditionalConditionOffset);
1855     }
1856 
1857     /* Integer Multiply/Divide (5.6) */
1858 
1859     /**
1860      * dst = src1 * src2 + src3.
1861      *
1862      * @param size register size. Has to be 32 or 64.
1863      * @param dst general purpose register. May not be null or the stackpointer.
1864      * @param src1 general purpose register. May not be null or the stackpointer.
1865      * @param src2 general purpose register. May not be null or the stackpointer.
1866      * @param src3 general purpose register. May not be null or the stackpointer.
1867      */
1868     protected void madd(int size, Register dst, Register src1, Register src2, Register src3) {
1869         mulInstruction(MADD, dst, src1, src2, src3, generalFromSize(size));
1870     }
1871 
1872     /**
1873      * dst = src3 - src1 * src2.
1874      *
1875      * @param size register size. Has to be 32 or 64.
1876      * @param dst general purpose register. May not be null or the stackpointer.
1877      * @param src1 general purpose register. May not be null or the stackpointer.
1878      * @param src2 general purpose register. May not be null or the stackpointer.
1879      * @param src3 general purpose register. May not be null or the stackpointer.
1880      */
1881     protected void msub(int size, Register dst, Register src1, Register src2, Register src3) {
1882         mulInstruction(MSUB, dst, src1, src2, src3, generalFromSize(size));
1883     }
1884 
1885     /**
1886      * Signed multiply high. dst = (src1 * src2)[127:64]
1887      *
1888      * @param dst general purpose register. May not be null or the stackpointer.
1889      * @param src1 general purpose register. May not be null or the stackpointer.
1890      * @param src2 general purpose register. May not be null or the stackpointer.
1891      */
1892     protected void smulh(Register dst, Register src1, Register src2) {
1893         assert !dst.equals(sp);
1894         assert !src1.equals(sp);
1895         assert !src2.equals(sp);
1896         emitInt(0b10011011010 << 21 | dst.encoding | rs1(src1) | rs2(src2) | 0b011111 << ImmediateOffset);
1897     }
1898 
1899     /**
1900      * unsigned multiply high. dst = (src1 * src2)[127:64]
1901      *
1902      * @param dst general purpose register. May not be null or the stackpointer.
1903      * @param src1 general purpose register. May not be null or the stackpointer.
1904      * @param src2 general purpose register. May not be null or the stackpointer.
1905      */
1906     protected void umulh(Register dst, Register src1, Register src2) {
1907         assert !dst.equals(sp);
1908         assert !src1.equals(sp);
1909         assert !src2.equals(sp);
1910         emitInt(0b10011011110 << 21 | dst.encoding | rs1(src1) | rs2(src2) | 0b011111 << ImmediateOffset);
1911     }
1912 
1913     /**
1914      * unsigned multiply add-long. xDst = xSrc3 + (wSrc1 * wSrc2)
1915      *
1916      * @param dst general purpose register. May not be null or the stackpointer.
1917      * @param src1 general purpose register. May not be null or the stackpointer.
1918      * @param src2 general purpose register. May not be null or the stackpointer.
1919      * @param src3 general purpose register. May not be null or the stackpointer.
1920      */
1921     protected void umaddl(Register dst, Register src1, Register src2, Register src3) {
1922         assert !dst.equals(sp);
1923         assert !src1.equals(sp);
1924         assert !src2.equals(sp);
1925         assert !src3.equals(sp);
1926         emitInt(0b10011011101 << 21 | dst.encoding | rs1(src1) | rs2(src2) | 0b011111 << ImmediateOffset);
1927     }
1928 
1929     /**
1930      * signed multiply add-long. xDst = xSrc3 + (wSrc1 * wSrc2)
1931      *
1932      * @param dst general purpose register. May not be null or the stackpointer.
1933      * @param src1 general purpose register. May not be null or the stackpointer.
1934      * @param src2 general purpose register. May not be null or the stackpointer.
1935      * @param src3 general purpose register. May not be null or the stackpointer.
1936      */
1937     protected void smaddl(Register dst, Register src1, Register src2, Register src3) {
1938         assert !dst.equals(sp);
1939         assert !src1.equals(sp);
1940         assert !src2.equals(sp);
1941         assert !src3.equals(sp);
1942         emitInt(0b10011011001 << 21 | dst.encoding | rs1(src1) | rs2(src2) | rs3(src3));
1943     }
1944 
1945     private void mulInstruction(Instruction instr, Register dst, Register src1, Register src2, Register src3, InstructionType type) {
1946         assert !dst.equals(sp);
1947         assert !src1.equals(sp);
1948         assert !src2.equals(sp);
1949         assert !src3.equals(sp);
1950         emitInt(type.encoding | instr.encoding | MulOp | rd(dst) | rs1(src1) | rs2(src2) | rs3(src3));
1951     }
1952 
1953     /**
1954      * Signed divide. dst = src1 / src2.
1955      *
1956      * @param size register size. Has to be 32 or 64.
1957      * @param dst general purpose register. May not be null or the stackpointer.
1958      * @param src1 general purpose register. May not be null or the stackpointer.
1959      * @param src2 general purpose register. May not be null or the stackpointer.
1960      */
1961     public void sdiv(int size, Register dst, Register src1, Register src2) {
1962         dataProcessing2SourceOp(SDIV, dst, src1, src2, generalFromSize(size));
1963     }
1964 
1965     /**
1966      * Unsigned divide. dst = src1 / src2.
1967      *
1968      * @param size register size. Has to be 32 or 64.
1969      * @param dst general purpose register. May not be null or the stackpointer.
1970      * @param src1 general purpose register. May not be null or the stackpointer.
1971      * @param src2 general purpose register. May not be null or the stackpointer.
1972      */
1973     public void udiv(int size, Register dst, Register src1, Register src2) {
1974         dataProcessing2SourceOp(UDIV, dst, src1, src2, generalFromSize(size));
1975     }
1976 
1977     private void dataProcessing1SourceOp(Instruction instr, Register dst, Register src, InstructionType type) {
1978         emitInt(type.encoding | instr.encoding | DataProcessing1SourceOp | rd(dst) | rs1(src));
1979     }
1980 
1981     private void dataProcessing2SourceOp(Instruction instr, Register dst, Register src1, Register src2, InstructionType type) {
1982         assert !dst.equals(sp);
1983         assert !src1.equals(sp);
1984         assert !src2.equals(sp);
1985         emitInt(type.encoding | instr.encoding | DataProcessing2SourceOp | rd(dst) | rs1(src1) | rs2(src2));
1986     }
1987 
1988     /* Floating point operations */
1989 
1990     /* Load-Store Single FP register (5.7.1.1) */
1991     /**
1992      * Floating point load.
1993      *
1994      * @param size number of bits read from memory into rt. Must be 32 or 64.
1995      * @param rt floating point register. May not be null.
1996      * @param address all addressing modes allowed. May not be null.
1997      */
1998     public void fldr(int size, Register rt, AArch64Address address) {
1999         assert rt.getRegisterCategory().equals(SIMD);
2000         assert size == 32 || size == 64;
2001         int transferSize = NumUtil.log2Ceil(size / 8);
2002         loadStoreInstruction(LDR, rt, address, InstructionType.FP32, transferSize);
2003     }
2004 
2005     /**
2006      * Floating point store.
2007      *
2008      * @param size number of bits read from memory into rt. Must be 32 or 64.
2009      * @param rt floating point register. May not be null.
2010      * @param address all addressing modes allowed. May not be null.
2011      */
2012     public void fstr(int size, Register rt, AArch64Address address) {
2013         assert rt.getRegisterCategory().equals(SIMD);
2014         assert size == 32 || size == 64;
2015         int transferSize = NumUtil.log2Ceil(size / 8);
2016         loadStoreInstruction(STR, rt, address, InstructionType.FP64, transferSize);
2017     }
2018 
2019     /* Floating-point Move (register) (5.7.2) */
2020 
2021     /**
2022      * Floating point move.
2023      *
2024      * @param size register size. Has to be 32 or 64.
2025      * @param dst floating point register. May not be null.
2026      * @param src floating point register. May not be null.
2027      */
2028     protected void fmov(int size, Register dst, Register src) {
2029         fpDataProcessing1Source(FMOV, dst, src, floatFromSize(size));
2030     }
2031 
2032     /**
2033      * Move size bits from floating point register unchanged to general purpose register.
2034      *
2035      * @param size number of bits read from memory into rt. Must be 32 or 64.
2036      * @param dst general purpose register. May not be null, stack-pointer or zero-register
2037      * @param src floating point register. May not be null.
2038      */
2039     protected void fmovFpu2Cpu(int size, Register dst, Register src) {
2040         assert dst.getRegisterCategory().equals(CPU);
2041         assert src.getRegisterCategory().equals(SIMD);
2042         fmovCpuFpuInstruction(dst, src, size == 64, Instruction.FMOVFPU2CPU);
2043     }
2044 
2045     /**
2046      * Move size bits from general purpose register unchanged to floating point register.
2047      *
2048      * @param size register size. Has to be 32 or 64.
2049      * @param dst floating point register. May not be null.
2050      * @param src general purpose register. May not be null or stack-pointer.
2051      */
2052     protected void fmovCpu2Fpu(int size, Register dst, Register src) {
2053         assert dst.getRegisterCategory().equals(SIMD);
2054         assert src.getRegisterCategory().equals(CPU);
2055         fmovCpuFpuInstruction(dst, src, size == 64, Instruction.FMOVCPU2FPU);
2056     }
2057 
2058     private void fmovCpuFpuInstruction(Register dst, Register src, boolean is64bit, Instruction instr) {
2059         int sf = is64bit ? FP64.encoding | General64.encoding : FP32.encoding | General32.encoding;
2060         emitInt(sf | instr.encoding | FpConvertOp | rd(dst) | rs1(src));
2061     }
2062 
2063     /* Floating-point Move (immediate) (5.7.3) */
2064 
2065     /**
2066      * Move immediate into register.
2067      *
2068      * @param size register size. Has to be 32 or 64.
2069      * @param dst floating point register. May not be null.
2070      * @param imm immediate that is loaded into dst. If size is 32 only float immediates can be
2071      *            loaded, i.e. (float) imm == imm must be true. In all cases
2072      *            {@code isFloatImmediate}, respectively {@code #isDoubleImmediate} must be true
2073      *            depending on size.
2074      */
2075     protected void fmov(int size, Register dst, double imm) {
2076         assert dst.getRegisterCategory().equals(SIMD);
2077         InstructionType type = floatFromSize(size);
2078         int immEncoding;
2079         if (type == FP64) {
2080             immEncoding = getDoubleImmediate(imm);
2081         } else {
2082             assert imm == (float) imm : "float mov must use an immediate that can be represented using a float.";
2083             immEncoding = getFloatImmediate((float) imm);
2084         }
2085         emitInt(type.encoding | FMOV.encoding | FpImmOp | immEncoding | rd(dst));
2086     }
2087 
2088     private static int getDoubleImmediate(double imm) {
2089         assert isDoubleImmediate(imm);
2090         // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2091         // 0000.0000.0000.0000.0000.0000.0000.0000
2092         long repr = Double.doubleToRawLongBits(imm);
2093         int a = (int) (repr >>> 63) << 7;
2094         int b = (int) ((repr >>> 61) & 0x1) << 6;
2095         int cToH = (int) (repr >>> 48) & 0x3f;
2096         return (a | b | cToH) << FpImmOffset;
2097     }
2098 
2099     protected static boolean isDoubleImmediate(double imm) {
2100         // Valid values will have the form:
2101         // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2102         // 0000.0000.0000.0000.0000.0000.0000.0000
2103         long bits = Double.doubleToRawLongBits(imm);
2104         // lower 48 bits are cleared
2105         if ((bits & NumUtil.getNbitNumberLong(48)) != 0) {
2106             return false;
2107         }
2108         // bits[61..54] are all set or all cleared.
2109         long pattern = (bits >> 54) & NumUtil.getNbitNumberLong(7);
2110         if (pattern != 0 && pattern != NumUtil.getNbitNumberLong(7)) {
2111             return false;
2112         }
2113         // bits[62] and bits[61] are opposites.
2114         return ((bits ^ (bits << 1)) & (1L << 62)) != 0;
2115     }
2116 
2117     private static int getFloatImmediate(float imm) {
2118         assert isFloatImmediate(imm);
2119         // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
2120         int repr = Float.floatToRawIntBits(imm);
2121         int a = (repr >>> 31) << 7;
2122         int b = ((repr >>> 29) & 0x1) << 6;
2123         int cToH = (repr >>> 19) & NumUtil.getNbitNumberInt(6);
2124         return (a | b | cToH) << FpImmOffset;
2125     }
2126 
2127     protected static boolean isFloatImmediate(float imm) {
2128         // Valid values will have the form:
2129         // aBbb.bbbc.defg.h000.0000.0000.0000.0000
2130         int bits = Float.floatToRawIntBits(imm);
2131         // lower 20 bits are cleared.
2132         if ((bits & NumUtil.getNbitNumberInt(19)) != 0) {
2133             return false;
2134         }
2135         // bits[29..25] are all set or all cleared
2136         int pattern = (bits >> 25) & NumUtil.getNbitNumberInt(5);
2137         if (pattern != 0 && pattern != NumUtil.getNbitNumberInt(5)) {
2138             return false;
2139         }
2140         // bits[29] and bits[30] have to be opposite
2141         return ((bits ^ (bits << 1)) & (1 << 30)) != 0;
2142     }
2143 
2144     /* Convert Floating-point Precision (5.7.4.1) */
2145     /* Converts float to double and vice-versa */
2146 
2147     /**
2148      * Convert float to double and vice-versa.
2149      *
2150      * @param srcSize size of source register in bits.
2151      * @param dst floating point register. May not be null.
2152      * @param src floating point register. May not be null.
2153      */
2154     public void fcvt(int srcSize, Register dst, Register src) {
2155         if (srcSize == 32) {
2156             fpDataProcessing1Source(FCVTDS, dst, src, floatFromSize(srcSize));
2157         } else {
2158             fpDataProcessing1Source(FCVTSD, dst, src, floatFromSize(srcSize));
2159         }
2160     }
2161 
2162     /* Convert to Integer (5.7.4.2) */
2163 
2164     /**
2165      * Convert floating point to integer. Rounds towards zero.
2166      *
2167      * @param targetSize size of integer register. 32 or 64.
2168      * @param srcSize size of floating point register. 32 or 64.
2169      * @param dst general purpose register. May not be null, the zero-register or the stackpointer.
2170      * @param src floating point register. May not be null.
2171      */
2172     public void fcvtzs(int targetSize, int srcSize, Register dst, Register src) {
2173         assert !dst.equals(zr) && !dst.equals(sp);
2174         assert src.getRegisterCategory().equals(SIMD);
2175         fcvtCpuFpuInstruction(FCVTZS, dst, src, generalFromSize(targetSize), floatFromSize(srcSize));
2176     }
2177 
2178     /* Convert from Integer (5.7.4.2) */
2179     /**
2180      * Converts integer to floating point. Uses rounding mode defined by FCPR.
2181      *
2182      * @param targetSize size of floating point register. 32 or 64.
2183      * @param srcSize size of integer register. 32 or 64.
2184      * @param dst floating point register. May not be null.
2185      * @param src general purpose register. May not be null or the stackpointer.
2186      */
2187     public void scvtf(int targetSize, int srcSize, Register dst, Register src) {
2188         assert dst.getRegisterCategory().equals(SIMD);
2189         assert !src.equals(sp);
2190         fcvtCpuFpuInstruction(SCVTF, dst, src, floatFromSize(targetSize), generalFromSize(srcSize));
2191     }
2192 
2193     private void fcvtCpuFpuInstruction(Instruction instr, Register dst, Register src, InstructionType type1, InstructionType type2) {
2194         emitInt(type1.encoding | type2.encoding | instr.encoding | FpConvertOp | rd(dst) | rs1(src));
2195     }
2196 
2197     /* Floating-point Round to Integral (5.7.5) */
2198 
2199     /**
2200      * Rounds floating-point to integral. Rounds towards zero.
2201      *
2202      * @param size register size.
2203      * @param dst floating point register. May not be null.
2204      * @param src floating point register. May not be null.
2205      */
2206     protected void frintz(int size, Register dst, Register src) {
2207         fpDataProcessing1Source(FRINTZ, dst, src, floatFromSize(size));
2208     }
2209 
2210     /* Floating-point Arithmetic (1 source) (5.7.6) */
2211 
2212     /**
2213      * dst = |src|.
2214      *
2215      * @param size register size.
2216      * @param dst floating point register. May not be null.
2217      * @param src floating point register. May not be null.
2218      */
2219     public void fabs(int size, Register dst, Register src) {
2220         fpDataProcessing1Source(FABS, dst, src, floatFromSize(size));
2221     }
2222 
2223     /**
2224      * dst = -neg.
2225      *
2226      * @param size register size.
2227      * @param dst floating point register. May not be null.
2228      * @param src floating point register. May not be null.
2229      */
2230     public void fneg(int size, Register dst, Register src) {
2231         fpDataProcessing1Source(FNEG, dst, src, floatFromSize(size));
2232     }
2233 
2234     /**
2235      * dst = Sqrt(src).
2236      *
2237      * @param size register size.
2238      * @param dst floating point register. May not be null.
2239      * @param src floating point register. May not be null.
2240      */
2241     public void fsqrt(int size, Register dst, Register src) {
2242         fpDataProcessing1Source(FSQRT, dst, src, floatFromSize(size));
2243     }
2244 
2245     private void fpDataProcessing1Source(Instruction instr, Register dst, Register src, InstructionType type) {
2246         assert dst.getRegisterCategory().equals(SIMD);
2247         assert src.getRegisterCategory().equals(SIMD);
2248         emitInt(type.encoding | instr.encoding | Fp1SourceOp | rd(dst) | rs1(src));
2249     }
2250 
2251     /* Floating-point Arithmetic (2 source) (5.7.7) */
2252 
2253     /**
2254      * dst = src1 + src2.
2255      *
2256      * @param size register size.
2257      * @param dst floating point register. May not be null.
2258      * @param src1 floating point register. May not be null.
2259      * @param src2 floating point register. May not be null.
2260      */
2261     public void fadd(int size, Register dst, Register src1, Register src2) {
2262         fpDataProcessing2Source(FADD, dst, src1, src2, floatFromSize(size));
2263     }
2264 
2265     /**
2266      * dst = src1 - src2.
2267      *
2268      * @param size register size.
2269      * @param dst floating point register. May not be null.
2270      * @param src1 floating point register. May not be null.
2271      * @param src2 floating point register. May not be null.
2272      */
2273     public void fsub(int size, Register dst, Register src1, Register src2) {
2274         fpDataProcessing2Source(FSUB, dst, src1, src2, floatFromSize(size));
2275     }
2276 
2277     /**
2278      * dst = src1 * src2.
2279      *
2280      * @param size register size.
2281      * @param dst floating point register. May not be null.
2282      * @param src1 floating point register. May not be null.
2283      * @param src2 floating point register. May not be null.
2284      */
2285     public void fmul(int size, Register dst, Register src1, Register src2) {
2286         fpDataProcessing2Source(FMUL, dst, src1, src2, floatFromSize(size));
2287     }
2288 
2289     /**
2290      * dst = src1 / src2.
2291      *
2292      * @param size register size.
2293      * @param dst floating point register. May not be null.
2294      * @param src1 floating point register. May not be null.
2295      * @param src2 floating point register. May not be null.
2296      */
2297     public void fdiv(int size, Register dst, Register src1, Register src2) {
2298         fpDataProcessing2Source(FDIV, dst, src1, src2, floatFromSize(size));
2299     }
2300 
2301     private void fpDataProcessing2Source(Instruction instr, Register dst, Register src1, Register src2, InstructionType type) {
2302         assert dst.getRegisterCategory().equals(SIMD);
2303         assert src1.getRegisterCategory().equals(SIMD);
2304         assert src2.getRegisterCategory().equals(SIMD);
2305         emitInt(type.encoding | instr.encoding | Fp2SourceOp | rd(dst) | rs1(src1) | rs2(src2));
2306     }
2307 
2308     /* Floating-point Multiply-Add (5.7.9) */
2309 
2310     /**
2311      * dst = src1 * src2 + src3.
2312      *
2313      * @param size register size.
2314      * @param dst floating point register. May not be null.
2315      * @param src1 floating point register. May not be null.
2316      * @param src2 floating point register. May not be null.
2317      * @param src3 floating point register. May not be null.
2318      */
2319     protected void fmadd(int size, Register dst, Register src1, Register src2, Register src3) {
2320         fpDataProcessing3Source(FMADD, dst, src1, src2, src3, floatFromSize(size));
2321     }
2322 
2323     /**
2324      * dst = src3 - src1 * src2.
2325      *
2326      * @param size register size.
2327      * @param dst floating point register. May not be null.
2328      * @param src1 floating point register. May not be null.
2329      * @param src2 floating point register. May not be null.
2330      * @param src3 floating point register. May not be null.
2331      */
2332     protected void fmsub(int size, Register dst, Register src1, Register src2, Register src3) {
2333         fpDataProcessing3Source(FMSUB, dst, src1, src2, src3, floatFromSize(size));
2334     }
2335 
2336     private void fpDataProcessing3Source(Instruction instr, Register dst, Register src1, Register src2, Register src3, InstructionType type) {
2337         assert dst.getRegisterCategory().equals(SIMD);
2338         assert src1.getRegisterCategory().equals(SIMD);
2339         assert src2.getRegisterCategory().equals(SIMD);
2340         assert src3.getRegisterCategory().equals(SIMD);
2341         emitInt(type.encoding | instr.encoding | Fp3SourceOp | rd(dst) | rs1(src1) | rs2(src2) | rs3(src3));
2342     }
2343 
2344     /* Floating-point Comparison (5.7.10) */
2345 
2346     /**
2347      * Compares src1 to src2.
2348      *
2349      * @param size register size.
2350      * @param src1 floating point register. May not be null.
2351      * @param src2 floating point register. May not be null.
2352      */
2353     public void fcmp(int size, Register src1, Register src2) {
2354         assert src1.getRegisterCategory().equals(SIMD);
2355         assert src2.getRegisterCategory().equals(SIMD);
2356         InstructionType type = floatFromSize(size);
2357         emitInt(type.encoding | FCMP.encoding | FpCmpOp | rs1(src1) | rs2(src2));
2358     }
2359 
2360     /**
2361      * Conditional compare. NZCV = fcmp(src1, src2) if condition else uimm4.
2362      *
2363      * @param size register size.
2364      * @param src1 floating point register. May not be null.
2365      * @param src2 floating point register. May not be null.
2366      * @param uimm4 condition flags that are used if condition is false.
2367      * @param condition every condition allowed. May not be null.
2368      */
2369     public void fccmp(int size, Register src1, Register src2, int uimm4, ConditionFlag condition) {
2370         assert NumUtil.isUnsignedNbit(4, uimm4);
2371         assert src1.getRegisterCategory().equals(SIMD);
2372         assert src2.getRegisterCategory().equals(SIMD);
2373         InstructionType type = floatFromSize(size);
2374         emitInt(type.encoding | FCCMP.encoding | uimm4 | condition.encoding << ConditionalConditionOffset | rs1(src1) | rs2(src2));
2375     }
2376 
2377     /**
2378      * Compare register to 0.0 .
2379      *
2380      * @param size register size.
2381      * @param src floating point register. May not be null.
2382      */
2383     public void fcmpZero(int size, Register src) {
2384         assert src.getRegisterCategory().equals(SIMD);
2385         InstructionType type = floatFromSize(size);
2386         emitInt(type.encoding | FCMPZERO.encoding | FpCmpOp | rs1(src));
2387     }
2388 
2389     /* Floating-point Conditional Select (5.7.11) */
2390 
2391     /**
2392      * Conditional select. dst = src1 if condition else src2.
2393      *
2394      * @param size register size.
2395      * @param dst floating point register. May not be null.
2396      * @param src1 floating point register. May not be null.
2397      * @param src2 floating point register. May not be null.
2398      * @param condition every condition allowed. May not be null.
2399      */
2400     protected void fcsel(int size, Register dst, Register src1, Register src2, ConditionFlag condition) {
2401         assert dst.getRegisterCategory().equals(SIMD);
2402         assert src1.getRegisterCategory().equals(SIMD);
2403         assert src2.getRegisterCategory().equals(SIMD);
2404         InstructionType type = floatFromSize(size);
2405         emitInt(type.encoding | FCSEL.encoding | rd(dst) | rs1(src1) | rs2(src2) | condition.encoding << ConditionalConditionOffset);
2406     }
2407 
2408     /* Debug exceptions (5.9.1.2) */
2409 
2410     /**
2411      * Halting mode software breakpoint: Enters halting mode debug state if enabled, else treated as
2412      * UNALLOCATED instruction.
2413      *
2414      * @param uimm16 Arbitrary 16-bit unsigned payload.
2415      */
2416     protected void hlt(int uimm16) {
2417         exceptionInstruction(HLT, uimm16);
2418     }
2419 
2420     /**
2421      * Monitor mode software breakpoint: exception routed to a debug monitor executing in a higher
2422      * exception level.
2423      *
2424      * @param uimm16 Arbitrary 16-bit unsigned payload.
2425      */
2426     protected void brk(int uimm16) {
2427         exceptionInstruction(BRK, uimm16);
2428     }
2429 
2430     private void exceptionInstruction(Instruction instr, int uimm16) {
2431         assert NumUtil.isUnsignedNbit(16, uimm16);
2432         emitInt(instr.encoding | ExceptionOp | uimm16 << SystemImmediateOffset);
2433     }
2434 
2435     /* Architectural hints (5.9.4) */
2436     public enum SystemHint {
2437         NOP(0x0),
2438         YIELD(0x1),
2439         WFE(0x2),
2440         WFI(0x3),
2441         SEV(0x4),
2442         SEVL(0x5);
2443 
2444         private final int encoding;
2445 
2446         SystemHint(int encoding) {
2447             this.encoding = encoding;
2448         }
2449     }
2450 
2451     /**
2452      * Architectural hints.
2453      *
2454      * @param hint Can be any of the defined hints. May not be null.
2455      */
2456     protected void hint(SystemHint hint) {
2457         emitInt(HINT.encoding | hint.encoding << SystemImmediateOffset);
2458     }
2459 
2460     /**
2461      * Clear Exclusive: clears the local record of the executing processor that an address has had a
2462      * request for an exclusive access.
2463      */
2464     protected void clrex() {
2465         emitInt(CLREX.encoding);
2466     }
2467 
2468     /**
2469      * Possible barrier definitions for Aarch64. LOAD_LOAD and LOAD_STORE map to the same underlying
2470      * barrier.
2471      *
2472      * We only need synchronization across the inner shareable domain (see B2-90 in the Reference
2473      * documentation).
2474      */
2475     public enum BarrierKind {
2476         LOAD_LOAD(0x9, "ISHLD"),
2477         LOAD_STORE(0x9, "ISHLD"),
2478         STORE_STORE(0xA, "ISHST"),
2479         ANY_ANY(0xB, "ISH");
2480 
2481         public final int encoding;
2482         public final String optionName;
2483 
2484         BarrierKind(int encoding, String optionName) {
2485             this.encoding = encoding;
2486             this.optionName = optionName;
2487         }
2488     }
2489 
2490     /**
2491      * Data Memory Barrier.
2492      *
2493      * @param barrierKind barrier that is issued. May not be null.
2494      */
2495     public void dmb(BarrierKind barrierKind) {
2496         emitInt(DMB.encoding | BarrierOp | barrierKind.encoding << BarrierKindOffset);
2497     }
2498 
2499 }