--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Mon Dec 12 16:16:27 2016 +0300
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Wed Mar 22 13:42:45 2017 -0700
@@ -39,7 +39,7 @@
import org.graalvm.compiler.asm.AbstractAddress;
import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.aarch64.AArch64;
@@ -196,6 +196,7 @@
break;
case ADD_TO_INDEX:
newIndex = allowOverwrite ? index : additionalReg;
+ assert !newIndex.equals(sp) && !newIndex.equals(zr);
if (plan.needsScratch) {
mov(additionalReg, scaledDisplacement);
add(signExtendIndex ? 32 : 64, newIndex, index, additionalReg);
@@ -206,6 +207,7 @@
break;
case ADD_TO_BASE:
newBase = allowOverwrite ? base : additionalReg;
+ assert !newBase.equals(sp) && !newBase.equals(zr);
if (plan.needsScratch) {
mov(additionalReg, displacement);
add(64, newBase, base, additionalReg);
@@ -412,6 +414,19 @@
}
/**
+ * Generates a 32-bit immediate move code sequence. The immediate may later be updated by
+ * HotSpot.
+ *
+ * @param dst general purpose register. May not be null, stackpointer or zero-register.
+ * @param imm
+ */
+ public void movNarrowAddress(Register dst, long imm) {
+ assert (imm & 0xFFFF_FFFF_0000_0000L) == 0;
+ movz(64, dst, (int) (imm >>> 16), 16);
+ movk(64, dst, (int) (imm & 0xffff), 0);
+ }
+
+ /**
* @return Number of instructions necessary to load immediate into register.
*/
public static int nrInstructionsToMoveImmediate(long imm) {
@@ -456,6 +471,19 @@
}
/**
+ * Loads a srcSize value from address into rt zero-extending it if necessary.
+ *
+ * @param srcSize size of memory read in bits. Must be 8, 16 or 32 and smaller or equal to
+ * targetSize.
+ * @param rt general purpose register. May not be null or stackpointer.
+ * @param address all addressing modes allowed. May not be null.
+ */
+ @Override
+ public void ldr(int srcSize, Register rt, AArch64Address address) {
+ super.ldr(srcSize, rt, address);
+ }
+
+ /**
* Conditional move. dst = src1 if condition else src2.
*
* @param size register size. Has to be 32 or 64.
@@ -482,52 +510,47 @@
* dst = src1 + src2.
*
* @param size register size. Has to be 32 or 64.
- * @param dst general purpose register. May not be null or stackpointer.
- * @param src1 general purpose register. May not be null or stackpointer.
+ * @param dst general purpose register. May not be null.
+ * @param src1 general purpose register. May not be null.
* @param src2 general purpose register. May not be null or stackpointer.
*/
public void add(int size, Register dst, Register src1, Register src2) {
- super.add(size, dst, src1, src2, ShiftType.LSL, 0);
+ if (dst.equals(sp) || src1.equals(sp)) {
+ super.add(size, dst, src1, src2, ExtendType.UXTX, 0);
+ } else {
+ super.add(size, dst, src1, src2, ShiftType.LSL, 0);
+ }
}
/**
* dst = src1 + src2 and sets condition flags.
*
* @param size register size. Has to be 32 or 64.
- * @param dst general purpose register. May not be null or stackpointer.
- * @param src1 general purpose register. May not be null or stackpointer.
+ * @param dst general purpose register. May not be null.
+ * @param src1 general purpose register. May not be null.
* @param src2 general purpose register. May not be null or stackpointer.
*/
public void adds(int size, Register dst, Register src1, Register src2) {
- super.adds(size, dst, src1, src2, getNopExtendType(size), 0);
+ if (dst.equals(sp) || src1.equals(sp)) {
+ super.adds(size, dst, src1, src2, ExtendType.UXTX, 0);
+ } else {
+ super.adds(size, dst, src1, src2, ShiftType.LSL, 0);
+ }
}
/**
* dst = src1 - src2 and sets condition flags.
*
* @param size register size. Has to be 32 or 64.
- * @param dst general purpose register. May not be null or stackpointer.
- * @param src1 general purpose register. May not be null or stackpointer.
+ * @param dst general purpose register. May not be null.
+ * @param src1 general purpose register. May not be null.
* @param src2 general purpose register. May not be null or stackpointer.
*/
public void subs(int size, Register dst, Register src1, Register src2) {
- super.subs(size, dst, src1, src2, getNopExtendType(size), 0);
- }
-
- /**
- * Returns the ExtendType for the given size that corresponds to a no-op.
- *
- * I.e. when doing add X0, X1, X2, the actual instruction has the form add X0, X1, X2 UXTX.
- *
- * @param size
- */
- private static ExtendType getNopExtendType(int size) {
- if (size == 64) {
- return ExtendType.UXTX;
- } else if (size == 32) {
- return ExtendType.UXTW;
+ if (dst.equals(sp) || src1.equals(sp)) {
+ super.subs(size, dst, src1, src2, ExtendType.UXTX, 0);
} else {
- throw GraalError.shouldNotReachHere("No-op ");
+ super.subs(size, dst, src1, src2, ShiftType.LSL, 0);
}
}
@@ -535,12 +558,16 @@
* dst = src1 - src2.
*
* @param size register size. Has to be 32 or 64.
- * @param dst general purpose register. May not be null or stackpointer.
- * @param src1 general purpose register. May not be null or stackpointer.
+ * @param dst general purpose register. May not be null.
+ * @param src1 general purpose register. May not be null.
* @param src2 general purpose register. May not be null or stackpointer.
*/
public void sub(int size, Register dst, Register src1, Register src2) {
- super.sub(size, dst, src1, src2, ShiftType.LSL, 0);
+ if (dst.equals(sp) || src1.equals(sp)) {
+ super.sub(size, dst, src1, src2, ExtendType.UXTX, 0);
+ } else {
+ super.sub(size, dst, src1, src2, ShiftType.LSL, 0);
+ }
}
/**
@@ -590,16 +617,26 @@
* dst = src + immediate.
*
* @param size register size. Has to be 32 or 64.
- * @param dst general purpose register. May not be null or stackpointer.
- * @param src general purpose register. May not be null or stackpointer.
- * @param immediate arithmetic immediate
+ * @param dst general purpose register. May not be null or zero-register.
+ * @param src general purpose register. May not be null or zero-register.
+ * @param immediate 32-bit signed int
*/
@Override
public void add(int size, Register dst, Register src, int immediate) {
+ assert (!dst.equals(zr) && !src.equals(zr));
if (immediate < 0) {
sub(size, dst, src, -immediate);
- } else if (!(dst.equals(src) && immediate == 0)) {
- super.add(size, dst, src, immediate);
+ } else if (isAimm(immediate)) {
+ if (!(dst.equals(src) && immediate == 0)) {
+ super.add(size, dst, src, immediate);
+ }
+ } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) {
+ super.add(size, dst, src, immediate & -(1 << 12));
+ super.add(size, dst, dst, immediate & ((1 << 12) - 1));
+ } else {
+ assert !dst.equals(src);
+ mov(dst, immediate);
+ add(size, src, dst, dst);
}
}
@@ -613,6 +650,7 @@
*/
@Override
public void adds(int size, Register dst, Register src, int immediate) {
+ assert (!dst.equals(sp) && !src.equals(zr));
if (immediate < 0) {
subs(size, dst, src, -immediate);
} else if (!(dst.equals(src) && immediate == 0)) {
@@ -624,16 +662,26 @@
* dst = src - immediate.
*
* @param size register size. Has to be 32 or 64.
- * @param dst general purpose register. May not be null or stackpointer.
- * @param src general purpose register. May not be null or stackpointer.
- * @param immediate arithmetic immediate
+ * @param dst general purpose register. May not be null or zero-register.
+ * @param src general purpose register. May not be null or zero-register.
+ * @param immediate 32-bit signed int
*/
@Override
public void sub(int size, Register dst, Register src, int immediate) {
+ assert (!dst.equals(zr) && !src.equals(zr));
if (immediate < 0) {
add(size, dst, src, -immediate);
- } else if (!dst.equals(src) || immediate != 0) {
- super.sub(size, dst, src, immediate);
+ } else if (isAimm(immediate)) {
+ if (!(dst.equals(src) && immediate == 0)) {
+ super.sub(size, dst, src, immediate);
+ }
+ } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) {
+ super.sub(size, dst, src, immediate & -(1 << 12));
+ super.sub(size, dst, dst, immediate & ((1 << 12) - 1));
+ } else {
+ assert !dst.equals(src);
+ mov(dst, immediate);
+ sub(size, src, dst, dst);
}
}
@@ -647,10 +695,11 @@
*/
@Override
public void subs(int size, Register dst, Register src, int immediate) {
+ assert (!dst.equals(sp) && !src.equals(zr));
if (immediate < 0) {
adds(size, dst, src, -immediate);
} else if (!dst.equals(src) || immediate != 0) {
- super.sub(size, dst, src, immediate);
+ super.subs(size, dst, src, immediate);
}
}
@@ -675,6 +724,7 @@
* @param src2 general purpose register. May not be null or the stackpointer.
*/
public void umulh(int size, Register dst, Register src1, Register src2) {
+ assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp));
assert size == 32 || size == 64;
if (size == 64) {
super.umulh(dst, src1, src2);
@@ -695,6 +745,7 @@
* @param src2 general purpose register. May not be null or the stackpointer.
*/
public void smulh(int size, Register dst, Register src1, Register src2) {
+ assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp));
assert size == 32 || size == 64;
if (size == 64) {
super.smulh(dst, src1, src2);
@@ -715,6 +766,7 @@
* @param d denominator. General purpose register. Divisor May not be null or the stackpointer.
*/
public void rem(int size, Register dst, Register n, Register d) {
+ assert (!dst.equals(sp) && !n.equals(sp) && !d.equals(sp));
// There is no irem or similar instruction. Instead we use the relation:
// n % d = n - Floor(n / d) * d if nd >= 0
// n % d = n - Ceil(n / d) * d else
@@ -940,16 +992,14 @@
/**
* Sign-extend value from src into dst.
*
- * @param destSize destination register size. Has to be 32 or 64.
- * @param srcSize source register size. May be 8, 16 or 32 and smaller than destSize.
+ * @param destSize destination register size. Must be 32 or 64.
+ * @param srcSize source register size. Must be smaller than destSize.
* @param dst general purpose register. May not be null, stackpointer or zero-register.
* @param src general purpose register. May not be null, stackpointer or zero-register.
*/
public void sxt(int destSize, int srcSize, Register dst, Register src) {
- assert (destSize == 32 || destSize == 64) && srcSize < destSize;
- assert srcSize == 8 || srcSize == 16 || srcSize == 32;
- int[] srcSizeValues = {7, 15, 31};
- super.sbfm(destSize, dst, src, 0, srcSizeValues[NumUtil.log2Ceil(srcSize / 8)]);
+ assert (srcSize < destSize && srcSize > 0);
+ super.sbfm(destSize, dst, src, 0, srcSize - 1);
}
/**
@@ -1078,6 +1128,7 @@
* @param y general purpose register. May not be null or stackpointer.
*/
public void cmp(int size, Register x, Register y) {
+ assert size == 32 || size == 64;
super.subs(size, zr, x, y, ShiftType.LSL, 0);
}
@@ -1089,6 +1140,7 @@
* @param y comparison immediate, {@link #isComparisonImmediate(long)} has to be true for it.
*/
public void cmp(int size, Register x, int y) {
+ assert size == 32 || size == 64;
if (y < 0) {
super.adds(size, zr, x, -y);
} else {
@@ -1109,6 +1161,54 @@
}
/**
+ * Sets overflow flag according to result of x * y.
+ *
+ * @param size register size. Has to be 32 or 64.
+ * @param dst general purpose register. May not be null or stack-pointer.
+ * @param x general purpose register. May not be null or stackpointer.
+ * @param y general purpose register. May not be null or stackpointer.
+ */
+ public void mulvs(int size, Register dst, Register x, Register y) {
+ try (ScratchRegister sc1 = getScratchRegister();
+ ScratchRegister sc2 = getScratchRegister()) {
+ switch (size) {
+ case 64: {
+ // Be careful with registers: it's possible that x, y, and dst are the same
+ // register.
+ Register rscratch1 = sc1.getRegister();
+ Register rscratch2 = sc2.getRegister();
+ mul(64, rscratch1, x, y); // Result bits 0..63
+ smulh(64, rscratch2, x, y); // Result bits 64..127
+ // Top is pure sign ext
+ subs(64, zr, rscratch2, rscratch1, ShiftType.ASR, 63);
+ // Copy all 64 bits of the result into dst
+ mov(64, dst, rscratch1);
+ mov(rscratch1, 0x80000000);
+ // Develop 0 (EQ), or 0x80000000 (NE)
+ cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE);
+ cmp(32, rscratch1, 1);
+ // 0x80000000 - 1 => VS
+ break;
+ }
+ case 32: {
+ Register rscratch1 = sc1.getRegister();
+ smaddl(rscratch1, x, y, zr);
+ // Copy the low 32 bits of the result into dst
+ mov(32, dst, rscratch1);
+ subs(64, zr, rscratch1, rscratch1, ExtendType.SXTW, 0);
+ // NE => overflow
+ mov(rscratch1, 0x80000000);
+ // Develop 0 (EQ), or 0x80000000 (NE)
+ cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE);
+ cmp(32, rscratch1, 1);
+ // 0x80000000 - 1 => VS
+ break;
+ }
+ }
+ }
+ }
+
+ /**
* When patching up Labels we have to know what kind of code to generate.
*/
public enum PatchLabelKind {
@@ -1353,7 +1453,8 @@
super.b(branchOffset, branch);
break;
case JUMP_ADDRESS:
- emitInt(jumpTarget, branch);
+ int offset = instruction >>> PatchLabelKind.INFORMATION_OFFSET;
+ emitInt(jumpTarget - offset, branch);
break;
case BRANCH_NONZERO:
case BRANCH_ZERO: {
@@ -1404,4 +1505,14 @@
public AbstractAddress getPlaceholder(int instructionStartPosition) {
return AArch64Address.PLACEHOLDER;
}
+
+ /**
+ * Loads an address into Register d.
+ *
+ * @param d general purpose register. May not be null.
+ * @param a AArch64Address the address of an operand.
+ */
+ public void lea(Register d, AArch64Address a) {
+ a.lea(this, d);
+ }
}