src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java
Print this page
*** 37,47 ****
import static jdk.vm.ci.aarch64.AArch64.sp;
import static jdk.vm.ci.aarch64.AArch64.zr;
import org.graalvm.compiler.asm.AbstractAddress;
import org.graalvm.compiler.asm.Label;
! import org.graalvm.compiler.asm.NumUtil;
import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.TargetDescription;
--- 37,47 ----
import static jdk.vm.ci.aarch64.AArch64.sp;
import static jdk.vm.ci.aarch64.AArch64.zr;
import org.graalvm.compiler.asm.AbstractAddress;
import org.graalvm.compiler.asm.Label;
! import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.TargetDescription;
*** 194,213 ****
--- 194,215 ----
immediate = (int) displacement;
}
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);
} else {
add(signExtendIndex ? 32 : 64, newIndex, index, (int) scaledDisplacement);
}
immediate = 0;
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);
} else {
add(64, newBase, base, (int) displacement);
*** 410,419 ****
--- 412,434 ----
}
assert !firstMove;
}
/**
+ * 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) {
if (imm == 0L || LogicalImmediateTable.isRepresentable(true, imm) != LogicalImmediateTable.Representable.NO) {
return 1;
*** 454,463 ****
--- 469,491 ----
super.ldrs(targetSize, srcSize, rt, address);
}
}
/**
+ * 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.
* @param result general purpose register. May not be null or the stackpointer.
* @param trueValue general purpose register. May not be null or the stackpointer.
*** 480,549 ****
/**
* 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 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);
}
/**
* 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 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);
}
/**
* 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 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;
} else {
! throw GraalError.shouldNotReachHere("No-op ");
}
}
/**
* 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 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);
}
/**
* dst = src1 + shiftType(src2, shiftAmt & (size - 1)).
*
* @param size register size. Has to be 32 or 64.
--- 508,576 ----
/**
* dst = src1 + src2.
*
* @param size register size. Has to be 32 or 64.
! * @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) {
+ 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.
! * @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) {
! 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.
! * @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) {
! if (dst.equals(sp) || src1.equals(sp)) {
! super.subs(size, dst, src1, src2, ExtendType.UXTX, 0);
} else {
! super.subs(size, dst, src1, src2, ShiftType.LSL, 0);
}
}
/**
* dst = src1 - src2.
*
* @param size register size. Has to be 32 or 64.
! * @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) {
+ 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);
}
+ }
/**
* dst = src1 + shiftType(src2, shiftAmt & (size - 1)).
*
* @param size register size. Has to be 32 or 64.
*** 588,608 ****
/**
* 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
*/
@Override
public void add(int size, Register dst, Register src, int immediate) {
if (immediate < 0) {
sub(size, dst, src, -immediate);
! } else if (!(dst.equals(src) && immediate == 0)) {
super.add(size, dst, src, immediate);
}
}
/**
* dst = src + aimm and sets condition flags.
*
--- 615,645 ----
/**
* dst = src + immediate.
*
* @param size register size. Has to be 32 or 64.
! * @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 (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);
+ }
}
/**
* dst = src + aimm and sets condition flags.
*
*** 611,620 ****
--- 648,658 ----
* @param src general purpose register. May not be null or zero-register.
* @param immediate arithmetic immediate.
*/
@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)) {
super.adds(size, dst, src, immediate);
}
*** 622,642 ****
/**
* 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
*/
@Override
public void sub(int size, Register dst, Register src, int immediate) {
if (immediate < 0) {
add(size, dst, src, -immediate);
! } else if (!dst.equals(src) || immediate != 0) {
super.sub(size, dst, src, immediate);
}
}
/**
* dst = src - aimm and sets condition flags.
*
--- 660,690 ----
/**
* dst = src - immediate.
*
* @param size register size. Has to be 32 or 64.
! * @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 (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);
+ }
}
/**
* dst = src - aimm and sets condition flags.
*
*** 645,658 ****
* @param src general purpose register. May not be null or zero-register.
* @param immediate arithmetic immediate.
*/
@Override
public void subs(int size, Register dst, Register src, int immediate) {
if (immediate < 0) {
adds(size, dst, src, -immediate);
} else if (!dst.equals(src) || immediate != 0) {
! super.sub(size, dst, src, immediate);
}
}
/**
* dst = src1 * src2.
--- 693,707 ----
* @param src general purpose register. May not be null or zero-register.
* @param immediate arithmetic immediate.
*/
@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.subs(size, dst, src, immediate);
}
}
/**
* dst = src1 * src2.
*** 673,682 ****
--- 722,732 ----
* @param dst general purpose register. May not be null or the stackpointer.
* @param src1 general purpose register. May not be null or the stackpointer.
* @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);
} else {
// xDst = wSrc1 * wSrc2
*** 693,702 ****
--- 743,753 ----
* @param dst general purpose register. May not be null or the stackpointer.
* @param src1 general purpose register. May not be null or the stackpointer.
* @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);
} else {
// xDst = wSrc1 * wSrc2
*** 713,722 ****
--- 764,774 ----
* @param dst general purpose register. May not be null or the stackpointer.
* @param n numerator. General purpose register. May not be null or the stackpointer.
* @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
// Which is equivalent to n - TruncatingDivision(n, d) * d
super.sdiv(size, dst, n, d);
*** 938,957 ****
}
/**
* 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 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)]);
}
/**
* dst = src if condition else -src.
*
--- 990,1007 ----
}
/**
* Sign-extend value from src into dst.
*
! * @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 (srcSize < destSize && srcSize > 0);
! super.sbfm(destSize, dst, src, 0, srcSize - 1);
}
/**
* dst = src if condition else -src.
*
*** 1076,1085 ****
--- 1126,1136 ----
* @param size register size. Has to be 32 or 64.
* @param x general purpose register. May not be null or stackpointer.
* @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);
}
/**
* Compares x to y and sets condition flags.
*** 1087,1096 ****
--- 1138,1148 ----
* @param size register size. Has to be 32 or 64.
* @param x general purpose register. May not be null or stackpointer.
* @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 {
super.subs(size, zr, x, y);
}
*** 1107,1116 ****
--- 1159,1216 ----
public void ands(int size, Register dst, Register x, Register y) {
super.ands(size, dst, x, y, ShiftType.LSL, 0);
}
/**
+ * 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 {
BRANCH_CONDITIONALLY(0x0),
BRANCH_UNCONDITIONALLY(0x1),
*** 1351,1361 ****
break;
case BRANCH_UNCONDITIONALLY:
super.b(branchOffset, branch);
break;
case JUMP_ADDRESS:
! emitInt(jumpTarget, branch);
break;
case BRANCH_NONZERO:
case BRANCH_ZERO: {
int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET;
int sizeEncoding = information & 1;
--- 1451,1462 ----
break;
case BRANCH_UNCONDITIONALLY:
super.b(branchOffset, branch);
break;
case JUMP_ADDRESS:
! int offset = instruction >>> PatchLabelKind.INFORMATION_OFFSET;
! emitInt(jumpTarget - offset, branch);
break;
case BRANCH_NONZERO:
case BRANCH_ZERO: {
int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET;
int sizeEncoding = information & 1;
*** 1402,1407 ****
--- 1503,1518 ----
@Override
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);
+ }
}
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File