x86bytecodevisitor.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 2,035 行 · 第 1/5 页

JAVA
2,035
字号
        os.writeADD(Register.ECX, Register.EAX); // hi2*lo1 + hi1*lo2
        os.writeMOV(INTSIZE, Register.EAX, Register.ESI); // lo2
        os.writeMUL_EAX(Register.EBX); // lo1*lo2
        os.writeADD(Register.EDX, Register.ECX); // hi2*lo1 + hi1*lo2 +
        // hi(lo1*lo2)
        os.setObjectRef(tmp2);
        // Reload the statics table, since it was destroyed here
        helper.writeLoadSTATICS(curInstrLabel, "lmul", false);
        helper.writePUSH64(Register.EAX, Register.EDX);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lneg()
     */
    public final void visit_lneg() {
        helper.writePOP64(T0, T1);
        os.writeNEG(T1); // msb := -msb
        os.writeNEG(T0); // lsb := -lsb
        os.writeSBB(T1, 0); // high += borrow
        helper.writePUSH64(T0, T1);
        /*
         * os.writeNEG(SP, 0); os.writeNEG(SP, 4);
         */
    }

    /**
     * @param defAddress
     * @param matchValues
     * @param addresses
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lookupswitch(int,
     *      int[], int[])
     */
    public final void visit_lookupswitch(int defAddress, int[] matchValues,
            int[] addresses) {
        final int n = matchValues.length;
        //BootLog.debug("lookupswitch length=" + n);
        helper.writePOP(Register.EAX); // Key
        for (int i = 0; i < n; i++) {
            os.writeCMP_EAX(matchValues[ i]);
            os.writeJCC(helper.getInstrLabel(addresses[ i]), X86Constants.JE); // JE
        }
        os.writeJMP(helper.getInstrLabel(defAddress));
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lor()
     */
    public final void visit_lor() {
        helper.writePOP64(T0, T1); // Value 2
        helper.writePOP64(S0, S1); // Value 1
        os.writeOR(S0, T0);
        os.writeOR(S1, T1);
        helper.writePUSH64(S0, S1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lrem()
     */
    public final void visit_lrem() {
        helper.invokeJavaMethod(context.getLremMethod());
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lreturn()
     */
    public final void visit_lreturn() {
        helper.writePOP64(T0, T1);
        visit_return();
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lshl()
     */
    public final void visit_lshl() {
        helper.writePOP(Register.ECX); // Value 2
        helper.writePOP64(Register.EAX, Register.EDX); // Value 1
        os.writeAND(Register.ECX, 63);
        os.writeCMP(Register.ECX, 32);
        Label gt32Label = new Label(curInstrLabel + "gt32");
        Label endLabel = new Label(curInstrLabel + "end");
        os.writeJCC(gt32Label, X86Constants.JAE); // JAE
        /** ECX < 32 */
        os.writeSHLD_CL(Register.EDX, Register.EAX);
        os.writeSHL_CL(Register.EAX);
        os.writeJMP(endLabel);
        /** ECX >= 32 */
        os.setObjectRef(gt32Label);
        os.writeMOV(INTSIZE, Register.EDX, Register.EAX);
        os.writeXOR(Register.EAX, Register.EAX);
        os.writeSHL_CL(Register.EDX);
        os.setObjectRef(endLabel);
        helper.writePUSH64(Register.EAX, Register.EDX);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lshr()
     */
    public final void visit_lshr() {
        helper.writePOP(Register.ECX); // Value 2
        helper.writePOP64(Register.EAX, Register.EDX); // Value 1
        os.writeAND(Register.ECX, 63);
        os.writeCMP(Register.ECX, 32);
        Label gt32Label = new Label(curInstrLabel + "gt32");
        Label endLabel = new Label(curInstrLabel + "end");
        os.writeJCC(gt32Label, X86Constants.JAE); // JAE
        /** ECX < 32 */
        os.writeSHRD_CL(Register.EAX, Register.EDX);
        os.writeSAR_CL(Register.EDX);
        os.writeJMP(endLabel);
        /** ECX >= 32 */
        os.setObjectRef(gt32Label);
        os.writeMOV(INTSIZE, Register.EAX, Register.EDX);
        os.writeSAR(Register.EDX, 31);
        os.writeSAR_CL(Register.EAX);
        os.setObjectRef(endLabel);
        helper.writePUSH64(Register.EAX, Register.EDX);
    }

    /**
     * @param index
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lstore(int)
     */
    public final void visit_lstore(int index) {
        int ebpOfs = stackFrame.getWideEbpOffset(index);
        helper.writePOP64(T0, T1);
        os.writeMOV(INTSIZE, FP, ebpOfs, T0);
        os.writeMOV(INTSIZE, FP, ebpOfs + 4, T1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lsub()
     */
    public final void visit_lsub() {
        helper.writePOP64(T0, T1); // Value 2
        helper.writePOP64(S0, S1); // Value 1
        os.writeSUB(S0, T0);
        os.writeSBB(S1, T1);
        helper.writePUSH64(S0, S1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lushr()
     */
    public final void visit_lushr() {
        helper.writePOP(Register.ECX); // Value 2
        helper.writePOP64(Register.EAX, Register.EDX); // Value 1
        os.writeAND(Register.ECX, 63);
        os.writeCMP(Register.ECX, 32);
        Label gt32Label = new Label(curInstrLabel + "gt32");
        Label endLabel = new Label(curInstrLabel + "end");
        os.writeJCC(gt32Label, X86Constants.JAE); // JAE
        /** ECX < 32 */
        os.writeSHRD_CL(Register.EAX, Register.EDX);
        os.writeSHR_CL(Register.EDX);
        os.writeJMP(endLabel);
        /** ECX >= 32 */
        os.setObjectRef(gt32Label);
        os.writeMOV(INTSIZE, Register.EAX, Register.EDX);
        os.writeXOR(Register.EDX, Register.EDX);
        os.writeSHR_CL(Register.EAX);
        os.setObjectRef(endLabel);
        helper.writePUSH64(Register.EAX, Register.EDX);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lxor()
     */
    public final void visit_lxor() {
        helper.writePOP64(T0, T1); // Value 2
        helper.writePOP64(S0, S1); // Value 1
        os.writeXOR(S0, T0);
        os.writeXOR(S1, T1);
        helper.writePUSH64(S0, S1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_monitorenter()
     */
    public final void visit_monitorenter() {
        // Objectref is already on the stack
        helper.invokeJavaMethod(context.getMonitorEnterMethod());
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_monitorexit()
     */
    public final void visit_monitorexit() {
        // Objectref is already on the stack
        helper.invokeJavaMethod(context.getMonitorExitMethod());
    }

    /**
     * @param clazz
     * @param dimensions
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_multianewarray(VmConstClass,
     *      int)
     */
    public final void visit_multianewarray(VmConstClass clazz, int dimensions) {
        System.out.println("multianewarray not implemented yet in "
                + helper.getMethod());
        // Dummy to maintain the stack structure, but cause a
        // NullPointerException
        for (int i = 0; i < dimensions; i++) {
            helper.writePOP(Register.EAX);
        }
        helper.writePUSH(0);
    }

    /**
     * @param classRef
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_new(org.jnode.vm.classmgr.VmConstClass)
     */
    public final void visit_new(VmConstClass classRef) {
        writeResolveAndLoadClassToEAX(classRef, S0);
        /* Setup a call to SoftByteCodes.allocObject */
        helper.writePUSH(Register.EAX); /* vmClass */
        helper.writePUSH(-1); /* Size */
        helper.invokeJavaMethod(context.getAllocObjectMethod());
        /* Result is already on the stack */
    }

    /**
     * @param type
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_newarray(int)
     */
    public final void visit_newarray(int type) {
        helper.writePOP(S0); /* Elements */

        /* Setup a call to SoftByteCodes.allocArray */
        helper.writePUSH(type); /* type */
        helper.writePUSH(S0); /* elements */
        helper.invokeJavaMethod(context.getAllocPrimitiveArrayMethod());
        /* Result is already on the stack */
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_nop()
     */
    public final void visit_nop() {
        os.writeNOP();
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_pop()
     */
    public final void visit_pop() {
        os.writeLEA(SP, SP, 4);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_pop2()
     */
    public final void visit_pop2() {
        os.writeLEA(SP, SP, 8);
    }

    /**
     * @param fieldRef
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_putfield(org.jnode.vm.classmgr.VmConstFieldRef)
     */
    public final void visit_putfield(VmConstFieldRef fieldRef) {
        fieldRef.resolve(loader);
        final VmField field = fieldRef.getResolvedVmField();
        if (field.isStatic()) { throw new IncompatibleClassChangeError(
                "getfield called on static field " + fieldRef.getName()); }
        final VmInstanceField inf = (VmInstanceField) field;
        final int offset = inf.getOffset();

        if (!fieldRef.isWide()) {
            /* Value -> T0 */
            helper.writePOP(T0);
        } else {
            /* Value LSB -> T0 */
            helper.writePOP(T0);
            /* Value MSB -> T1 */
            helper.writePOP(T1);
        }
        /* Objectref -> S0 */
        helper.writePOP(S0); // Objectref
        /* Get the data */
        if (!fieldRef.isWide()) {
            os.writeMOV(INTSIZE, S0, offset, T0);
            helper.writePutfieldWriteBarrier(inf, S0, T0, S1);
        } else {
            /** Msb */
            os.writeMOV(INTSIZE, S0, offset + 4, T1);
            /** Lsb */
            os.writeMOV(INTSIZE, S0, offset, T0);
        }
    }

    /**
     * @param fieldRef
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_putstatic(org.jnode.vm.classmgr.VmConstFieldRef)
     */
    public final void visit_putstatic(VmConstFieldRef fieldRef) {
        fieldRef.resolve(loader);
        final VmStaticField sf = (VmStaticField) fieldRef.getResolvedVmField();

        if (!sf.getDeclaringClass().isInitialized()) {
            writeInitializeClass(fieldRef, S0);
        }
        // Put static field
        if (!fieldRef.isWide()) {
            helper.writePOP(T0);
            helper.writePutStaticsEntry(curInstrLabel, T0, sf);
            helper.writePutstaticWriteBarrier(sf, T0, S1);
        } else {
            helper.writePOP64(T0, T1);
            helper.writePutStaticsEntry64(curInstrLabel, T0, T1, sf);
        }
    }

    /**
     * @param index
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ret(int)
     */
    public final void visit_ret(int index) {
        final int ebpOfs = stackFrame.getEbpOffset(index);
        os.writeMOV(INTSIZE, T0, FP, ebpOfs);
        os.writeJMP(T0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_return()
     */
    public final void visit_return() {
        stackFrame.emitReturn();
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_saload()
     */
    public final void visit_saload() {
        helper.writePOP(T0); // Index
        helper.writePOP(S0); // Arrayref
        checkBounds(S0, T0);
        os.writeMOV(WORDSIZE, T0, S0, T0, 2, VmArray.DATA_OFFSET * 4);
        os.writeMOVSX(T0, T0, WORDSIZE);
        helper.writePUSH(T0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_sastore()
     */
    public final void visit_sastore() {
        helper.writePOP(T1); // Value
        helper.writePOP(T0); // Index
        helper.writePOP(S0); // Arrayref
        checkBounds(S0, T0);
        os.writeMOV(WORDSIZE, S0, T0, 2, VmArray.DATA_OFFSET * 4, T1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_swap()
     */
    public final void visit_swap() {
        helper.writePOP(T0); // Value1
        helper.writePOP(S0); // Value2
        helper.writePUSH(T0); // Value1
        helper.writePUSH(S0); // Value2
    }

    /**
     * @param defAddress
     * @param lowValue
     * @param highValue
     * @param addresses
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_tableswitch(int, int,
     *      int, int[])
     */
    public final void visit_tableswitch(int defAddress, int lowValue,
            int highValue, int[] addresses) {
        final int n = addresses.length;

        helper.writePOP(Register.EAX);
        if (n > 8) {

            // Optimized jumptable.
            // This has some overhead to call, so only worth while for large
            // tableswitches.
            if (lowValue != 0) {
                os.writeSUB(EAX, lowValue);
            }
            // If outsite low-high range, jump to default
            os.writeCMP(EAX, n);
            os.writeJCC(helper.getInstrLabel(defAddress), X86Constants.JAE);

            final Label l1 = new Label(curInstrLabel + "$$l1");
            final Label l2 = new Label(curInstrLabel + "$$l2");
            final int l1Ofs;
            final int l2Ofs;
            final int l12distance = 12;

            // Get absolute address of l1 into S0. (do not use
            // helper.writePOP!)
            os.writeCALL(l1);
            os.setObjectRef(l1);
            l1Ofs = os.getLength();
            os.writePOP(S0);

            // Calculate absolute address of jumptable entry into S1
            os.writeLEA(S1, S0, EAX, 4, l12distance);

            // Calculate absolute address of jump target
            os.writeADD(S1, S1, 0);
            os.writeLEA(S1, S1, 4); // Compensate for writ

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?