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 24 25 26 package org.graalvm.compiler.asm.aarch64; 27 28 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.BASE_REGISTER_ONLY; 29 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.EXTENDED_REGISTER_OFFSET; 30 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_SCALED; 31 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_UNSCALED; 32 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.REGISTER_OFFSET; 33 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE; 34 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_INDEX; 35 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.NO_WORK; 36 import static jdk.vm.ci.aarch64.AArch64.CPU; 37 import static jdk.vm.ci.aarch64.AArch64.r8; 38 import static jdk.vm.ci.aarch64.AArch64.r9; 39 import static jdk.vm.ci.aarch64.AArch64.sp; 40 import static jdk.vm.ci.aarch64.AArch64.zr; 41 42 import org.graalvm.compiler.asm.Label; 43 import org.graalvm.compiler.core.common.NumUtil; 44 import org.graalvm.compiler.debug.GraalError; 45 46 import jdk.vm.ci.aarch64.AArch64; 47 import jdk.vm.ci.code.Register; 48 import jdk.vm.ci.code.TargetDescription; 49 50 public class AArch64MacroAssembler extends AArch64Assembler { 51 52 private final ScratchRegister[] scratchRegister = new ScratchRegister[]{new ScratchRegister(r8), new ScratchRegister(r9)}; 53 54 // Points to the next free scratch register 55 private int nextFreeScratchRegister = 0; 1435 */ 1436 public void cbz(int size, Register cmp, Label label) { 1437 // TODO Handle case where offset is too large for a single jump instruction 1438 if (label.isBound()) { 1439 int offset = label.position() - position(); 1440 super.cbz(size, cmp, offset); 1441 } else { 1442 label.addPatchAt(position()); 1443 int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 1); 1444 int sizeEncoding = (size == 64 ? 1 : 0) << PatchLabelKind.INFORMATION_OFFSET; 1445 // Encode condition flag so that we know how to patch the instruction later 1446 emitInt(PatchLabelKind.BRANCH_ZERO.encoding | regEncoding | sizeEncoding); 1447 } 1448 } 1449 1450 /** 1451 * Test a single bit and branch if the bit is nonzero. 1452 * 1453 * @param cmp general purpose register. May not be null, zero-register or stackpointer. 1454 * @param uimm6 Unsigned 6-bit bit index. 1455 * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. 1456 */ 1457 public void tbnz(Register cmp, int uimm6, Label label) { 1458 assert NumUtil.isUnsignedNbit(6, uimm6); 1459 if (label.isBound()) { 1460 int offset = label.position() - position(); 1461 super.tbnz(cmp, uimm6, offset); 1462 } else { 1463 label.addPatchAt(position()); 1464 int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; 1465 int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); 1466 emitInt(PatchLabelKind.BRANCH_BIT_NONZERO.encoding | indexEncoding | regEncoding); 1467 } 1468 } 1469 1470 /** 1471 * Test a single bit and branch if the bit is zero. 1472 * 1473 * @param cmp general purpose register. May not be null, zero-register or stackpointer. 1474 * @param uimm6 Unsigned 6-bit bit index. 1475 * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. 1476 */ 1477 public void tbz(Register cmp, int uimm6, Label label) { 1478 assert NumUtil.isUnsignedNbit(6, uimm6); 1479 if (label.isBound()) { 1480 int offset = label.position() - position(); 1481 super.tbz(cmp, uimm6, offset); 1482 } else { 1483 label.addPatchAt(position()); 1484 int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; 1485 int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); 1486 emitInt(PatchLabelKind.BRANCH_BIT_ZERO.encoding | indexEncoding | regEncoding); 1487 } 1488 } 1489 1490 /** 1491 * Branches to label if condition is true. 1492 * 1493 * @param condition any condition value allowed. Non null. 1494 * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. 1495 */ 1664 int regEncoding = information >>> 1; 1665 Register reg = AArch64.cpuRegisters.get(regEncoding); 1666 // 1 => 64; 0 => 32 1667 int size = sizeEncoding * 32 + 32; 1668 switch (type) { 1669 case BRANCH_NONZERO: 1670 super.cbnz(size, reg, branchOffset, branch); 1671 break; 1672 case BRANCH_ZERO: 1673 super.cbz(size, reg, branchOffset, branch); 1674 break; 1675 } 1676 break; 1677 } 1678 case BRANCH_BIT_NONZERO: 1679 case BRANCH_BIT_ZERO: { 1680 int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; 1681 int sizeEncoding = information & NumUtil.getNbitNumberInt(6); 1682 int regEncoding = information >>> 6; 1683 Register reg = AArch64.cpuRegisters.get(regEncoding); 1684 switch (type) { 1685 case BRANCH_BIT_NONZERO: 1686 super.tbnz(reg, sizeEncoding, branchOffset, branch); 1687 break; 1688 case BRANCH_BIT_ZERO: 1689 super.tbz(reg, sizeEncoding, branchOffset, branch); 1690 break; 1691 } 1692 break; 1693 } 1694 case ADR: { 1695 int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; 1696 int regEncoding = information; 1697 Register reg = AArch64.cpuRegisters.get(regEncoding); 1698 super.adr(reg, branchOffset, branch); 1699 break; 1700 } 1701 default: 1702 throw GraalError.shouldNotReachHere(); 1703 } | 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 24 25 26 package org.graalvm.compiler.asm.aarch64; 27 28 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.BASE_REGISTER_ONLY; 29 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.EXTENDED_REGISTER_OFFSET; 30 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_SCALED; 31 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_UNSCALED; 32 import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.REGISTER_OFFSET; 33 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE; 34 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_INDEX; 35 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.NO_WORK; 36 37 import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; 38 39 import static jdk.vm.ci.aarch64.AArch64.CPU; 40 import static jdk.vm.ci.aarch64.AArch64.r8; 41 import static jdk.vm.ci.aarch64.AArch64.r9; 42 import static jdk.vm.ci.aarch64.AArch64.sp; 43 import static jdk.vm.ci.aarch64.AArch64.zr; 44 45 import org.graalvm.compiler.asm.Label; 46 import org.graalvm.compiler.core.common.NumUtil; 47 import org.graalvm.compiler.debug.GraalError; 48 49 import jdk.vm.ci.aarch64.AArch64; 50 import jdk.vm.ci.code.Register; 51 import jdk.vm.ci.code.TargetDescription; 52 53 public class AArch64MacroAssembler extends AArch64Assembler { 54 55 private final ScratchRegister[] scratchRegister = new ScratchRegister[]{new ScratchRegister(r8), new ScratchRegister(r9)}; 56 57 // Points to the next free scratch register 58 private int nextFreeScratchRegister = 0; 1438 */ 1439 public void cbz(int size, Register cmp, Label label) { 1440 // TODO Handle case where offset is too large for a single jump instruction 1441 if (label.isBound()) { 1442 int offset = label.position() - position(); 1443 super.cbz(size, cmp, offset); 1444 } else { 1445 label.addPatchAt(position()); 1446 int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 1); 1447 int sizeEncoding = (size == 64 ? 1 : 0) << PatchLabelKind.INFORMATION_OFFSET; 1448 // Encode condition flag so that we know how to patch the instruction later 1449 emitInt(PatchLabelKind.BRANCH_ZERO.encoding | regEncoding | sizeEncoding); 1450 } 1451 } 1452 1453 /** 1454 * Test a single bit and branch if the bit is nonzero. 1455 * 1456 * @param cmp general purpose register. May not be null, zero-register or stackpointer. 1457 * @param uimm6 Unsigned 6-bit bit index. 1458 * @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null. 1459 */ 1460 public void tbnz(Register cmp, int uimm6, Label label) { 1461 assert NumUtil.isUnsignedNbit(6, uimm6); 1462 if (label.isBound()) { 1463 int offset = label.position() - position(); 1464 super.tbnz(cmp, uimm6, offset); 1465 } else { 1466 label.addPatchAt(position()); 1467 int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; 1468 int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); 1469 emitInt(PatchLabelKind.BRANCH_BIT_NONZERO.encoding | indexEncoding | regEncoding); 1470 } 1471 } 1472 1473 /** 1474 * Test a single bit and branch if the bit is zero. 1475 * 1476 * @param cmp general purpose register. May not be null, zero-register or stackpointer. 1477 * @param uimm6 Unsigned 6-bit bit index. 1478 * @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null. 1479 */ 1480 public void tbz(Register cmp, int uimm6, Label label) { 1481 assert NumUtil.isUnsignedNbit(6, uimm6); 1482 if (label.isBound()) { 1483 int offset = label.position() - position(); 1484 super.tbz(cmp, uimm6, offset); 1485 } else { 1486 label.addPatchAt(position()); 1487 int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; 1488 int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); 1489 emitInt(PatchLabelKind.BRANCH_BIT_ZERO.encoding | indexEncoding | regEncoding); 1490 } 1491 } 1492 1493 /** 1494 * Branches to label if condition is true. 1495 * 1496 * @param condition any condition value allowed. Non null. 1497 * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. 1498 */ 1667 int regEncoding = information >>> 1; 1668 Register reg = AArch64.cpuRegisters.get(regEncoding); 1669 // 1 => 64; 0 => 32 1670 int size = sizeEncoding * 32 + 32; 1671 switch (type) { 1672 case BRANCH_NONZERO: 1673 super.cbnz(size, reg, branchOffset, branch); 1674 break; 1675 case BRANCH_ZERO: 1676 super.cbz(size, reg, branchOffset, branch); 1677 break; 1678 } 1679 break; 1680 } 1681 case BRANCH_BIT_NONZERO: 1682 case BRANCH_BIT_ZERO: { 1683 int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; 1684 int sizeEncoding = information & NumUtil.getNbitNumberInt(6); 1685 int regEncoding = information >>> 6; 1686 Register reg = AArch64.cpuRegisters.get(regEncoding); 1687 if (!NumUtil.isSignedNbit(16, branchOffset)) { 1688 throw new BranchTargetOutOfBoundsException(true, "Branch target %d out of bounds", branchOffset); 1689 } 1690 switch (type) { 1691 case BRANCH_BIT_NONZERO: 1692 super.tbnz(reg, sizeEncoding, branchOffset, branch); 1693 break; 1694 case BRANCH_BIT_ZERO: 1695 super.tbz(reg, sizeEncoding, branchOffset, branch); 1696 break; 1697 } 1698 break; 1699 } 1700 case ADR: { 1701 int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; 1702 int regEncoding = information; 1703 Register reg = AArch64.cpuRegisters.get(regEncoding); 1704 super.adr(reg, branchOffset, branch); 1705 break; 1706 } 1707 default: 1708 throw GraalError.shouldNotReachHere(); 1709 } |