36 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
37 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
38 import static java.lang.Math.max;
39 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
40 import static jdk.vm.ci.code.ValueUtil.asRegister;
41 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
42 import static jdk.vm.ci.code.ValueUtil.isRegister;
43 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
44 import static jdk.vm.ci.sparc.SPARC.g0;
45 import static jdk.vm.ci.sparc.SPARCKind.DOUBLE;
46 import static jdk.vm.ci.sparc.SPARCKind.SINGLE;
47 import static jdk.vm.ci.sparc.SPARCKind.WORD;
48 import static jdk.vm.ci.sparc.SPARCKind.XWORD;
49
50 import java.util.Set;
51
52 import org.graalvm.compiler.asm.sparc.SPARCAddress;
53 import org.graalvm.compiler.asm.sparc.SPARCAssembler;
54 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
55 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
56 import org.graalvm.compiler.core.common.LIRKind;
57 import org.graalvm.compiler.core.common.type.DataPointerConstant;
58 import org.graalvm.compiler.debug.GraalError;
59 import org.graalvm.compiler.lir.LIRFrameState;
60 import org.graalvm.compiler.lir.LIRInstructionClass;
61 import org.graalvm.compiler.lir.Opcode;
62 import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck;
63 import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
64 import org.graalvm.compiler.lir.StandardOp.NullCheck;
65 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
66 import org.graalvm.compiler.lir.VirtualStackSlot;
67 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
68
69 import jdk.vm.ci.code.Register;
70 import jdk.vm.ci.code.StackSlot;
71 import jdk.vm.ci.meta.AllocatableValue;
72 import jdk.vm.ci.meta.Constant;
73 import jdk.vm.ci.meta.JavaConstant;
74 import jdk.vm.ci.meta.PlatformKind;
75 import jdk.vm.ci.meta.Value;
99 StackSlot slot = asStackSlot(result);
100 const2stack(crb, masm, slot, g0, getDelayedControlTransfer(), constant);
101 }
102 }
103
104 @Override
105 public Constant getConstant() {
106 return constant;
107 }
108
109 @Override
110 public AllocatableValue getResult() {
111 return result;
112 }
113 }
114
115 public static class LoadConstantFromTable extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
116 public static final LIRInstructionClass<LoadConstantFromTable> TYPE = LIRInstructionClass.create(LoadConstantFromTable.class);
117 public static final SizeEstimate SIZE = SizeEstimate.create(1, 8);
118
119 private Constant constant;
120 @Def({REG, STACK}) AllocatableValue result;
121 @Use({REG}) private AllocatableValue constantTableBase;
122
123 public LoadConstantFromTable(Constant constant, AllocatableValue constantTableBase, AllocatableValue result) {
124 super(TYPE, SIZE);
125 this.constant = constant;
126 this.result = result;
127 this.constantTableBase = constantTableBase;
128 }
129
130 @Override
131 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
132 final int byteCount = result.getPlatformKind().getSizeInBytes();
133 assert byteCount > 1 : "Byte values must not be loaded via constant table";
134 Register baseRegister = asRegister(constantTableBase);
135 if (isRegister(result)) {
136 Register resultRegister = asRegister(result);
137 loadFromConstantTable(crb, masm, byteCount, baseRegister, constant, resultRegister, getDelayedControlTransfer());
138 } else if (isStackSlot(result)) {
139 try (ScratchRegister scratch = masm.getScratchRegister()) {
140 Register scratchRegister = scratch.getRegister();
141 loadFromConstantTable(crb, masm, byteCount, baseRegister, constant, scratchRegister, getDelayedControlTransfer());
142 StackSlot slot = asStackSlot(result);
143 reg2stack(crb, masm, slot, scratchRegister.asValue(), getDelayedControlTransfer());
144 }
145 }
146 }
147 }
148
149 @Opcode("MOVE")
150 public static class Move extends SPARCLIRInstruction implements ValueMoveOp, SPARCTailDelayedLIRInstruction {
151 public static final LIRInstructionClass<Move> TYPE = LIRInstructionClass.create(Move.class);
152 public static final SizeEstimate SIZE = SizeEstimate.create(8);
153
154 @Def({REG, STACK, HINT}) protected AllocatableValue result;
155 @Use({REG, STACK}) protected AllocatableValue input;
156
157 public Move(AllocatableValue result, AllocatableValue input) {
158 super(TYPE, SIZE);
159 this.result = result;
160 this.input = input;
161 }
625 * @param scratch The register as scratch to use
626 * @return a loadable SPARCAddress
627 */
628 public static SPARCAddress generateSimm13OffsetLoad(SPARCAddress addr, SPARCMacroAssembler masm, Register scratch) {
629 boolean displacementOutOfBound = addr.getIndex().equals(Register.None) && !SPARCAssembler.isSimm13(addr.getDisplacement());
630 if (displacementOutOfBound) {
631 masm.setx(addr.getDisplacement(), scratch, false);
632 return new SPARCAddress(addr.getBase(), scratch);
633 } else {
634 return addr;
635 }
636 }
637
638 public static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Register constantTableBase, JavaConstant input, SPARCDelayedControlTransfer delaySlotLir) {
639 try (ScratchRegister sc = masm.getScratchRegister()) {
640 Register scratch = sc.getRegister();
641 Set<CPUFeature> cpuFeatures = ((SPARC) masm.target.arch).getFeatures();
642 boolean hasVIS1 = cpuFeatures.contains(CPUFeature.VIS1);
643 boolean hasVIS3 = cpuFeatures.contains(CPUFeature.VIS3);
644 Register resultRegister = asRegister(result);
645 int byteCount = result.getPlatformKind().getSizeInBytes();
646 switch (input.getJavaKind().getStackKind()) {
647 case Int:
648 if (input.isDefaultForKind()) {
649 delaySlotLir.emitControlTransfer(crb, masm);
650 masm.clr(resultRegister);
651 } else if (isSimm13(input.asInt())) {
652 delaySlotLir.emitControlTransfer(crb, masm);
653 masm.or(g0, input.asInt(), resultRegister);
654 } else {
655 if (constantTableBase.equals(g0)) {
656 throw GraalError.shouldNotReachHere();
657 } else {
658 loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
659 }
660 }
661 break;
662 case Long:
663 if (input.isDefaultForKind()) {
664 delaySlotLir.emitControlTransfer(crb, masm);
665 masm.clr(resultRegister);
666 } else if (isSimm13(input.asLong())) {
667 delaySlotLir.emitControlTransfer(crb, masm);
668 masm.or(g0, (int) input.asLong(), resultRegister);
669 } else {
670 loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
671 }
672 break;
673 case Float: {
674 float constant = input.asFloat();
675 int constantBits = java.lang.Float.floatToIntBits(constant);
676 if (hasVIS1 && constantBits == 0) {
677 delaySlotLir.emitControlTransfer(crb, masm);
678 masm.fzeros(resultRegister);
679 } else {
680 if (hasVIS3 && isSimm13(constantBits)) {
681 masm.or(g0, constantBits, scratch);
682 delaySlotLir.emitControlTransfer(crb, masm);
683 masm.movwtos(scratch, resultRegister);
684 } else {
685 // First load the address into the scratch register
686 loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
687 }
688 }
689 break;
690 }
691 case Double: {
692 double constant = input.asDouble();
693 long constantBits = java.lang.Double.doubleToRawLongBits(constant);
694 if (hasVIS1 && constantBits == 0) {
695 delaySlotLir.emitControlTransfer(crb, masm);
696 masm.fzerod(resultRegister);
697 } else {
698 if (hasVIS3 && isSimm13(constantBits)) {
699 masm.or(g0, (int) constantBits, scratch);
700 delaySlotLir.emitControlTransfer(crb, masm);
701 masm.movxtod(scratch, resultRegister);
702 } else {
703 loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
704 }
705 }
706 break;
707 }
708 case Object:
709 if (input.isNull()) {
710 delaySlotLir.emitControlTransfer(crb, masm);
711 masm.clr(resultRegister);
712 } else {
713 loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
714 }
715 break;
716 default:
717 throw GraalError.shouldNotReachHere("missing: " + input.getJavaKind());
718 }
719 }
720 }
721
722 protected static void compareAndSwap(CompilationResultBuilder crb, SPARCMacroAssembler masm, AllocatableValue address, AllocatableValue cmpValue, AllocatableValue newValue,
723 SPARCDelayedControlTransfer delay) {
724 delay.emitControlTransfer(crb, masm);
725 switch ((SPARCKind) cmpValue.getPlatformKind()) {
726 case WORD:
727 masm.cas(asRegister(address), asRegister(cmpValue), asRegister(newValue));
728 break;
729 case XWORD:
730 masm.casx(asRegister(address), asRegister(cmpValue), asRegister(newValue));
731 break;
732 default:
733 throw GraalError.shouldNotReachHere();
751
752 public static void emitStore(Value input, SPARCAddress address, PlatformKind kind, SPARCDelayedControlTransfer delayedControlTransfer, LIRFrameState state, CompilationResultBuilder crb,
753 SPARCMacroAssembler masm) {
754 try (ScratchRegister sc = masm.getScratchRegister()) {
755 Register scratch = sc.getRegister();
756 SPARCAddress addr = generateSimm13OffsetLoad(address, masm, scratch);
757 delayedControlTransfer.emitControlTransfer(crb, masm);
758 if (state != null) {
759 crb.recordImplicitException(masm.position(), state);
760 }
761 int byteCount = kind.getSizeInBytes();
762 masm.st(asRegister(input), addr, byteCount);
763 }
764 }
765
766 /**
767 * This method creates a load from the constant section. It automatically respects the different
768 * patterns used for small constant sections (<8k) and large constant sections (>=8k). The
769 * generated patterns by this method must be understood by
770 * CodeInstaller::pd_patch_DataSectionReference (jvmciCodeInstaller_sparc.cpp).
771 */
772 public static void loadFromConstantTable(CompilationResultBuilder crb, SPARCMacroAssembler masm, int byteCount, Register constantTableBase, Constant input, Register dest,
773 SPARCDelayedControlTransfer delaySlotInstruction) {
774 SPARCAddress address;
775 ScratchRegister scratch = null;
776 try {
777 if (masm.isImmediateConstantLoad()) {
778 address = new SPARCAddress(constantTableBase, 0);
779 // Make delayed only, when using immediate constant load.
780 delaySlotInstruction.emitControlTransfer(crb, masm);
781 crb.recordDataReferenceInCode(input, byteCount);
782 } else {
783 scratch = masm.getScratchRegister();
784 Register sr = scratch.getRegister();
785 crb.recordDataReferenceInCode(input, byteCount);
786 masm.sethix(0, sr, true);
787 address = new SPARCAddress(sr, 0);
788 }
789 masm.ld(address, dest, byteCount, false);
790 } finally {
791 if (scratch != null) {
792 scratch.close();
793 }
794 }
795 }
796 }
|
36 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
37 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
38 import static java.lang.Math.max;
39 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
40 import static jdk.vm.ci.code.ValueUtil.asRegister;
41 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
42 import static jdk.vm.ci.code.ValueUtil.isRegister;
43 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
44 import static jdk.vm.ci.sparc.SPARC.g0;
45 import static jdk.vm.ci.sparc.SPARCKind.DOUBLE;
46 import static jdk.vm.ci.sparc.SPARCKind.SINGLE;
47 import static jdk.vm.ci.sparc.SPARCKind.WORD;
48 import static jdk.vm.ci.sparc.SPARCKind.XWORD;
49
50 import java.util.Set;
51
52 import org.graalvm.compiler.asm.sparc.SPARCAddress;
53 import org.graalvm.compiler.asm.sparc.SPARCAssembler;
54 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
55 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
56 import org.graalvm.compiler.code.DataSection.Data;
57 import org.graalvm.compiler.core.common.LIRKind;
58 import org.graalvm.compiler.core.common.type.DataPointerConstant;
59 import org.graalvm.compiler.debug.GraalError;
60 import org.graalvm.compiler.lir.LIRFrameState;
61 import org.graalvm.compiler.lir.LIRInstructionClass;
62 import org.graalvm.compiler.lir.Opcode;
63 import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck;
64 import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
65 import org.graalvm.compiler.lir.StandardOp.NullCheck;
66 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
67 import org.graalvm.compiler.lir.VirtualStackSlot;
68 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
69
70 import jdk.vm.ci.code.Register;
71 import jdk.vm.ci.code.StackSlot;
72 import jdk.vm.ci.meta.AllocatableValue;
73 import jdk.vm.ci.meta.Constant;
74 import jdk.vm.ci.meta.JavaConstant;
75 import jdk.vm.ci.meta.PlatformKind;
76 import jdk.vm.ci.meta.Value;
100 StackSlot slot = asStackSlot(result);
101 const2stack(crb, masm, slot, g0, getDelayedControlTransfer(), constant);
102 }
103 }
104
105 @Override
106 public Constant getConstant() {
107 return constant;
108 }
109
110 @Override
111 public AllocatableValue getResult() {
112 return result;
113 }
114 }
115
116 public static class LoadConstantFromTable extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
117 public static final LIRInstructionClass<LoadConstantFromTable> TYPE = LIRInstructionClass.create(LoadConstantFromTable.class);
118 public static final SizeEstimate SIZE = SizeEstimate.create(1, 8);
119
120 private JavaConstant constant;
121 @Def({REG, STACK}) AllocatableValue result;
122 @Use({REG}) private AllocatableValue constantTableBase;
123
124 public LoadConstantFromTable(JavaConstant constant, AllocatableValue constantTableBase, AllocatableValue result) {
125 super(TYPE, SIZE);
126 this.constant = constant;
127 this.result = result;
128 this.constantTableBase = constantTableBase;
129 }
130
131 @Override
132 public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
133 final int byteCount = result.getPlatformKind().getSizeInBytes();
134 assert byteCount > 1 : "Byte values must not be loaded via constant table";
135 Register baseRegister = asRegister(constantTableBase);
136 if (isRegister(result)) {
137 Register resultRegister = asRegister(result);
138 loadFromConstantTable(crb, masm, baseRegister, constant, resultRegister, getDelayedControlTransfer());
139 } else if (isStackSlot(result)) {
140 try (ScratchRegister scratch = masm.getScratchRegister()) {
141 Register scratchRegister = scratch.getRegister();
142 loadFromConstantTable(crb, masm, baseRegister, constant, scratchRegister, getDelayedControlTransfer());
143 StackSlot slot = asStackSlot(result);
144 reg2stack(crb, masm, slot, scratchRegister.asValue(), getDelayedControlTransfer());
145 }
146 }
147 }
148 }
149
150 @Opcode("MOVE")
151 public static class Move extends SPARCLIRInstruction implements ValueMoveOp, SPARCTailDelayedLIRInstruction {
152 public static final LIRInstructionClass<Move> TYPE = LIRInstructionClass.create(Move.class);
153 public static final SizeEstimate SIZE = SizeEstimate.create(8);
154
155 @Def({REG, STACK, HINT}) protected AllocatableValue result;
156 @Use({REG, STACK}) protected AllocatableValue input;
157
158 public Move(AllocatableValue result, AllocatableValue input) {
159 super(TYPE, SIZE);
160 this.result = result;
161 this.input = input;
162 }
626 * @param scratch The register as scratch to use
627 * @return a loadable SPARCAddress
628 */
629 public static SPARCAddress generateSimm13OffsetLoad(SPARCAddress addr, SPARCMacroAssembler masm, Register scratch) {
630 boolean displacementOutOfBound = addr.getIndex().equals(Register.None) && !SPARCAssembler.isSimm13(addr.getDisplacement());
631 if (displacementOutOfBound) {
632 masm.setx(addr.getDisplacement(), scratch, false);
633 return new SPARCAddress(addr.getBase(), scratch);
634 } else {
635 return addr;
636 }
637 }
638
639 public static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Register constantTableBase, JavaConstant input, SPARCDelayedControlTransfer delaySlotLir) {
640 try (ScratchRegister sc = masm.getScratchRegister()) {
641 Register scratch = sc.getRegister();
642 Set<CPUFeature> cpuFeatures = ((SPARC) masm.target.arch).getFeatures();
643 boolean hasVIS1 = cpuFeatures.contains(CPUFeature.VIS1);
644 boolean hasVIS3 = cpuFeatures.contains(CPUFeature.VIS3);
645 Register resultRegister = asRegister(result);
646 switch (input.getJavaKind().getStackKind()) {
647 case Int:
648 if (input.isDefaultForKind()) {
649 delaySlotLir.emitControlTransfer(crb, masm);
650 masm.clr(resultRegister);
651 } else if (isSimm13(input.asInt())) {
652 delaySlotLir.emitControlTransfer(crb, masm);
653 masm.or(g0, input.asInt(), resultRegister);
654 } else {
655 if (constantTableBase.equals(g0)) {
656 throw GraalError.shouldNotReachHere();
657 } else {
658 loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
659 }
660 }
661 break;
662 case Long:
663 if (input.isDefaultForKind()) {
664 delaySlotLir.emitControlTransfer(crb, masm);
665 masm.clr(resultRegister);
666 } else if (isSimm13(input.asLong())) {
667 delaySlotLir.emitControlTransfer(crb, masm);
668 masm.or(g0, (int) input.asLong(), resultRegister);
669 } else {
670 loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
671 }
672 break;
673 case Float: {
674 float constant = input.asFloat();
675 int constantBits = java.lang.Float.floatToIntBits(constant);
676 if (hasVIS1 && constantBits == 0) {
677 delaySlotLir.emitControlTransfer(crb, masm);
678 masm.fzeros(resultRegister);
679 } else {
680 if (hasVIS3 && isSimm13(constantBits)) {
681 masm.or(g0, constantBits, scratch);
682 delaySlotLir.emitControlTransfer(crb, masm);
683 masm.movwtos(scratch, resultRegister);
684 } else {
685 // First load the address into the scratch register
686 loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
687 }
688 }
689 break;
690 }
691 case Double: {
692 double constant = input.asDouble();
693 long constantBits = java.lang.Double.doubleToRawLongBits(constant);
694 if (hasVIS1 && constantBits == 0) {
695 delaySlotLir.emitControlTransfer(crb, masm);
696 masm.fzerod(resultRegister);
697 } else {
698 if (hasVIS3 && isSimm13(constantBits)) {
699 masm.or(g0, (int) constantBits, scratch);
700 delaySlotLir.emitControlTransfer(crb, masm);
701 masm.movxtod(scratch, resultRegister);
702 } else {
703 loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
704 }
705 }
706 break;
707 }
708 case Object:
709 if (input.isNull()) {
710 delaySlotLir.emitControlTransfer(crb, masm);
711 masm.clr(resultRegister);
712 } else {
713 loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
714 }
715 break;
716 default:
717 throw GraalError.shouldNotReachHere("missing: " + input.getJavaKind());
718 }
719 }
720 }
721
722 protected static void compareAndSwap(CompilationResultBuilder crb, SPARCMacroAssembler masm, AllocatableValue address, AllocatableValue cmpValue, AllocatableValue newValue,
723 SPARCDelayedControlTransfer delay) {
724 delay.emitControlTransfer(crb, masm);
725 switch ((SPARCKind) cmpValue.getPlatformKind()) {
726 case WORD:
727 masm.cas(asRegister(address), asRegister(cmpValue), asRegister(newValue));
728 break;
729 case XWORD:
730 masm.casx(asRegister(address), asRegister(cmpValue), asRegister(newValue));
731 break;
732 default:
733 throw GraalError.shouldNotReachHere();
751
752 public static void emitStore(Value input, SPARCAddress address, PlatformKind kind, SPARCDelayedControlTransfer delayedControlTransfer, LIRFrameState state, CompilationResultBuilder crb,
753 SPARCMacroAssembler masm) {
754 try (ScratchRegister sc = masm.getScratchRegister()) {
755 Register scratch = sc.getRegister();
756 SPARCAddress addr = generateSimm13OffsetLoad(address, masm, scratch);
757 delayedControlTransfer.emitControlTransfer(crb, masm);
758 if (state != null) {
759 crb.recordImplicitException(masm.position(), state);
760 }
761 int byteCount = kind.getSizeInBytes();
762 masm.st(asRegister(input), addr, byteCount);
763 }
764 }
765
766 /**
767 * This method creates a load from the constant section. It automatically respects the different
768 * patterns used for small constant sections (<8k) and large constant sections (>=8k). The
769 * generated patterns by this method must be understood by
770 * CodeInstaller::pd_patch_DataSectionReference (jvmciCodeInstaller_sparc.cpp).
771 *
772 * @return the number of bytes loaded from the constant table
773 */
774 public static int loadFromConstantTable(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register constantTableBase, Constant input, Register dest,
775 SPARCDelayedControlTransfer delaySlotInstruction) {
776 SPARCAddress address;
777 ScratchRegister scratch = null;
778 try {
779 Data data = crb.createDataItem(input);
780 int size = data.getSize();
781 if (masm.isImmediateConstantLoad()) {
782 address = new SPARCAddress(constantTableBase, 0);
783 // Make delayed only, when using immediate constant load.
784 delaySlotInstruction.emitControlTransfer(crb, masm);
785 crb.recordDataReferenceInCode(data, size);
786 } else {
787 scratch = masm.getScratchRegister();
788 Register sr = scratch.getRegister();
789 crb.recordDataReferenceInCode(data, size);
790 masm.sethix(0, sr, true);
791 address = new SPARCAddress(sr, 0);
792 }
793 masm.ld(address, dest, size, false);
794 return size;
795 } finally {
796 if (scratch != null) {
797 scratch.close();
798 }
799 }
800 }
801 }
|