Example usage for org.objectweb.asm Opcodes IFEQ

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

Introduction

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

Prototype

int IFEQ

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

Click Source Link

Usage

From source file:io.syncframework.optimizer.OControllerClassVisitor.java

License:Apache License

/**
 * Creates the code as://from  w ww.  ja va2s  .co  m
 * 
 * public void _asParameter(String name, Object value) {
 *    if(name.equals("name") {
 *       setName((String)value);
 *       return;
 *    }
 *   if(name.equals("date") {
 *      setDate((Date)value);
 *      return;
 *   }
 *   ...
 *    return;
 * } 
 */
private void createParametersSetterMethod() {
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "_asParameter",
            "(Ljava/lang/String;Ljava/lang/Object;)V", null, null);

    Label start = new Label();
    Label next = new Label();
    Label variable = new Label();
    boolean first = true;

    for (String name : reflector.getParameters().keySet()) {
        Label l0 = null;
        Label l1 = new Label();
        Label l2 = new Label();

        if (first) {
            l0 = new Label();
            first = false;
        } else {
            l0 = next;
            next = new Label();
        }

        mv.visitLabel(l0);
        if (!first)
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn(name);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
        mv.visitJumpInsn(Opcodes.IFEQ, next);

        Class<?> parameterType = reflector.getParameters().get(name);

        String setterMethodName = reflector.getSetters().get(name).getName();
        String setterMethodDesc = "(" + Type.getDescriptor(parameterType) + ")V";

        mv.visitLabel(l1);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 2);
        mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(parameterType));
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, reflector.getClazzInternalName(), setterMethodName,
                setterMethodDesc, false);

        mv.visitLabel(l2);
        mv.visitInsn(Opcodes.RETURN);
    }

    mv.visitLabel(next);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitInsn(Opcodes.RETURN);

    mv.visitLabel(variable);
    mv.visitLocalVariable("this", reflector.getClazzDescriptor(), null, start, next, 0);
    mv.visitLocalVariable("name", "Ljava/lang/String;", null, start, next, 1);
    mv.visitLocalVariable("value", "Ljava/lang/Object;", null, start, next, 2);
    mv.visitMaxs(2, 3);
    mv.visitEnd();
}

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;//w w  w.  j  ava 2 s .  co m
            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.CodeInstruction.java

License:Open Source License

private int getBranchingOpcode(CompilerContext context, MethodVisitor mv) {
    int branchingOpcode = Opcodes.NOP;

    if (insn == Instructions.BEQ) {
        branchingOpcode = getBranchingOpcodeBranch2(context, mv, Opcodes.IF_ICMPEQ, Opcodes.IF_ICMPNE);
    } else if (insn == Instructions.BEQL) {
        branchingOpcode = getBranchingOpcodeBranch2L(context, mv, Opcodes.IF_ICMPEQ, Opcodes.IF_ICMPNE);
    } else if (insn == Instructions.BNE) {
        branchingOpcode = getBranchingOpcodeBranch2(context, mv, Opcodes.IF_ICMPNE, Opcodes.IF_ICMPEQ);
    } else if (insn == Instructions.BNEL) {
        branchingOpcode = getBranchingOpcodeBranch2L(context, mv, Opcodes.IF_ICMPNE, Opcodes.IF_ICMPEQ);
    } else if (insn == Instructions.BGEZ) {
        branchingOpcode = getBranchingOpcodeBranch1(context, mv, Opcodes.IFGE, Opcodes.IFLT);
    } else if (insn == Instructions.BGEZL) {
        branchingOpcode = getBranchingOpcodeBranch1L(context, mv, Opcodes.IFGE, Opcodes.IFLT);
    } else if (insn == Instructions.BGTZ) {
        branchingOpcode = getBranchingOpcodeBranch1(context, mv, Opcodes.IFGT, Opcodes.IFLE);
    } else if (insn == Instructions.BGTZL) {
        branchingOpcode = getBranchingOpcodeBranch1L(context, mv, Opcodes.IFGT, Opcodes.IFLE);
    } else if (insn == Instructions.BLEZ) {
        branchingOpcode = getBranchingOpcodeBranch1(context, mv, Opcodes.IFLE, Opcodes.IFGT);
    } else if (insn == Instructions.BLEZL) {
        branchingOpcode = getBranchingOpcodeBranch1L(context, mv, Opcodes.IFLE, Opcodes.IFGT);
    } else if (insn == Instructions.BLTZ) {
        branchingOpcode = getBranchingOpcodeBranch1(context, mv, Opcodes.IFLT, Opcodes.IFGE);
    } else if (insn == Instructions.BLTZL) {
        branchingOpcode = getBranchingOpcodeBranch1L(context, mv, Opcodes.IFLT, Opcodes.IFGE);
    } else if (insn == Instructions.J) {
        branchingOpcode = getBranchingOpcodeBranch0(context, mv);
    } else if (insn == Instructions.JAL) {
        branchingOpcode = getBranchingOpcodeCall0(context, mv);
    } else if (insn == Instructions.BLTZAL) {
        branchingOpcode = getBranchingOpcodeCall1(context, mv, Opcodes.IFLT, Opcodes.IFGE);
    } else if (insn == Instructions.BLTZALL) {
        branchingOpcode = getBranchingOpcodeCall1L(context, mv, Opcodes.IFLT, Opcodes.IFGE);
    } else if (insn == Instructions.BGEZAL) {
        branchingOpcode = getBranchingOpcodeCall1(context, mv, Opcodes.IFGE, Opcodes.IFLT);
    } else if (insn == Instructions.BGEZALL) {
        branchingOpcode = getBranchingOpcodeCall1L(context, mv, Opcodes.IFGE, Opcodes.IFLT);
    } else if (insn == Instructions.BC1F) {
        branchingOpcode = getBranchingOpcodeBC1(context, mv, Opcodes.IFEQ, Opcodes.IFNE);
    } else if (insn == Instructions.BC1FL) {
        branchingOpcode = getBranchingOpcodeBC1L(context, mv, Opcodes.IFEQ, Opcodes.IFNE);
    } else if (insn == Instructions.BC1T) {
        branchingOpcode = getBranchingOpcodeBC1(context, mv, Opcodes.IFNE, Opcodes.IFEQ);
    } else if (insn == Instructions.BC1TL) {
        branchingOpcode = getBranchingOpcodeBC1L(context, mv, Opcodes.IFNE, Opcodes.IFEQ);
    } else if (insn == Instructions.BVF) {
        branchingOpcode = getBranchingOpcodeBV(context, mv, Opcodes.IFEQ, Opcodes.IFNE);
    } else if (insn == Instructions.BVT) {
        branchingOpcode = getBranchingOpcodeBV(context, mv, Opcodes.IFNE, Opcodes.IFEQ);
    } else if (insn == Instructions.BVFL) {
        branchingOpcode = getBranchingOpcodeBVL(context, mv, Opcodes.IFEQ, Opcodes.IFNE);
    } else if (insn == Instructions.BVTL) {
        branchingOpcode = getBranchingOpcodeBVL(context, mv, Opcodes.IFNE, Opcodes.IFEQ);
    } else {//from   w  w w .j  a  v  a 2 s . c o  m
        log.error("CodeInstruction.getBranchingOpcode: unknown instruction "
                + insn.disasm(getAddress(), getOpcode()));
    }

    return branchingOpcode;
}

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,/*from  w ww .  j a v a2 s .com*/
 * 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

private void logSyscall(HLEModuleFunction func, String logPrefix, String logCheckFunction, String logFunction) {
    // Modules.getLogger(func.getModuleName()).warn("Unimplemented...");
    loadModuleLoggger(func);/*from ww  w .  j a  va  2  s .c om*/
    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;//w  w  w. j  a  v a  2s .c o m
    }
    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 w  w  .  j  av 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

public void checkSync() {
    if (RuntimeContext.enableDaemonThreadSync) {
        Label doNotWantSync = new Label();
        mv.visitFieldInsn(Opcodes.GETSTATIC, runtimeContextInternalName, "wantSync", "Z");
        mv.visitJumpInsn(Opcodes.IFEQ, doNotWantSync);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextInternalName, RuntimeContext.syncName, "()V");
        mv.visitLabel(doNotWantSync);//w  ww.  j  a  v  a  2s  . com
    }
}

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

License:Open Source License

private void startInstructionLLE(CodeInstruction codeInstruction) {
    // Check for a pending interrupt only for instructions not being in a delay slot
    if (codeInstruction.isDelaySlot()) {
        return;/*from  ww w .j a  va 2s  .  c  o  m*/
    }

    // TO avoid checking too often for a pending interrupt, check
    // only for instructions being the target of the branch or for those marked
    // as potentially modifying the interrupt state.
    if (!codeInstruction.isBranchTarget() && !previousInstructionModifiesInterruptState(codeInstruction)) {
        return;
    }

    Label noPendingInterrupt = new Label();
    mv.visitFieldInsn(Opcodes.GETSTATIC, runtimeContextLLEInternalName, "pendingInterruptIPbits", "I");
    mv.visitJumpInsn(Opcodes.IFEQ, noPendingInterrupt);
    int returnAddress = codeInstruction.getAddress();
    loadImm(returnAddress);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeContextLLEInternalName, "checkPendingInterruptException",
            "(I)I");
    visitContinueToAddress(returnAddress, false);
    mv.visitLabel(noPendingInterrupt);
}

From source file:lapin.comp.asm.ASMByteCodeGenerator.java

License:Open Source License

private void generateCall(CallableInfo ci, Env env) {
    /*/*www.  ja  v a2  s  .c  o m*/
     * local variables
     * <Callable#call>
     * 0: this
     * 1: args (list of arguments)
     * 2: env
     *
     * <Callable0#call0>
     * 0: this
     * 1: env
     *
     * <Callable1#call1>
     * 0: this
     * 1: arg0
     * 2: env
     *
     * <Callable2#call2>
     * 0: this
     * 1: arg0
     * 2: arg1
     * 3: env
     *
     * ...
     *
     */
    MethodVisitor mv = _cw.visitMethod(
            ci.mi.implCallable() ? Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL : Opcodes.ACC_FINAL, ci.mi.name(),
            Type.getMethodDescriptor(ci.retType, ci.paramTypes), null, null);

    // instruction list
    int len = ci.mi.instLen();
    // label
    Label label = null;

    // generate code
    for (int i = 0; i < len; i++) {
        Object inst = ci.mi.getInst(i);
        if (Logger.tracelevelp(env))
            Logger.trace("[asm:gen]" + i + ":\t~S", Lists.list(inst), env);

        // inst is symbol
        // -> convert tag (Symbol) to label (ASMe Label object)
        if (Data.isSymbol(inst)) {
            Symbol tag = Data.symbol(inst);
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label is null: ~S.", Lists.list(tag));
            } else if (l != label) {
                mv.visitLabel(l);
                label = l;
                if (Logger.tracelevelp(env))
                    Logger.trace("[asm:gen]" + i + ":\ttag ~S -> label ~S", Lists.list(tag, l), env);
            } else {
                if (Logger.tracelevelp(env))
                    Logger.trace("[asm:gen]" + i + ":\ttag ~S -> label ~S" + " (dup)", Lists.list(tag, l), env);
            }
            continue;
        }

        // inst must be the form of (id <arg1> <arg2> ....)
        Object id = Lists.car(inst);
        if (id == Insts.CONST) {
            /* push const on the stack. */
            Object obj = Lists.cadr(inst);
            String val = Data.string(constTable.get(obj));
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, toInternalName(super.classInfo.classname()), val,
                    TYPE_OBJECT.getDescriptor());
        } else if (id == Insts.VAR) {
            /* push var on the stack */
            Object var = Lists.cadr(inst);
            String val = Data.string(varTable.get(var));
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, toInternalName(super.classInfo.classname()), val,
                    TYPE_SYMBOL.getDescriptor());
        } else if (id == Insts.LAMBDA_LIST) {
            /* push lambdaList on the stack */
            Object var = Lists.cadr(inst);
            /* push _ll_<i> on the stack */
            String val = Data.string(llTable.get(var));
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, toInternalName(super.classInfo.classname()), val,
                    TYPE_LAMBDA_LIST.getDescriptor());
        } else if (id == Insts.ENV_GET) {
            /* env.get */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "getInt",
                        Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "getDouble",
                        Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "getChar",
                        Type.getMethodDescriptor(Type.CHAR_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "get",
                        Type.getMethodDescriptor(TYPE_OBJECT, new Type[] { TYPE_SYMBOL }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_SET) {
            /* env.set */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.INT_TYPE }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.DOUBLE_TYPE }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.CHAR_TYPE }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "set",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, TYPE_OBJECT }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_BIND) {
            /* env.bind */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.INT_TYPE }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.DOUBLE_TYPE }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, Type.CHAR_TYPE }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "bind",
                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { TYPE_SYMBOL, TYPE_OBJECT }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_UNBIND) {
            /* env.unbind */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbindInt",
                        Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(double.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbindDouble",
                        Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (type.equals(char.class)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbindChar",
                        Type.getMethodDescriptor(Type.CHAR_TYPE, new Type[] { TYPE_SYMBOL }));
            } else if (Object.class.isAssignableFrom(type)) {
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "unbind",
                        Type.getMethodDescriptor(TYPE_OBJECT, new Type[] { TYPE_SYMBOL }));
            } else {
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
        } else if (id == Insts.ENV_CHILD) {
            /* env.child */
            Object oldEnvVar = Lists.cadr(inst);
            Object newEnvVar = Lists.caddr(inst);
            Object oldSlot = Lists.cadr(oldEnvVar);
            Object newSlot = Lists.cadr(newEnvVar);
            int oldLocal = Data.fixnum(ci.localTable.get(oldSlot)).intValue();
            int newLocal = Data.fixnum(ci.localTable.get(newSlot)).intValue();
            if (Logger.tracelevelp(env))
                Logger.trace("[asm:gen]" + i + ":\tenv-child: local ~S -> ~S",
                        Lists.list(Data.toFixnum(oldLocal), Data.toFixnum(newLocal)), env);
            mv.visitVarInsn(Opcodes.ALOAD, oldLocal);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_ENV.getInternalName(), "child",
                    Type.getMethodDescriptor(TYPE_ENV, TYPE_NO_ARGS));
            mv.visitVarInsn(Opcodes.ASTORE, newLocal);
        } else if (id == Insts.CALL) {
            /* funcall */
            int nargs = Data.fixnum(Lists.cadr(inst)).intValue();
            String className = "lapin.eval.Funcall";
            String methodName = nargs < 0 ? "funcall" : "funcall" + nargs;
            Class rType = Object.class;
            Class[] pTypes;
            if (nargs < 0) {
                pTypes = new Class[] { Function.class, Object.class, // list of args
                        Env.class };
            } else {
                pTypes = new Class[nargs + 2];
                pTypes[0] = Function.class;
                for (int j = 0; j < nargs; j++) {
                    pTypes[j + 1] = Object.class;
                }
                pTypes[nargs + 1] = Env.class;
            }

            Type retType = Type.getType(rType);
            Type[] paramTypes = new Type[pTypes.length];
            for (int j = 0; j < pTypes.length; j++)
                paramTypes[j] = Type.getType(pTypes[j]);

            mv.visitMethodInsn(Opcodes.INVOKESTATIC, toInternalName(className), methodName,
                    Type.getMethodDescriptor(retType, paramTypes));
        } else if (id == Insts.CALL_DIRECT) {
            /*
             * public class Foo
             *   extends CompiledExpr implements Callable2 {
             *  public Object call2(Object arg0, Object arg1, Env env) {
             *   ...
             *  }
             * }
             */
            MethodInfo mi = (MethodInfo) Lists.cadr(inst);
            String className = mi.classInfo().classname();
            int nargs = mi.nargs();
            boolean rest = mi.rest();
            String methodName = mi.name();
            Class rType = mi.retType();
            Class[] pTypes = mi.paramTypes();

            Type retType = Type.getType(rType);
            Type[] paramTypes = new Type[pTypes.length];
            for (int j = 0; j < pTypes.length; j++)
                paramTypes[j] = Type.getType(pTypes[j]);

            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, toInternalName(className), methodName,
                    Type.getMethodDescriptor(retType, paramTypes));
        } else if (id == Insts.COMPILED_EXPR) {
            /*
             * public class Foo extends CompiledExpr {
             *  static public Foo SELF;
             *  ...
             * }
             */
            String className = Data.string(Lists.cadr(inst));
            String fieldName = "SELF";
            String typeName = className;
            mv.visitFieldInsn(Opcodes.GETSTATIC, toInternalName(className), fieldName,
                    toTypeDescriptor(typeName));
        } else if (id == Insts.RETURN) {
            /* return */
            Class type = Data.javaClass(Lists.cadr(inst));
            if (type.equals(int.class) || type.equals(short.class) || type.equals(byte.class)
                    || type.equals(char.class)) {
                mv.visitInsn(Opcodes.IRETURN);
            } else if (type.equals(long.class)) {
                mv.visitInsn(Opcodes.LRETURN);
            } else if (type.equals(float.class)) {
                mv.visitInsn(Opcodes.FRETURN);
            } else if (type.equals(double.class)) {
                mv.visitInsn(Opcodes.DRETURN);
            } else if (type.equals(void.class)) {
                //mv.visitInsn(Opcodes.RETURN);
                throw new NotReachedException("unsupported returnType: ~S.", Lists.list(type));
            } else {
                mv.visitInsn(Opcodes.ARETURN);
            }
        } else if (id == Insts.IFEQ) {
            /* conditional jump */
            Symbol tag = Data.symbol(Lists.cadr(inst));
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tag));
            }
            mv.visitJumpInsn(Opcodes.IFEQ, l);
        } else if (id == Insts.IFNE) {
            /* conditional jump */
            Symbol tag = Data.symbol(Lists.cadr(inst));
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tag));
            }
            mv.visitJumpInsn(Opcodes.IFNE, l);
        } else if (id == Insts.GOTO) {
            /* jump */
            Symbol tag = Data.symbol(Lists.cadr(inst));
            Label l = (Label) ci.labelTable.get(tag);
            if (l == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tag));
            }
            mv.visitJumpInsn(Opcodes.GOTO, l);
        } else if (id == Insts.LOAD) {
            /* local -> stack */
            Object localVar = Lists.cadr(inst);
            Object slot = Lists.cadr(localVar);
            Class type = Data.javaClass(Lists.caddr(localVar));
            int local = Data.fixnum(ci.localTable.get(slot)).intValue();
            int op = Type.getType(type).getOpcode(Opcodes.ILOAD);
            if (Logger.tracelevelp(env))
                Logger.trace("[asm:gen]" + i + ":\tload: local=~S type=~S",
                        Lists.list(Data.toFixnum(local), type), env);
            mv.visitVarInsn(op, local);
        } else if (id == Insts.STORE) {
            /* stack -> local */
            Object localVar = Lists.cadr(inst);
            Object slot = Lists.cadr(localVar);
            Class type = Data.javaClass(Lists.caddr(localVar));
            int local = Data.fixnum(ci.localTable.get(slot)).intValue();
            int op = Type.getType(type).getOpcode(Opcodes.ISTORE);
            if (Logger.tracelevelp(env))
                Logger.trace("[asm:gen]" + i + ":\tstore: local=~S type=~S",
                        Lists.list(Data.toFixnum(local), type), env);
            mv.visitVarInsn(op, local);
        } else if (id == Insts.POP) {
            /* pop a value and discard it */
            Class type = Data.javaClass(Lists.cadr(inst));
            int op;
            switch (Classes.sizeOf(type)) {
            case 1:
                op = Opcodes.POP;
                break;
            case 2:
                op = Opcodes.POP2;
                break;
            default:
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
            mv.visitInsn(op);
        } else if (id == Insts.DUP) {
            /* peek a value and duplicate it */
            Class type = Data.javaClass(Lists.cadr(inst));
            int op;
            switch (Classes.sizeOf(type)) {
            case 1:
                op = Opcodes.DUP;
                break;
            case 2:
                op = Opcodes.DUP2;
                break;
            default:
                throw new NotReachedException("unsupported type: ~S.", Lists.list(type));
            }
            mv.visitInsn(op);
        } else if (id == Insts.PUSH) {
            /* push a constant */
            Object val = Lists.cadr(inst);
            if (Data.isJavaBoolean(val)) {
                if (Data.javaBoolean(val).booleanValue())
                    mv.visitInsn(Opcodes.ICONST_1);
                else
                    mv.visitInsn(Opcodes.ICONST_0);
            } else if (val instanceof Byte || val instanceof Short || val instanceof Integer) {
                int n = Data.javaNumber(val).intValue();
                if (n == -1)
                    mv.visitInsn(Opcodes.ICONST_M1);
                else if (n == 0)
                    mv.visitInsn(Opcodes.ICONST_0);
                else if (n == 1)
                    mv.visitInsn(Opcodes.ICONST_1);
                else if (n == 2)
                    mv.visitInsn(Opcodes.ICONST_2);
                else if (n == 3)
                    mv.visitInsn(Opcodes.ICONST_3);
                else if (n == 4)
                    mv.visitInsn(Opcodes.ICONST_4);
                else if (n == 5)
                    mv.visitInsn(Opcodes.ICONST_5);
                else if (Byte.MIN_VALUE <= n && n <= Byte.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.BIPUSH, n);
                else if (Short.MIN_VALUE <= n && n <= Short.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.SIPUSH, n);
                else
                    mv.visitLdcInsn(Data.toFixnum(n));
            } else if (val instanceof Long) {
                long n = Data.javaNumber(val).longValue();
                if (n == 0L)
                    mv.visitInsn(Opcodes.LCONST_0);
                else if (n == 1L)
                    mv.visitInsn(Opcodes.LCONST_1);
                else
                    mv.visitLdcInsn(val);
            } else if (val instanceof Float) {
                float n = Data.javaNumber(val).floatValue();
                if (n == 0.0f)
                    mv.visitInsn(Opcodes.FCONST_0);
                else if (n == 1.0f)
                    mv.visitInsn(Opcodes.FCONST_1);
                else if (n == 2.0f)
                    mv.visitInsn(Opcodes.FCONST_2);
                else
                    mv.visitLdcInsn(val);
            } else if (val instanceof Double) {
                double n = Data.javaNumber(val).doubleValue();
                if (n == 0.0)
                    mv.visitInsn(Opcodes.DCONST_0);
                else if (n == 1.0)
                    mv.visitInsn(Opcodes.DCONST_1);
                else
                    mv.visitLdcInsn(val);
            } else if (Data.isCharacter(val)) {
                Character c = Data.character(val);
                int n = (int) c.charValue();
                if (Byte.MIN_VALUE <= n && n <= Byte.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.BIPUSH, n);
                else if (Short.MIN_VALUE <= n && n <= Short.MAX_VALUE)
                    mv.visitIntInsn(Opcodes.SIPUSH, n);
                else
                    mv.visitLdcInsn(Data.toFixnum(n));
            } else if (Data.isString(val)) {
                mv.visitLdcInsn(val);
            } else {
                throw new NotReachedException("cannot push: ~S.", Lists.list(val));
            }
        } else if (id == Insts.GET) {
            Field f = Data.javaField(Lists.cadr(inst));
            String fieldName = f.getName();
            Class c = f.getDeclaringClass();
            String className = c.getName();
            Class t = f.getType();
            String typeName = t.getName();

            boolean isStatic = Classes.isStatic(f);
            int op = isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD;

            mv.visitFieldInsn(op, toInternalName(className), fieldName, toTypeDescriptor(typeName));
        } else if (id == Insts.PUT) {
            Field f = Data.javaField(Lists.cadr(inst));
            String fieldName = f.getName();
            Class c = f.getDeclaringClass();
            String className = c.getName();
            Class t = f.getType();
            String typeName = t.getName();

            boolean isStatic = Classes.isStatic(f);
            int op = isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD;

            mv.visitFieldInsn(op, toInternalName(className), fieldName, toTypeDescriptor(typeName));
        } else if (id == Insts.INVOKE) {
            Method m = Data.javaMethod(Lists.cadr(inst));
            String methodName = m.getName();
            Class c = m.getDeclaringClass();
            String className = c.getName();
            Class rType = m.getReturnType();
            Class[] pTypes = m.getParameterTypes();
            if (rType.equals(void.class)) {
                throw new NotReachedException("unsupported returnType: ~S.", Lists.list(rType));
            }
            Type retType = Type.getType(rType);
            Type[] paramTypes = new Type[pTypes.length];
            for (int j = 0; j < pTypes.length; j++)
                paramTypes[j] = Type.getType(pTypes[j]);

            boolean isStatic = Classes.isStatic(m);
            boolean isInterface = c.isInterface();
            int op = isStatic ? Opcodes.INVOKESTATIC
                    : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL;

            mv.visitMethodInsn(op, toInternalName(className), methodName,
                    Type.getMethodDescriptor(retType, paramTypes));
        } else if (id == Insts.CHECKCAST) {
            Class c = Data.javaClass(Lists.cadr(inst));
            Type t = Type.getType(c);
            mv.visitTypeInsn(Opcodes.CHECKCAST, t.getInternalName());
        } else if (id == Insts.THROW) {
            mv.visitInsn(Opcodes.ATHROW);
        } else if (id == Insts.CATCH) {
            Symbol tagS = Data.symbol(Lists.cadr(inst));
            Symbol tagE = Data.symbol(Lists.caddr(inst));
            Symbol tagH = Data.symbol(Lists.cadddr(inst));
            String className;
            if (Lists.isEnd(Lists.cddddr(inst))) {
                className = null;
            } else {
                Class c = Data.javaClass(Lists.car(Lists.cddddr(inst)));
                className = toInternalName(c.getName());
            }
            Label labelS = (Label) ci.labelTable.get(tagS);
            if (labelS == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tagS));
            }
            Label labelE = (Label) ci.labelTable.get(tagE);
            if (labelE == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tagE));
            }
            Label labelH = (Label) ci.labelTable.get(tagH);
            if (labelH == null) {
                throw new NotReachedException("label not found: ~S.", Lists.list(tagH));
            }
            mv.visitTryCatchBlock(labelS, labelE, labelH, className);
        }
        //else if (id == Insts.CATCH_FROM ||
        //         id == Insts.CATCH_TO ||
        //         id == Insts.CATCH_HANDLER) {
        //    /* nothing emitted */
        //    continue;
        //}
        else {
            throw new NotReachedException("unknown inst: ~S.", Lists.list(inst));
        }
    }
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}