京东自营 + 国补 iPhone 历史最低价          国家补贴 享8折

JDK14/Java14源码在线阅读

/*
 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package org.graalvm.compiler.lir.sparc;

import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CCR_V_SHIFT;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CCR_XCC_SHIFT;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FBPCC;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isSimm13;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Fcc0;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Equal;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.F_Ordered;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fcmpd;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fcmps;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.sparc.SPARC.g0;
import static jdk.vm.ci.sparc.SPARCKind.DOUBLE;
import static jdk.vm.ci.sparc.SPARCKind.SINGLE;
import static jdk.vm.ci.sparc.SPARCKind.WORD;
import static jdk.vm.ci.sparc.SPARCKind.XWORD;

import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.sparc.SPARCAssembler;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;

import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.Value;
import jdk.vm.ci.sparc.SPARC;

public class SPARCArithmetic {
    public static final class FloatConvertOp extends SPARCLIRInstruction {
        public static final LIRInstructionClass<FloatConvertOp> TYPE = LIRInstructionClass.create(FloatConvertOp.class);
        public static final SizeEstimate SIZE = SizeEstimate.create(5);

        @Opcode private final FloatConvert opcode;
        @Def({REG, HINT}) protected AllocatableValue result;
        @Use({REG}) protected Value x;

        public enum FloatConvert {
            F2I,
            D2I,
            F2L,
            D2L
        }

        public FloatConvertOp(FloatConvert opcode, Value x, AllocatableValue result) {
            super(TYPE, SIZE);
            this.opcode = opcode;
            this.x = x;
            this.result = result;
        }

        @Override
        protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
            Label notOrdered = new Label();
            switch (opcode) {
                case F2L:
                    masm.fcmp(Fcc0, Fcmps, asRegister(x, SINGLE), asRegister(x, SINGLE));
                    FBPCC.emit(masm, Fcc0, F_Ordered, ANNUL, PREDICT_TAKEN, notOrdered);
                    masm.fstox(asRegister(x, SINGLE), asRegister(result, DOUBLE));
                    masm.fxtod(asRegister(result), asRegister(result));
                    masm.fsubd(asRegister(result, DOUBLE), asRegister(result, DOUBLE), asRegister(result, DOUBLE));
                    masm.bind(notOrdered);
                    break;
                case F2I:
                    masm.fcmp(Fcc0, Fcmps, asRegister(x, SINGLE), asRegister(x, SINGLE));
                    FBPCC.emit(masm, Fcc0, F_Ordered, ANNUL, PREDICT_TAKEN, notOrdered);
                    masm.fstoi(asRegister(x, SINGLE), asRegister(result, SINGLE));
                    masm.fitos(asRegister(result, SINGLE), asRegister(result, SINGLE));
                    masm.fsubs(asRegister(result, SINGLE), asRegister(result, SINGLE), asRegister(result, SINGLE));
                    masm.bind(notOrdered);
                    break;
                case D2L:
                    masm.fcmp(Fcc0, Fcmpd, asRegister(x, DOUBLE), asRegister(x, DOUBLE));
                    FBPCC.emit(masm, Fcc0, F_Ordered, ANNUL, PREDICT_TAKEN, notOrdered);
                    masm.fdtox(asRegister(x, DOUBLE), asRegister(result, DOUBLE));
                    masm.fxtod(asRegister(result, DOUBLE), asRegister(result, DOUBLE));
                    masm.fsubd(asRegister(result, DOUBLE), asRegister(result, DOUBLE), asRegister(result, DOUBLE));
                    masm.bind(notOrdered);
                    break;
                case D2I:
                    masm.fcmp(Fcc0, Fcmpd, asRegister(x, DOUBLE), asRegister(x, DOUBLE));
                    FBPCC.emit(masm, Fcc0, F_Ordered, ANNUL, PREDICT_TAKEN, notOrdered);
                    masm.fdtoi(asRegister(x, DOUBLE), asRegister(result, SINGLE));
                    masm.fitos(asRegister(result, SINGLE), asRegister(result, SINGLE));
                    masm.fsubs(asRegister(result, SINGLE), asRegister(result, SINGLE), asRegister(result, SINGLE));
                    masm.bind(notOrdered);
                    break;
                default:
                    throw GraalError.shouldNotReachHere("missing: " + opcode);
            }
        }
    }

    /**
     * Special LIR instruction as it requires a bunch of scratch registers.
     */
    public static final class RemOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
        public static final LIRInstructionClass<RemOp> TYPE = LIRInstructionClass.create(RemOp.class);
        public static final SizeEstimate SIZE = SizeEstimate.create(4);

        @Opcode private final Rem opcode;
        @Def({REG}) protected AllocatableValue result;
        @Alive({REG, CONST}) protected Value x;
        @Alive({REG, CONST}) protected Value y;
        @Temp({REG}) protected AllocatableValue scratch1;
        @Temp({REG}) protected AllocatableValue scratch2;
        @State protected LIRFrameState state;

        public enum Rem {
            IUREM,
            LUREM
        }

        public RemOp(Rem opcode, AllocatableValue result, Value x, Value y, AllocatableValue scratch1, AllocatableValue scratch2, LIRFrameState state) {
            super(TYPE, SIZE);
            this.opcode = opcode;
            this.result = result;
            this.x = x;
            this.y = y;
            this.scratch1 = scratch1;
            this.scratch2 = scratch2;
            this.state = state;
        }

        @Override
        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
            if (!isJavaConstant(x) && isJavaConstant(y)) {
                assert isSimm13(crb.asIntConst(y));
                assert !x.equals(scratch1);
                assert !x.equals(scratch2);
                assert !y.equals(scratch1);
                switch (opcode) {
                    case LUREM:
                        if (state != null) {
                            crb.recordImplicitException(masm.position(), state);
                        }
                        masm.udivx(asRegister(x, XWORD), crb.asIntConst(y), asRegister(scratch1, XWORD));
                        masm.mulx(asRegister(scratch1, XWORD), crb.asIntConst(y), asRegister(scratch2, XWORD));
                        getDelayedControlTransfer().emitControlTransfer(crb, masm);
                        masm.sub(asRegister(x, XWORD), asRegister(scratch2, XWORD), asRegister(result, XWORD));
                        break;
                    case IUREM:
                        GraalError.unimplemented();
                        break;
                    default:
                        throw GraalError.shouldNotReachHere();
                }
            } else if (isRegister(x) && isRegister(y)) {
                Value xLeft = x;
                switch (opcode) {
                    case LUREM:
                        if (isJavaConstant(x)) {
                            masm.setx(crb.asLongConst(x), asRegister(scratch2, XWORD), false);
                            xLeft = scratch2;
                        }
                        assert !asRegister(xLeft, XWORD).equals(asRegister(scratch1, XWORD));
                        assert !asRegister(y, XWORD).equals(asRegister(scratch1, XWORD));
                        if (state != null) {
                            crb.recordImplicitException(masm.position(), state);
                        }
                        masm.udivx(asRegister(xLeft, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD));
                        masm.mulx(asRegister(scratch1, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD));
                        getDelayedControlTransfer().emitControlTransfer(crb, masm);
                        masm.sub(asRegister(xLeft, XWORD), asRegister(scratch1, XWORD), asRegister(result, XWORD));
                        break;
                    case IUREM:
                        assert !asRegister(result, WORD).equals(asRegister(scratch1, WORD));
                        assert !asRegister(result, WORD).equals(asRegister(scratch2, WORD));
                        masm.srl(asRegister(x, WORD), 0, asRegister(scratch1, WORD));
                        masm.srl(asRegister(y, WORD), 0, asRegister(result, WORD));
                        if (state != null) {
                            crb.recordImplicitException(masm.position(), state);
                        }
                        masm.udivx(asRegister(scratch1, WORD), asRegister(result, WORD), asRegister(scratch2, WORD));
                        masm.mulx(asRegister(scratch2, WORD), asRegister(result, WORD), asRegister(result, WORD));
                        getDelayedControlTransfer().emitControlTransfer(crb, masm);
                        masm.sub(asRegister(scratch1, WORD), asRegister(result, WORD), asRegister(result, WORD));
                        break;
                    default:
                        throw GraalError.shouldNotReachHere();
                }
            } else {
                throw GraalError.shouldNotReachHere();
            }
        }
    }

    public static final class SPARCIMulccOp extends SPARCLIRInstruction {
        public static final LIRInstructionClass<SPARCIMulccOp> TYPE = LIRInstructionClass.create(SPARCIMulccOp.class);
        public static final SizeEstimate SIZE = SizeEstimate.create(10);
        @Def({REG}) protected AllocatableValue result;
        @Alive({REG}) protected AllocatableValue x;
        @Alive({REG}) protected AllocatableValue y;

        public SPARCIMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y) {
            super(TYPE, SIZE);
            this.result = result;
            this.x = x;
            this.y = y;
        }

        @Override
        protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
            try (ScratchRegister tmpScratch = masm.getScratchRegister()) {
                Register tmp = tmpScratch.getRegister();
                Register resultRegister = asRegister(result, WORD);
                Register xRegister = asRegister(x, WORD);
                Register yRegister = asRegister(y, WORD);
                masm.sra(xRegister, 0, xRegister);
                masm.sra(yRegister, 0, yRegister);
                masm.mulx(xRegister, yRegister, resultRegister);
                Label noOverflow = new Label();
                masm.sra(resultRegister, 0, tmp);
                masm.compareBranch(tmp, resultRegister, Equal, Xcc, noOverflow, PREDICT_TAKEN, null);
                masm.wrccr(SPARC.g0, 1 << (SPARCAssembler.CCR_ICC_SHIFT + SPARCAssembler.CCR_V_SHIFT));
                masm.bind(noOverflow);
            }
        }
    }

    /**
     * Calculates the product and condition code for long multiplication of long values.
     */
    public static final class SPARCLMulccOp extends SPARCLIRInstruction {
        public static final LIRInstructionClass<SPARCLMulccOp> TYPE = LIRInstructionClass.create(SPARCLMulccOp.class);
        public static final SizeEstimate SIZE = SizeEstimate.create(13);

        @Def({REG}) protected AllocatableValue result;
        @Alive({REG}) protected AllocatableValue x;
        @Alive({REG}) protected AllocatableValue y;
        @Temp({REG}) protected AllocatableValue scratch1;
        @Temp({REG}) protected AllocatableValue scratch2;

        public SPARCLMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y, LIRGeneratorTool gen) {
            super(TYPE, SIZE);
            this.result = result;
            this.x = x;
            this.y = y;
            this.scratch1 = gen.newVariable(LIRKind.combine(x, y));
            this.scratch2 = gen.newVariable(LIRKind.combine(x, y));
        }

        @Override
        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
            Label noOverflow = new Label();
            masm.mulx(asRegister(x, XWORD), asRegister(y, XWORD), asRegister(result, XWORD));

            // Calculate the upper 64 bit signed := (umulxhi product - (x{63}&y + y{63}&x))
            masm.umulxhi(asRegister(x, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD));
            masm.srax(asRegister(x, XWORD), 63, asRegister(scratch2, XWORD));
            masm.and(asRegister(scratch2, XWORD), asRegister(y, XWORD), asRegister(scratch2, XWORD));
            masm.sub(asRegister(scratch1, XWORD), asRegister(scratch2, XWORD), asRegister(scratch1, XWORD));

            masm.srax(asRegister(y, XWORD), 63, asRegister(scratch2, XWORD));
            masm.and(asRegister(scratch2, XWORD), asRegister(x, XWORD), asRegister(scratch2, XWORD));
            masm.sub(asRegister(scratch1, XWORD), asRegister(scratch2, XWORD), asRegister(scratch1, XWORD));

            // Now construct the lower half and compare
            masm.srax(asRegister(result, XWORD), 63, asRegister(scratch2, XWORD));
            masm.cmp(asRegister(scratch1, XWORD), asRegister(scratch2, XWORD));
            BPCC.emit(masm, Xcc, Equal, NOT_ANNUL, PREDICT_TAKEN, noOverflow);
            masm.nop();
            masm.wrccr(g0, 1 << (CCR_XCC_SHIFT + CCR_V_SHIFT));
            masm.bind(noOverflow);
        }
    }

    public static final class MulHighOp extends SPARCLIRInstruction {
        public static final LIRInstructionClass<MulHighOp> TYPE = LIRInstructionClass.create(MulHighOp.class);
        public static final SizeEstimate SIZE = SizeEstimate.create(4);

        @Opcode private final MulHigh opcode;
        @Def({REG}) public AllocatableValue result;
        @Alive({REG}) public AllocatableValue x;
        @Alive({REG}) public AllocatableValue y;
        @Temp({REG}) public AllocatableValue scratch;

        public enum MulHigh {
            IMUL,
            LMUL
        }


/**代码未完, 请加载全部代码(NowJava.com).**/
展开阅读全文

关注时代Java

关注时代Java