Example usage for org.objectweb.asm Opcodes INVOKEVIRTUAL

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

Introduction

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

Prototype

int INVOKEVIRTUAL

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

Click Source Link

Usage

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

License:Open Source License

/**
 * Generate the required Java code to load one parameter for
 * the syscall function from the CPU registers.
 *
 * The following code is generated based on the parameter type:
 * Processor: parameterValue = RuntimeContext.processor
 * int:       parameterValue = cpu.gpr[paramIndex++]
 * float:     parameterValue = cpu.fpr[paramFloatIndex++]
 * long:      parameterValue = (cpu.gpr[paramIndex++] & 0xFFFFFFFFL) + ((long) cpu.gpr[paramIndex++]) << 32)
 * boolean:   parameterValue = cpu.gpr[paramIndex++]
 * TPointer,/*  ww  w.java  2  s .c o  m*/
 * TPointer8,
 * TPointer16,
 * TPointer32,
 * TPointer64,
 * TErrorPointer32:
 *            if (checkMemoryAccess()) {
 *                if (canBeNullParam && address == 0) {
 *                    goto addressGood;
 *                }
 *                if (RuntimeContext.checkMemoryPointer(address)) {
 *                    goto addressGood;
 *                }
 *                cpu.gpr[_v0] = SceKernelErrors.ERROR_INVALID_POINTER;
 *                pop all the parameters already prepared on the stack;
 *                goto afterSyscall;
 *                addressGood:
 *            }
 *            <parameterType> pointer = new <parameterType>(address);
 *            if (parameterType == TErrorPointer32.class) {
 *                parameterReader.setHasErrorPointer(true);
 *                localVar[LOCAL_ERROR_POINTER] = pointer;
 *            }
 *            parameterValue = pointer
 * HLEUidClass defined in annotation:
 *            <parameterType> uidObject = HLEUidObjectMapping.getObject("<parameterType>", uid);
 *            if (uidObject == null) {
 *                cpu.gpr[_v0] = errorValueOnNotFound;
 *                pop all the parameters already prepared on the stack;
 *                goto afterSyscall;
 *            }
 *            parameterValue = uidObject
 *
 * And then common for all the types:
 *            try {
 *                parameterValue = <module>.<methodToCheck>(parameterValue);
 *            } catch (SceKernelErrorException e) {
 *                goto catchSceKernelErrorException;
 *            }
 *            push parameterValue on stack
 *
 * @param parameterReader               the current parameter state
 * @param func                          the syscall function
 * @param parameterType                 the type of the parameter
 * @param afterSyscallLabel             the Label pointing after the call to the syscall function
 * @param catchSceKernelErrorException  the Label pointing to the SceKernelErrorException catch handler
 */
private void loadParameter(CompilerParameterReader parameterReader, HLEModuleFunction func,
        Class<?> parameterType, Annotation[] parameterAnnotations, Label afterSyscallLabel,
        Label catchSceKernelErrorException) {
    if (parameterType == Processor.class) {
        loadProcessor();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == CpuState.class) {
        loadCpu();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == int.class) {
        parameterReader.loadNextInt();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == float.class) {
        parameterReader.loadNextFloat();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == long.class) {
        parameterReader.loadNextLong();
        parameterReader.incrementCurrentStackSize(2);
    } else if (parameterType == boolean.class) {
        parameterReader.loadNextInt();
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == String.class) {
        parameterReader.loadNextInt();

        int maxLength = 16 * 1024;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof StringInfo) {
                StringInfo stringInfo = ((StringInfo) parameterAnnotation);
                maxLength = stringInfo.maxLength();
                break;
            }
        }
        loadImm(maxLength);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "readStringNZ",
                "(II)" + Type.getDescriptor(String.class));
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == PspString.class) {
        parameterReader.loadNextInt();

        int maxLength = 16 * 1024;
        boolean canBeNull = false;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof StringInfo) {
                StringInfo stringInfo = ((StringInfo) parameterAnnotation);
                maxLength = stringInfo.maxLength();
            }
            if (parameterAnnotation instanceof CanBeNull) {
                canBeNull = true;
            }
        }
        loadImm(maxLength);
        loadImm(canBeNull);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "readPspStringNZ",
                "(IIZ)" + Type.getDescriptor(PspString.class));
        parameterReader.incrementCurrentStackSize();
    } else if (parameterType == TPointer.class || parameterType == TPointer8.class
            || parameterType == TPointer16.class || parameterType == TPointer32.class
            || parameterType == TPointer64.class || parameterType == TErrorPointer32.class) {
        // if (checkMemoryAccess()) {
        //     if (canBeNullParam && address == 0) {
        //         goto addressGood;
        //     }
        //     if (RuntimeContext.checkMemoryPointer(address)) {
        //         goto addressGood;
        //     }
        //     cpu.gpr[_v0] = SceKernelErrors.ERROR_INVALID_POINTER;
        //     pop all the parameters already prepared on the stack;
        //     goto afterSyscall;
        //     addressGood:
        // }
        // <parameterType> pointer = new <parameterType>(address);
        // if (parameterType == TErrorPointer32.class) {
        //     parameterReader.setHasErrorPointer(true);
        //     localVar[LOCAL_ERROR_POINTER] = pointer;
        // }
        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(parameterType));
        mv.visitInsn(Opcodes.DUP);
        loadMemory();
        parameterReader.loadNextInt();

        boolean canBeNull = false;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof CanBeNull) {
                canBeNull = true;
                break;
            }
        }

        if (checkMemoryAccess() && afterSyscallLabel != null) {
            Label addressGood = new Label();
            if (canBeNull) {
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFEQ, addressGood);
            }
            mv.visitInsn(Opcodes.DUP);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "checkMemoryPointer", "(I)Z");
            mv.visitJumpInsn(Opcodes.IFNE, addressGood);
            storeRegister(_v0, SceKernelErrors.ERROR_INVALID_POINTER);
            parameterReader.popAllStack(4);
            mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
            mv.visitLabel(addressGood);
        }
        if (parameterType == TPointer8.class || parameterType == TPointer16.class
                || parameterType == TPointer32.class || parameterType == TPointer64.class) {
            loadImm(canBeNull);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parameterType), "<init>",
                    "(" + memoryDescriptor + "IZ)V");
        } else {
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parameterType), "<init>",
                    "(" + memoryDescriptor + "I)V");
        }
        if (parameterType == TErrorPointer32.class) {
            parameterReader.setHasErrorPointer(true);
            mv.visitInsn(Opcodes.DUP);
            mv.visitVarInsn(Opcodes.ASTORE, LOCAL_ERROR_POINTER);
        }
        parameterReader.incrementCurrentStackSize();
    } else if (pspAbstractMemoryMappedStructure.class.isAssignableFrom(parameterType)) {
        parameterReader.loadNextInt();

        boolean canBeNull = false;
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof CanBeNull) {
                canBeNull = true;
                break;
            }
        }

        if (checkMemoryAccess() && afterSyscallLabel != null) {
            Label addressGood = new Label();
            if (canBeNull) {
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFEQ, addressGood);
            }
            mv.visitInsn(Opcodes.DUP);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "checkMemoryPointer", "(I)Z");
            mv.visitJumpInsn(Opcodes.IFNE, addressGood);
            storeRegister(_v0, SceKernelErrors.ERROR_INVALID_POINTER);
            parameterReader.popAllStack(1);
            mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
            mv.visitLabel(addressGood);
        }

        mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(parameterType));
        mv.visitInsn(Opcodes.DUP);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parameterType), "<init>", "()V");
        mv.visitInsn(Opcodes.DUP_X1);
        mv.visitInsn(Opcodes.SWAP);
        loadMemory();
        mv.visitInsn(Opcodes.SWAP);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(parameterType), "read",
                "(" + memoryDescriptor + "I)V");
        parameterReader.incrementCurrentStackSize();
    } else {
        HLEUidClass hleUidClass = parameterType.getAnnotation(HLEUidClass.class);
        if (hleUidClass != null) {
            int errorValueOnNotFound = hleUidClass.errorValueOnNotFound();

            // <parameterType> uidObject = HLEUidObjectMapping.getObject("<parameterType>", uid);
            // if (uidObject == null) {
            //     cpu.gpr[_v0] = errorValueOnNotFound;
            //     pop all the parameters already prepared on the stack;
            //     goto afterSyscall;
            // }
            mv.visitLdcInsn(parameterType.getName());
            // Load the UID
            parameterReader.loadNextInt();

            // Load the UID Object
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(HLEUidObjectMapping.class),
                    "getObject",
                    "(" + Type.getDescriptor(String.class) + "I)" + Type.getDescriptor(Object.class));
            if (afterSyscallLabel != null) {
                Label foundUid = new Label();
                mv.visitInsn(Opcodes.DUP);
                mv.visitJumpInsn(Opcodes.IFNONNULL, foundUid);
                storeRegister(_v0, errorValueOnNotFound);
                parameterReader.popAllStack(1);
                mv.visitJumpInsn(Opcodes.GOTO, afterSyscallLabel);
                mv.visitLabel(foundUid);
            }
            mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(parameterType));
            parameterReader.incrementCurrentStackSize();
        } else {
            log.error(String.format("Unsupported sycall parameter type '%s'", parameterType.getName()));
            Emulator.PauseEmuWithStatus(Emulator.EMU_STATUS_UNIMPLEMENTED);
        }
    }

    Method methodToCheck = null;
    if (afterSyscallLabel != null) {
        for (Annotation parameterAnnotation : parameterAnnotations) {
            if (parameterAnnotation instanceof CheckArgument) {
                CheckArgument checkArgument = (CheckArgument) parameterAnnotation;
                try {
                    methodToCheck = func.getHLEModule().getClass().getMethod(checkArgument.value(),
                            parameterType);
                } catch (Exception e) {
                    log.error(String.format("CheckArgument method '%s' not found in %s", checkArgument.value(),
                            func.getModuleName()), e);
                }
                break;
            }
        }
    }

    if (methodToCheck != null) {
        // try {
        //     parameterValue = <module>.<methodToCheck>(parameterValue);
        // } catch (SceKernelErrorException e) {
        //     goto catchSceKernelErrorException;
        // }
        loadModule(func.getModuleName());
        mv.visitInsn(Opcodes.SWAP);

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

        mv.visitLabel(tryStart);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(methodToCheck.getDeclaringClass()),
                methodToCheck.getName(),
                "(" + Type.getDescriptor(parameterType) + ")" + Type.getDescriptor(parameterType));
        mv.visitLabel(tryEnd);
    }

    parameterReader.incrementCurrentParameterIndex();
}

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

License:Open Source License

/**
 * Generate the required Java code to store the return value of
 * the syscall function into the CPU registers.
 *
 * The following code is generated depending on the return type:
 * void:         -/*from  ww w  .jav a2 s. c om*/
 * int:          cpu.gpr[_v0] = intValue
 * boolean:      cpu.gpr[_v0] = booleanValue
 * long:         cpu.gpr[_v0] = (int) (longValue & 0xFFFFFFFFL)
 *               cpu.gpr[_v1] = (int) (longValue >>> 32)
 * float:        cpu.fpr[_f0] = floatValue
 * HLEUidClass:  if (moduleMethodUidGenerator == "") {
 *                   cpu.gpr[_v0] = HLEUidObjectMapping.createUidForObject("<return type>", returnValue);
 *               } else {
 *                   int uid = <module>.<moduleMethodUidGenerator>();
 *                   cpu.gpr[_v0] = HLEUidObjectMapping.addObjectMap("<return type>", uid, returnValue);
 *               }
 *
 * @param func        the syscall function
 * @param returnType  the type of the return value
 */
private void storeReturnValue(HLEModuleFunction func, Class<?> returnType) {
    if (returnType == void.class) {
        // Nothing to do
    } else if (returnType == int.class) {
        // cpu.gpr[_v0] = intValue
        storeRegister(_v0);
    } else if (returnType == boolean.class) {
        // cpu.gpr[_v0] = booleanValue
        storeRegister(_v0);
    } else if (returnType == long.class) {
        // cpu.gpr[_v0] = (int) (longValue & 0xFFFFFFFFL)
        // cpu.gpr[_v1] = (int) (longValue >>> 32)
        mv.visitInsn(Opcodes.DUP2);
        mv.visitLdcInsn(0xFFFFFFFFL);
        mv.visitInsn(Opcodes.LAND);
        mv.visitInsn(Opcodes.L2I);
        storeRegister(_v0);
        loadImm(32);
        mv.visitInsn(Opcodes.LSHR);
        mv.visitInsn(Opcodes.L2I);
        storeRegister(_v1);
    } else if (returnType == float.class) {
        // cpu.fpr[_f0] = floatValue
        storeFRegister(_f0);
    } else {
        HLEUidClass hleUidClass = returnType.getAnnotation(HLEUidClass.class);
        if (hleUidClass != null) {
            // if (moduleMethodUidGenerator == "") {
            //     cpu.gpr[_v0] = HLEUidObjectMapping.createUidForObject("<return type>", returnValue);
            // } else {
            //     int uid = <module>.<moduleMethodUidGenerator>();
            //     cpu.gpr[_v0] = HLEUidObjectMapping.addObjectMap("<return type>", uid, returnValue);
            // }
            if (hleUidClass.moduleMethodUidGenerator().length() <= 0) {
                // No UID generator method, use the default one
                mv.visitLdcInsn(returnType.getName());
                mv.visitInsn(Opcodes.SWAP);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(HLEUidObjectMapping.class),
                        "createUidForObject",
                        "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Object.class) + ")I");
                storeRegister(_v0);
            } else {
                mv.visitLdcInsn(returnType.getName());
                mv.visitInsn(Opcodes.SWAP);
                loadModule(func.getModuleName());
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                        Type.getInternalName(func.getHLEModuleMethod().getDeclaringClass()),
                        hleUidClass.moduleMethodUidGenerator(), "()I");
                mv.visitInsn(Opcodes.SWAP);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(HLEUidObjectMapping.class),
                        "addObjectMap",
                        "(" + Type.getDescriptor(String.class) + "I" + Type.getDescriptor(Object.class) + ")I");
                storeRegister(_v0);
            }
        } else {
            log.error(String.format("Unsupported sycall return value type '%s'", returnType.getName()));
        }
    }
}

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);/*ww  w. j  a v 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;/* www. j a  va  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://from   w w  w  .j a v a 2 s. co  m
 *     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);
    }
}

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

License:Open Source License

@SuppressWarnings("unused")
public void startInstruction(CodeInstruction codeInstruction) {
    if (RuntimeContext.enableLineNumbers) {
        int lineNumber = codeInstruction.getAddress() - getCodeBlock().getLowestAddress();
        // Java line number is unsigned 16bits
        if (lineNumber >= 0 && lineNumber <= 0xFFFF) {
            mv.visitLineNumber(lineNumber, codeInstruction.getLabel());
        }//www  . j  ava 2 s . c o m
    }

    // The pc is used by the DebuggerMemory or the LLE/MMIO
    if (Memory.getInstance() instanceof DebuggerMemory || RuntimeContextLLE.isLLEActive()) {
        storePc();
    }

    if (RuntimeContextLLE.isLLEActive()) {
        startInstructionLLE(codeInstruction);
    }

    if (RuntimeContext.debugCodeInstruction) {
        loadImm(codeInstruction.getAddress());
        loadImm(codeInstruction.getOpcode());
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName,
                RuntimeContext.debugCodeInstructionName, "(II)V");
    }

    if (RuntimeContext.enableInstructionTypeCounting) {
        if (codeInstruction.getInsn() != null) {
            loadInstruction(codeInstruction.getInsn());
            loadImm(codeInstruction.getOpcode());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName,
                    RuntimeContext.instructionTypeCount, "(" + instructionDescriptor + "I)V");
        }
    }

    if (RuntimeContext.enableDebugger) {
        loadImm(codeInstruction.getAddress());
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, RuntimeContext.debuggerName,
                "(I)V");
    }

    if (RuntimeContext.checkCodeModification && !(codeInstruction instanceof NativeCodeInstruction)) {
        // Generate the following sequence:
        //
        //     if (memory.read32(pc) != opcode) {
        //         RuntimeContext.onCodeModification(pc, opcode);
        //     }
        //
        loadMemory();
        loadImm(codeInstruction.getAddress());
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read32", "(I)I");
        loadImm(codeInstruction.getOpcode());
        Label codeUnchanged = new Label();
        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, codeUnchanged);

        loadImm(codeInstruction.getAddress());
        loadImm(codeInstruction.getOpcode());
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, "onCodeModification", "(II)V");

        mv.visitLabel(codeUnchanged);
    }

    if (!isNonBranchingCodeSequence(codeInstruction)) {
        startNonBranchingCodeSequence();
    }

    // This instructions consumes the PFXT prefix but does not use it.
    if (codeInstruction.hasFlags(Instruction.FLAG_CONSUMES_VFPU_PFXT)) {
        disablePfxSrc(vfpuPfxtState);
    }
}

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

License:Open Source License

@Override
public void compileRTRSIMM(String method, boolean signedImm) {
    loadCpu();// w  w w. ja v  a  2  s  .c o m
    loadRtIndex();
    loadRsIndex();
    loadImm16(signedImm);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, cpuInternalName, method, "(III)V");
}

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

License:Open Source License

@Override
public void compileRDRT(String method) {
    loadCpu();/*from   w w  w .  j  ava 2 s. c  om*/
    loadRdIndex();
    loadRtIndex();
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, cpuInternalName, method, "(II)V");
}

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

License:Open Source License

@Override
public void compileFDFSFT(String method) {
    loadCpu();//www . ja v  a2 s .  c om
    loadFdIndex();
    loadFsIndex();
    loadFtIndex();
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, cpuInternalName, method, "(III)V");
}

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

License:Open Source License

@Override
public void memRead32(int registerIndex, int offset) {
    if (useMMIO()) {
        loadMMIO();//from w ww.  j a  v a  2s . c om
    } else if (!RuntimeContext.hasMemoryInt()) {
        loadMemory();
    } else {
        loadMemoryInt();
    }

    prepareMemIndex(registerIndex, offset, true, 32);

    if (useMMIO() || !RuntimeContext.hasMemoryInt()) {
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, memoryInternalName, "read32", "(I)I");
    } else {
        mv.visitInsn(Opcodes.IALOAD);
    }
}