Example usage for org.objectweb.asm Opcodes POP

List of usage examples for org.objectweb.asm Opcodes POP

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes POP.

Prototype

int POP

To view the source code for org.objectweb.asm Opcodes POP.

Click Source Link

Usage

From source file:jerl.bcm.inj.impl.InjectCollection.java

License:Apache License

public void injectReplaceStackInt(MethodVisitor mv, int i) {
    mv.visitInsn(Opcodes.POP);
    mv.visitLdcInsn(new Integer(i));
}

From source file:jerl.bcm.inj.impl.MethodCallRemove.java

License:Apache License

@Override
public void inject(MethodVisitor mv) {
    // TODO Auto-generated method stub
    // pop arguments
    Type[] args = Type.getArgumentTypes(desc);
    for (int i = 0; i < args.length; i++) {
        if (args[i].getSort() == Type.DOUBLE || args[i].getSort() == Type.LONG) {
            mv.visitInsn(Opcodes.POP2);/* w ww. ja va  2s .c om*/
        } else {
            mv.visitInsn(Opcodes.POP);
        }
    }
    if (opcode == Opcodes.INVOKESTATIC) {
    } else {
        mv.visitInsn(Opcodes.POP);
    }
}

From source file:jpcsp.Allegrex.compiler.CodeInstruction.java

License:Open Source License

private int loadRegistersForBranchingOpcodeBranch2(CompilerContext context, MethodVisitor mv,
        int branchingOpcode) {
    boolean loadRs = true;
    boolean loadRt = true;

    if (context.getRsRegisterIndex() == context.getRtRegisterIndex()) {
        if (branchingOpcode == Opcodes.IF_ICMPEQ) {
            loadRs = false;//from w ww. j  a  v a2  s.  com
            loadRt = false;
            branchingOpcode = Opcodes.GOTO;

            // The ASM library has problems with small frames having no
            // stack (NullPointerException). Generate a dummy stack requirement:
            //   ILOAD 0
            //   POP
            context.loadImm(0);
            context.getMethodVisitor().visitInsn(Opcodes.POP);
        } else if (branchingOpcode == Opcodes.IF_ICMPNE) {
            loadRs = false;
            loadRt = false;
            branchingOpcode = Opcodes.NOP;
        }
    } else if (context.isRsRegister0()) {
        if (branchingOpcode == Opcodes.IF_ICMPEQ) {
            loadRs = false;
            branchingOpcode = Opcodes.IFEQ;
        } else if (branchingOpcode == Opcodes.IF_ICMPNE) {
            loadRs = false;
            branchingOpcode = Opcodes.IFNE;
        }
    } else if (context.isRtRegister0()) {
        if (branchingOpcode == Opcodes.IF_ICMPEQ) {
            loadRt = false;
            branchingOpcode = Opcodes.IFEQ;
        } else if (branchingOpcode == Opcodes.IF_ICMPNE) {
            loadRt = false;
            branchingOpcode = Opcodes.IFNE;
        }
    }

    if (loadRs) {
        context.loadRs();
    }
    if (loadRt) {
        context.loadRt();
    }

    return branchingOpcode;
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

private void storeVRegister(int vsize, int reg, int n, VfpuPfxDstState pfxDstState, boolean isFloat) {
    if (log.isTraceEnabled() && pfxDstState != null && pfxDstState.isKnown() && pfxDstState.pfxDst.enabled) {
        log.trace(String.format("PFX    %08X - storeVRegister %d, %d, %d", getCodeInstruction().getAddress(),
                vsize, reg, n));/* w w  w .ja v  a 2  s. c  o  m*/
    }

    if (preparedRegisterForStore == reg) {
        if (isPfxDstMasked(pfxDstState, n)) {
            if (log.isTraceEnabled() && pfxDstState != null && pfxDstState.isKnown()
                    && pfxDstState.pfxDst.enabled) {
                log.trace(String.format("PFX    %08X - storeVRegister %d masked",
                        getCodeInstruction().getAddress(), n));
            }

            mv.visitInsn(Opcodes.POP);
        } else {
            applyPfxDstPostfix(pfxDstState, n, isFloat);
            if (isFloat) {
                // Keep a copy of the value for the int value
                mv.visitInsn(Opcodes.DUP_X2);
                mv.visitInsn(Opcodes.FASTORE); // First store the float value
                convertVFloatToInt();
                mv.visitInsn(Opcodes.IASTORE); // Second store the int value
            } else {
                // Keep a copy of the value for the float value
                mv.visitInsn(Opcodes.DUP_X2);
                mv.visitInsn(Opcodes.IASTORE); // First store the int value
                convertVIntToFloat();
                mv.visitInsn(Opcodes.FASTORE); // Second store the float value
            }
        }
        preparedRegisterForStore = -1;
    } else {
        log.error("storeVRegister with non-prepared register is not supported");
    }
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

@Override
public void storeHilo() {
    if (!hiloPrepared) {
        loadCpu();// w  w  w  . j  a  v a  2 s. c  o m
        mv.visitInsn(Opcodes.DUP_X2);
        mv.visitInsn(Opcodes.POP);
    }
    mv.visitFieldInsn(Opcodes.PUTFIELD, cpuInternalName, "hilo", Type.getDescriptor(long.class));

    hiloPrepared = false;
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

private void visitContinueToAddress(int returnAddress, boolean returnOnUnknownAddress) {
    //      if (x != returnAddress) {
    //          RuntimeContext.jump(x, returnAddress);
    //      }/*w w w  .  ja  v a  2s  .  c  o m*/
    Label continueLabel = new Label();
    Label isReturnAddress = new Label();

    mv.visitInsn(Opcodes.DUP);
    loadImm(returnAddress);
    visitJump(Opcodes.IF_ICMPEQ, isReturnAddress);

    if (returnOnUnknownAddress) {
        visitJump();
    } else {
        loadImm(returnAddress);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "jump", "(II)V");
        mv.visitJumpInsn(Opcodes.GOTO, continueLabel);
    }

    mv.visitLabel(isReturnAddress);
    mv.visitInsn(Opcodes.POP);
    mv.visitLabel(continueLabel);
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

private void visitContinueToAddressInRegister(int reg) {
    //      if (x != cpu.reg) {
    //          RuntimeContext.jump(x, cpu.reg);
    //      }/*from w w w . j ava 2  s . com*/
    Label continueLabel = new Label();
    Label isReturnAddress = new Label();

    mv.visitInsn(Opcodes.DUP);
    loadRegister(reg);
    visitJump(Opcodes.IF_ICMPEQ, isReturnAddress);

    loadRegister(reg);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "jump", "(II)V");
    mv.visitJumpInsn(Opcodes.GOTO, continueLabel);

    mv.visitLabel(isReturnAddress);
    mv.visitInsn(Opcodes.POP);
    mv.visitLabel(continueLabel);
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

private void logSyscall(HLEModuleFunction func, String logPrefix, String logCheckFunction, String logFunction) {
    // Modules.getLogger(func.getModuleName()).warn("Unimplemented...");
    loadModuleLoggger(func);/*from  w  w  w  .j av  a 2 s  . c o m*/
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), logCheckFunction, "()Z");
    Label loggingDisabled = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, loggingDisabled);

    loadModuleLoggger(func);

    StringBuilder formatString = new StringBuilder();
    if (logPrefix != null) {
        formatString.append(logPrefix);
    }
    formatString.append(func.getFunctionName());
    ParameterInfo[] parameters = new ClassAnalyzer().getParameters(func.getFunctionName(),
            func.getHLEModuleMethod().getDeclaringClass());
    if (parameters != null) {
        // Log message:
        //    String.format(
        //       "Unimplemented <function name>
        //                 <parameterIntegerName>=0x%X,
        //                 <parameterBooleanName>=%b,
        //                 <parameterLongName>=0x%X,
        //                 <parameterFloatName>=%f,
        //                 <parameterOtherTypeName>=%s",
        //       new Object[] {
        //                 new Integer(parameterValueInteger),
        //                 new Boolean(parameterValueBoolean),
        //                 new Long(parameterValueLong),
        //                 new Float(parameterValueFloat),
        //                 parameterValueOtherTypes
        //       })
        loadImm(parameters.length);
        mv.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class));
        CompilerParameterReader parameterReader = new CompilerParameterReader(this);
        Annotation[][] paramsAnotations = func.getHLEModuleMethod().getParameterAnnotations();
        int objectArrayIndex = 0;
        for (int paramIndex = 0; paramIndex < parameters.length; paramIndex++) {
            ParameterInfo parameter = parameters[paramIndex];
            Class<?> parameterType = parameter.type;
            CompilerTypeInformation typeInformation = compilerTypeManager
                    .getCompilerTypeInformation(parameterType);

            mv.visitInsn(Opcodes.DUP);
            loadImm(objectArrayIndex);

            formatString.append(paramIndex > 0 ? ", " : " ");
            formatString.append(parameter.name);
            formatString.append("=");
            formatString.append(typeInformation.formatString);

            if (typeInformation.boxingTypeInternalName != null) {
                mv.visitTypeInsn(Opcodes.NEW, typeInformation.boxingTypeInternalName);
                mv.visitInsn(Opcodes.DUP);
            }

            loadParameter(parameterReader, func, parameterType, paramsAnotations[paramIndex], null, null);

            if (typeInformation.boxingTypeInternalName != null) {
                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, typeInformation.boxingTypeInternalName, "<init>",
                        typeInformation.boxingMethodDescriptor);
            }
            mv.visitInsn(Opcodes.AASTORE);

            objectArrayIndex++;
        }
        mv.visitLdcInsn(formatString.toString());
        mv.visitInsn(Opcodes.SWAP);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "format",
                "(" + Type.getDescriptor(String.class) + "[" + Type.getDescriptor(Object.class) + ")"
                        + Type.getDescriptor(String.class));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), logFunction,
                "(" + Type.getDescriptor(Object.class) + ")V");

        parameterReader = new CompilerParameterReader(this);
        for (int paramIndex = 0; paramIndex < parameters.length; paramIndex++) {
            ParameterInfo parameter = parameters[paramIndex];
            Class<?> parameterType = parameter.type;

            LengthInfo lengthInfo = BufferInfo.defaultLengthInfo;
            int length = BufferInfo.defaultLength;
            Usage usage = BufferInfo.defaultUsage;
            for (Annotation parameterAnnotation : paramsAnotations[paramIndex]) {
                if (parameterAnnotation instanceof BufferInfo) {
                    BufferInfo bufferInfo = (BufferInfo) parameterAnnotation;
                    lengthInfo = bufferInfo.lengthInfo();
                    length = bufferInfo.length();
                    usage = bufferInfo.usage();
                }
            }

            boolean parameterRead = false;
            if ((usage == Usage.in || usage == Usage.inout)
                    && (lengthInfo != LengthInfo.unknown || parameterType == TPointer16.class
                            || parameterType == TPointer32.class || parameterType == TPointer64.class)) {
                loadModuleLoggger(func);
                loadImm(1);
                mv.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class));
                mv.visitInsn(Opcodes.DUP);
                loadImm(0);

                Label done = new Label();
                Label addressNull = new Label();
                parameterReader.loadNextInt();
                parameterRead = true;
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFEQ, addressNull);

                String format = String.format("%s[%s]:%%s", parameter.name, usage);
                boolean useMemoryDump = true;

                switch (lengthInfo) {
                case fixedLength:
                    loadImm(length);
                    break;
                case nextNextParameter:
                    parameterReader.skipNextInt();
                    paramIndex++;
                    parameterReader.loadNextInt();
                    paramIndex++;
                    break;
                case nextParameter:
                    parameterReader.loadNextInt();
                    paramIndex++;
                    break;
                case previousParameter:
                    // Go back to the address parameter
                    parameterReader.rewindPreviousInt();
                    // Go back to the previous parameter
                    parameterReader.rewindPreviousInt();
                    // Load the length from the previous parameter
                    parameterReader.loadNextInt();
                    // Skip again the address parameter
                    // to come back to the above situation
                    parameterReader.skipNextInt();
                    break;
                case variableLength:
                    mv.visitInsn(Opcodes.DUP);
                    loadMemory();
                    mv.visitInsn(Opcodes.SWAP);
                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read32", "(I)I");
                    break;
                case unknown:
                    useMemoryDump = false;
                    format = String.format("%s[%s]: 0x%%X", parameter.name, usage);
                    loadMemory();
                    mv.visitInsn(Opcodes.SWAP);
                    if (parameterType == TPointer64.class) {
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read64", "(I)J");
                        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Long.class));
                        mv.visitInsn(Opcodes.DUP);
                        mv.visitInsn(Opcodes.DUP2_X2);
                        mv.visitInsn(Opcodes.POP2);
                        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Long.class), "<init>",
                                "(J)V");
                    } else if (parameterType == TPointer16.class) {
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read16", "(I)I");
                        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Integer.class));
                        mv.visitInsn(Opcodes.DUP_X1);
                        mv.visitInsn(Opcodes.SWAP);
                        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Integer.class), "<init>",
                                "(I)V");
                    } else {
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read32", "(I)I");
                        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Integer.class));
                        mv.visitInsn(Opcodes.DUP_X1);
                        mv.visitInsn(Opcodes.SWAP);
                        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Integer.class), "<init>",
                                "(I)V");
                    }
                    break;
                default:
                    log.error(String.format("Unimplemented lengthInfo=%s", lengthInfo));
                    break;
                }

                if (useMemoryDump) {
                    mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Utilities.class),
                            "getMemoryDump", "(II)" + Type.getDescriptor(String.class));
                }
                mv.visitInsn(Opcodes.AASTORE);

                mv.visitLdcInsn(format);
                mv.visitInsn(Opcodes.SWAP);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "format",
                        "(" + Type.getDescriptor(String.class) + "[" + Type.getDescriptor(Object.class) + ")"
                                + Type.getDescriptor(String.class));
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), logFunction,
                        "(" + Type.getDescriptor(Object.class) + ")V");
                mv.visitJumpInsn(Opcodes.GOTO, done);

                mv.visitLabel(addressNull);
                mv.visitInsn(Opcodes.POP);
                mv.visitInsn(Opcodes.POP2);
                mv.visitInsn(Opcodes.POP2);
                mv.visitLabel(done);
            }

            if (!parameterRead) {
                if (parameterType == long.class) {
                    parameterReader.skipNextLong();
                } else if (parameterType == float.class) {
                    parameterReader.skipNextFloat();
                } else {
                    parameterReader.skipNextInt();
                }
            }
        }
    } else {
        mv.visitLdcInsn(formatString.toString());
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), logFunction,
                "(" + Type.getDescriptor(Object.class) + ")V");
    }

    mv.visitLabel(loggingDisabled);
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

private void logSyscallEnd(HLEModuleFunction func, boolean isErrorCode) {
    String loggingLevel = getLoggingLevel(func);
    if (loggingLevel == null) {
        return;//from w w  w .j a  v a 2 s .c  om
    }
    String logCheckFunction = getLogCheckFunction(loggingLevel);

    // if (Modules.getLogger(func.getModuleName()).isDebugEnabled()) {
    //     Modules.getLogger(func.getModuleName()).debug(String.format("<function name> returning 0x%X", new Object[1] { new Integer(returnValue) }));
    // }
    loadModuleLoggger(func);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), logCheckFunction, "()Z");
    Label notDebug = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, notDebug);

    boolean isReturningVoid = func.getHLEModuleMethod().getReturnType() == void.class;

    mv.visitInsn(Opcodes.DUP);
    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Integer.class));
    mv.visitInsn(Opcodes.DUP_X1);
    mv.visitInsn(Opcodes.SWAP);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Integer.class), "<init>", "(I)V");
    loadImm(1);
    mv.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class));
    mv.visitInsn(Opcodes.DUP_X1);
    mv.visitInsn(Opcodes.SWAP);
    loadImm(0);
    mv.visitInsn(Opcodes.SWAP);
    mv.visitInsn(Opcodes.AASTORE);
    String prefix = func.isUnimplemented() && !codeBlock.isHLEFunction() ? "Unimplemented " : "";
    mv.visitLdcInsn(String.format("%s%s returning %s%s", prefix, func.getFunctionName(),
            isErrorCode ? "errorCode " : "", isReturningVoid ? "void" : "0x%X"));
    mv.visitInsn(Opcodes.SWAP);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "format",
            "(" + Type.getDescriptor(String.class) + "[" + Type.getDescriptor(Object.class) + ")"
                    + Type.getDescriptor(String.class));
    loadModuleLoggger(func);
    mv.visitInsn(Opcodes.SWAP);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), loggingLevel,
            "(" + Type.getDescriptor(Object.class) + ")V");

    if (!isErrorCode) {
        ParameterInfo[] parameters = new ClassAnalyzer().getParameters(func.getFunctionName(),
                func.getHLEModuleMethod().getDeclaringClass());
        if (parameters != null) {
            CompilerParameterReader parameterReader;
            if (parametersSavedToLocals) {
                parameterReader = new CompilerLocalVarParameterReader(this, LOCAL_FIRST_SAVED_PARAMETER);
            } else {
                parameterReader = new CompilerParameterReader(this);
            }

            Annotation[][] paramsAnotations = func.getHLEModuleMethod().getParameterAnnotations();
            for (int paramIndex = 0; paramIndex < parameters.length; paramIndex++) {
                ParameterInfo parameter = parameters[paramIndex];
                Class<?> parameterType = parameter.type;

                LengthInfo lengthInfo = BufferInfo.defaultLengthInfo;
                int length = BufferInfo.defaultLength;
                Usage usage = BufferInfo.defaultUsage;
                boolean debugMemory = false;
                for (Annotation parameterAnnotation : paramsAnotations[paramIndex]) {
                    if (parameterAnnotation instanceof BufferInfo) {
                        BufferInfo bufferInfo = (BufferInfo) parameterAnnotation;
                        lengthInfo = bufferInfo.lengthInfo();
                        length = bufferInfo.length();
                        usage = bufferInfo.usage();
                    } else if (parameterAnnotation instanceof DebugMemory) {
                        debugMemory = true;
                    }
                }

                boolean parameterRead = false;
                if ((usage == Usage.out || usage == Usage.inout)
                        && (lengthInfo != LengthInfo.unknown || parameterType == TPointer16.class
                                || parameterType == TPointer32.class || parameterType == TPointer64.class)) {
                    loadModuleLoggger(func);
                    loadImm(1);
                    mv.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class));
                    mv.visitInsn(Opcodes.DUP);
                    loadImm(0);

                    Label done = new Label();
                    Label addressNull = new Label();
                    parameterReader.loadNextInt();
                    parameterRead = true;
                    mv.visitInsn(Opcodes.DUP);
                    mv.visitJumpInsn(Opcodes.IFEQ, addressNull);

                    String format = String.format("%s[%s]:%%s", parameter.name, usage);
                    boolean useMemoryDump = true;

                    switch (lengthInfo) {
                    case fixedLength:
                        loadImm(length);
                        break;
                    case nextNextParameter:
                        parameterReader.skipNextInt();
                        paramIndex++;
                        parameterReader.loadNextInt();
                        paramIndex++;
                        break;
                    case nextParameter:
                        parameterReader.loadNextInt();
                        paramIndex++;
                        break;
                    case previousParameter:
                        // Go back to the address parameter
                        parameterReader.rewindPreviousInt();
                        // Go back to the previous parameter
                        parameterReader.rewindPreviousInt();
                        // Load the length from the previous parameter
                        parameterReader.loadNextInt();
                        // Skip again the address parameter
                        // to come back to the above situation
                        parameterReader.skipNextInt();
                        break;
                    case variableLength:
                        mv.visitInsn(Opcodes.DUP);
                        loadMemory();
                        mv.visitInsn(Opcodes.SWAP);
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read32", "(I)I");
                        break;
                    case returnValue:
                        loadRegister(_v0);
                        break;
                    case unknown:
                        useMemoryDump = false;
                        format = String.format("%s[%s]: 0x%%X", parameter.name, usage);
                        loadMemory();
                        mv.visitInsn(Opcodes.SWAP);
                        if (parameterType == TPointer64.class) {
                            if (debugMemory) {
                                mv.visitInsn(Opcodes.DUP);
                                loadImm(8);
                                mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName,
                                        "debugMemory", "(II)V");
                            }
                            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read64", "(I)J");
                            mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Long.class));
                            mv.visitInsn(Opcodes.DUP);
                            mv.visitInsn(Opcodes.DUP2_X2);
                            mv.visitInsn(Opcodes.POP2);
                            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Long.class),
                                    "<init>", "(J)V");
                        } else if (parameterType == TPointer16.class) {
                            if (debugMemory) {
                                mv.visitInsn(Opcodes.DUP);
                                loadImm(2);
                                mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName,
                                        "debugMemory", "(II)V");
                            }
                            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read16", "(I)I");
                            mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Integer.class));
                            mv.visitInsn(Opcodes.DUP_X1);
                            mv.visitInsn(Opcodes.SWAP);
                            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Integer.class),
                                    "<init>", "(I)V");
                        } else {
                            if (debugMemory) {
                                mv.visitInsn(Opcodes.DUP);
                                loadImm(4);
                                mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName,
                                        "debugMemory", "(II)V");
                            }
                            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read32", "(I)I");
                            mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Integer.class));
                            mv.visitInsn(Opcodes.DUP_X1);
                            mv.visitInsn(Opcodes.SWAP);
                            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Integer.class),
                                    "<init>", "(I)V");
                        }
                        break;
                    default:
                        log.error(String.format("Unimplemented lengthInfo=%s", lengthInfo));
                        break;
                    }

                    if (useMemoryDump) {
                        if (debugMemory) {
                            mv.visitInsn(Opcodes.DUP2);
                            mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "debugMemory",
                                    "(II)V");
                        }
                        mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Utilities.class),
                                "getMemoryDump", "(II)" + Type.getDescriptor(String.class));
                    }
                    mv.visitInsn(Opcodes.AASTORE);

                    mv.visitLdcInsn(format);
                    mv.visitInsn(Opcodes.SWAP);
                    mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "format",
                            "(" + Type.getDescriptor(String.class) + "[" + Type.getDescriptor(Object.class)
                                    + ")" + Type.getDescriptor(String.class));
                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), loggingLevel,
                            "(" + Type.getDescriptor(Object.class) + ")V");
                    mv.visitJumpInsn(Opcodes.GOTO, done);

                    mv.visitLabel(addressNull);
                    mv.visitInsn(Opcodes.POP);
                    mv.visitInsn(Opcodes.POP2);
                    mv.visitInsn(Opcodes.POP2);
                    mv.visitLabel(done);
                }

                if (!parameterRead) {
                    if (parameterType == long.class) {
                        parameterReader.skipNextLong();
                    } else if (parameterType == float.class) {
                        parameterReader.skipNextFloat();
                    } else {
                        parameterReader.skipNextInt();
                    }
                }
            }
        }
    }

    mv.visitLabel(notDebug);
}

From source file:jpcsp.Allegrex.compiler.CompilerContext.java

License:Open Source License

/**
 * Generate the required Java code to call a syscall function.
 * The code generated must match the Java behavior implemented in
 * jpcsp.HLE.modules.HLEModuleFunctionReflection
 *
 * The following code is generated://  w  ww.jav  a2  s. com
 *     if (func.getFirmwareVersion() <= RuntimeContext.firmwareVersion) {
 *         if (!fastSyscall) {
 *             RuntimeContext.preSyscall();
 *         }
 *         if (func.checkInsideInterrupt()) {
 *             if (IntrManager.getInstance.isInsideInterrupt()) {
 *                 cpu.gpr[_v0] = SceKernelErrors.ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT;
 *                 goto afterSyscall;
 *             }
 *         }
 *         if (func.checkDispatchThreadEnabled()) {
 *             if (!Modules.ThreadManForUserModule.isDispatchThreadEnabled()) {
 *                 cpu.gpr[_v0] = SceKernelErrors.ERROR_KERNEL_WAIT_CAN_NOT_WAIT;
 *                 goto afterSyscall;
 *             }
 *         }
 *         if (func.isUnimplemented()) {
 *             Modules.getLogger(func.getModuleName()).warn("Unimplemented <function name> parameterName1=parameterValue1, parameterName2=parameterValue2, ...");
 *         }
 *         foreach parameter {
 *             loadParameter(parameter);
 *         }
 *         try {
 *             returnValue = <module name>.<function name>(...parameters...);
 *             storeReturnValue();
 *             if (parameterReader.hasErrorPointer()) {
 *                 errorPointer.setValue(0);
 *             }
 *         } catch (SceKernelErrorException e) {
 *             errorCode = e.errorCode;
 *             if (Modules.getLogger(func.getModuleName()).isDebugEnabled()) {
 *                 Modules.getLogger(func.getModuleName()).debug(String.format("<function name> return errorCode 0x%08X", errorCode));
 *             }
 *             if (parameterReader.hasErrorPointer()) {
 *                 errorPointer.setValue(errorCode);
 *                 cpu.gpr[_v0] = 0;
 *             } else {
 *                 cpu.gpr[_v0] = errorCode;
 *             }
 *             reload cpu.gpr[_ra]; // an exception is always clearing the whole stack
 *         }
 *         afterSyscall:
 *         if (fastSyscall) {
 *             RuntimeContext.postSyscallFast();
 *         } else {
 *             RuntimeContext.postSyscall();
 *         }
 *     } else {
 *         Modules.getLogger(func.getModuleName()).warn("<function name> is not supported in firmware version <firmwareVersion>, it requires at least firmware version <function firmwareVersion>");
 *         cpu.gpr[_v0] = -1;
 *     }
 *
 * @param func         the syscall function
 * @param fastSyscall  true if this is a fast syscall (i.e. without context switching)
 *                     false if not (i.e. a syscall where context switching could happen)
 */
private void visitSyscall(HLEModuleFunction func, boolean fastSyscall) {
    // The compilation of a syscall requires more stack size than usual
    maxStackSize = SYSCALL_MAX_STACK_SIZE;

    boolean needFirmwareVersionCheck = true;
    if (func.getFirmwareVersion() >= 999) {
        // Dummy version number meaning valid for all versions
        needFirmwareVersionCheck = false;
    } else if (isCodeInstructionInKernelMemory()) {
        // When compiling code in the kernel memory space, do not perform any version check.
        // This is used by overwritten HLE functions.
        needFirmwareVersionCheck = false;
    } else {
        // When compiling code loaded from flash0, do not perform any version check.
        // This is used by overwritten HLE functions.
        SceModule module = Managers.modules.getModuleByAddress(codeInstruction.getAddress());
        if (module != null && module.pspfilename != null && module.pspfilename.startsWith("flash0:")) {
            if (log.isDebugEnabled()) {
                log.debug(String.format("syscall from a flash0 module(%s, '%s'), no firmware version check",
                        module, module.pspfilename));
            }
            needFirmwareVersionCheck = false;
        }
    }

    Label unsupportedVersionLabel = null;
    if (needFirmwareVersionCheck) {
        unsupportedVersionLabel = new Label();
        loadImm(func.getFirmwareVersion());
        mv.visitFieldInsn(Opcodes.GETSTATIC, runtimeContextInternalName, "firmwareVersion", "I");
        mv.visitJumpInsn(Opcodes.IF_ICMPGT, unsupportedVersionLabel);
    }

    // Save the syscall parameter to locals for debugging
    if (!fastSyscall) {
        saveParametersToLocals();
    }

    if (!fastSyscall) {
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "preSyscall", "()V");
    }

    Label afterSyscallLabel = new Label();

    if (func.checkInsideInterrupt()) {
        // if (IntrManager.getInstance().isInsideInterrupt()) {
        //     if (Modules.getLogger(func.getModuleName()).isDebugEnabled()) {
        //         Modules.getLogger(func.getModuleName()).debug("<function name> return errorCode 0x80020064 (ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT)");
        //     }
        //     cpu.gpr[_v0] = SceKernelErrors.ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT;
        //     goto afterSyscall
        // }
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(IntrManager.class), "getInstance",
                "()" + Type.getDescriptor(IntrManager.class));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(IntrManager.class), "isInsideInterrupt",
                "()Z");
        Label notInsideInterrupt = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, notInsideInterrupt);

        loadModuleLoggger(func);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), "isDebugEnabled", "()Z");
        Label notDebug = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, notDebug);
        loadModuleLoggger(func);
        mv.visitLdcInsn(
                String.format("%s returning errorCode 0x%08X (ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT)",
                        func.getFunctionName(), SceKernelErrors.ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), "debug",
                "(" + Type.getDescriptor(Object.class) + ")V");
        mv.visitLabel(notDebug);

        storeRegister(_v0, SceKernelErrors.ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT);
        mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
        mv.visitLabel(notInsideInterrupt);
    }

    if (func.checkDispatchThreadEnabled()) {
        // if (!Modules.ThreadManForUserModule.isDispatchThreadEnabled() || !Interrupts.isInterruptsEnabled()) {
        //     if (Modules.getLogger(func.getModuleName()).isDebugEnabled()) {
        //         Modules.getLogger(func.getModuleName()).debug("<function name> return errorCode 0x800201A7 (ERROR_KERNEL_WAIT_CAN_NOT_WAIT)");
        //     }
        //     cpu.gpr[_v0] = SceKernelErrors.ERROR_KERNEL_WAIT_CAN_NOT_WAIT;
        //     goto afterSyscall
        // }
        loadModule("ThreadManForUser");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(ThreadManForUser.class),
                "isDispatchThreadEnabled", "()Z");
        Label returnError = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, returnError);
        loadProcessor();
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Processor.class), "isInterruptsEnabled",
                "()Z");
        Label noError = new Label();
        mv.visitJumpInsn(Opcodes.IFNE, noError);

        mv.visitLabel(returnError);
        loadModuleLoggger(func);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), "isDebugEnabled", "()Z");
        Label notDebug = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, notDebug);
        loadModuleLoggger(func);
        mv.visitLdcInsn(String.format("%s returning errorCode 0x%08X (ERROR_KERNEL_WAIT_CAN_NOT_WAIT)",
                func.getFunctionName(), SceKernelErrors.ERROR_KERNEL_WAIT_CAN_NOT_WAIT));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), "debug",
                "(" + Type.getDescriptor(Object.class) + ")V");
        mv.visitLabel(notDebug);

        storeRegister(_v0, SceKernelErrors.ERROR_KERNEL_WAIT_CAN_NOT_WAIT);
        mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
        mv.visitLabel(noError);
    }

    logSyscallStart(func);

    if (func.hasStackUsage()) {
        loadMemory();
        loadRegister(_sp);
        loadImm(func.getStackUsage());
        mv.visitInsn(Opcodes.ISUB);
        loadImm(0);
        loadImm(func.getStackUsage());
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "memset", "(IBI)V");
    }

    // Collecting the parameters and calling the module function...
    CompilerParameterReader parameterReader = new CompilerParameterReader(this);

    loadModule(func.getModuleName());
    parameterReader.incrementCurrentStackSize();

    Label tryStart = new Label();
    Label tryEnd = new Label();
    Label catchSceKernelErrorException = new Label();
    mv.visitTryCatchBlock(tryStart, tryEnd, catchSceKernelErrorException,
            Type.getInternalName(SceKernelErrorException.class));

    Class<?>[] parameterTypes = func.getHLEModuleMethod().getParameterTypes();
    Class<?> returnType = func.getHLEModuleMethod().getReturnType();
    StringBuilder methodDescriptor = new StringBuilder();
    methodDescriptor.append("(");

    Annotation[][] paramsAnotations = func.getHLEModuleMethod().getParameterAnnotations();
    int paramIndex = 0;
    for (Class<?> parameterType : parameterTypes) {
        methodDescriptor.append(Type.getDescriptor(parameterType));
        loadParameter(parameterReader, func, parameterType, paramsAnotations[paramIndex], afterSyscallLabel,
                catchSceKernelErrorException);
        paramIndex++;
    }
    methodDescriptor.append(")");
    methodDescriptor.append(Type.getDescriptor(returnType));

    mv.visitLabel(tryStart);

    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
            Type.getInternalName(func.getHLEModuleMethod().getDeclaringClass()), func.getFunctionName(),
            methodDescriptor.toString());

    storeReturnValue(func, returnType);

    if (parameterReader.hasErrorPointer()) {
        // errorPointer.setValue(0);
        mv.visitVarInsn(Opcodes.ALOAD, LOCAL_ERROR_POINTER);
        loadImm(0);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(TErrorPointer32.class), "setValue",
                "(I)V");
    }

    loadRegister(_v0);
    logSyscallEnd(func, false);
    mv.visitInsn(Opcodes.POP);

    mv.visitLabel(tryEnd);
    mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);

    // catch (SceKernelErrorException e) {
    //     errorCode = e.errorCode;
    //     if (Modules.log.isDebugEnabled()) {
    //         Modules.log.debug(String.format("<function name> return errorCode 0x%08X", errorCode));
    //     }
    //     if (hasErrorPointer()) {
    //         errorPointer.setValue(errorCode);
    //         cpu.gpr[_v0] = 0;
    //     } else {
    //         cpu.gpr[_v0] = errorCode;
    //     }
    // }
    mv.visitLabel(catchSceKernelErrorException);
    mv.visitFieldInsn(Opcodes.GETFIELD, Type.getInternalName(SceKernelErrorException.class), "errorCode", "I");
    logSyscallEnd(func, true);
    if (parameterReader.hasErrorPointer()) {
        // errorPointer.setValue(errorCode);
        // cpu.gpr[_v0] = 0;
        mv.visitVarInsn(Opcodes.ALOAD, LOCAL_ERROR_POINTER);
        mv.visitInsn(Opcodes.SWAP);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(TErrorPointer32.class), "setValue",
                "(I)V");
        storeRegister(_v0, 0);
    } else {
        // cpu.gpr[_v0] = errorCode;
        storeRegister(_v0);
    }

    // Reload the $ra register, the stack is lost after an exception
    CodeInstruction previousInstruction = codeBlock.getCodeInstruction(codeInstruction.getAddress() - 4);
    if (previousInstruction != null && previousInstruction.getInsn() == Instructions.JR) {
        int jumpRegister = (previousInstruction.getOpcode() >> 21) & 0x1F;
        loadRegister(jumpRegister);
    }

    mv.visitLabel(afterSyscallLabel);

    if (fastSyscall) {
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "postSyscallFast", "()V");
    } else {
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "postSyscall", "()V");
    }

    if (needFirmwareVersionCheck) {
        Label afterVersionCheckLabel = new Label();
        mv.visitJumpInsn(Opcodes.GOTO, afterVersionCheckLabel);

        mv.visitLabel(unsupportedVersionLabel);
        loadModuleLoggger(func);
        mv.visitLdcInsn(String.format(
                "%s is not supported in firmware version %d, it requires at least firmware version %d",
                func.getFunctionName(), RuntimeContext.firmwareVersion, func.getFirmwareVersion()));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Logger.class), "warn",
                "(" + Type.getDescriptor(Object.class) + ")V");
        storeRegister(_v0, -1);

        mv.visitLabel(afterVersionCheckLabel);
    }
}