Search in sources :

Example 36 with ForwardReference

use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.

the class BaselineCompilerImpl method emit_checkcast_resolvedInterface.

@Override
protected void emit_checkcast_resolvedInterface(RVMClass type) {
    int interfaceIndex = type.getDoesImplementIndex();
    int interfaceMask = type.getDoesImplementBitMask();
    // load the object being checked
    peekAddr(T0, 0);
    // check for null
    asm.emitCMPAddrI(T0, 0);
    ForwardReference isNull = asm.emitForwardBC(EQ);
    // TIB of "this" object
    asm.baselineEmitLoadTIB(T0, T0);
    // implements bit vector
    asm.emitLAddr(T0, TIB_DOES_IMPLEMENT_INDEX << LOG_BYTES_IN_ADDRESS, T0);
    if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
        // must do arraybounds check of implements bit vector
        // T1 gets array length
        asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset());
        asm.emitLVAL(T2, interfaceIndex);
        asm.emitCMPL(T2, T1);
        // if in bounds, jump around trap.  TODO: would like to encode "y" bit that this branch is expected to be takem.
        ForwardReference fr1 = asm.emitForwardBC(LT);
        // encoding of TRAP_ALWAYS CHECKCAST
        asm.emitTWI(31, GPR.R12, CHECKCAST_TRAP);
        fr1.resolve(asm);
    }
    // Test the appropriate bit and if set, branch around another trap imm
    asm.emitLInt(T1, interfaceIndex << LOG_BYTES_IN_INT, T0);
    if ((interfaceMask & 0xffff) == interfaceMask) {
        asm.emitANDI(S0, T1, interfaceMask);
    } else {
        if (VM.VerifyAssertions)
            VM._assert((interfaceMask & 0xffff0000) == interfaceMask);
        asm.emitANDIS(S0, T1, interfaceMask);
    }
    // TODO: encode "y" bit that branch is likely taken.
    ForwardReference fr2 = asm.emitForwardBC(NE);
    // encoding of TRAP_ALWAYS CHECKCAST
    asm.emitTWI(31, GPR.R12, CHECKCAST_TRAP);
    fr2.resolve(asm);
    isNull.resolve(asm);
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference)

Example 37 with ForwardReference

use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.

the class BaselineCompilerImpl method generateAddrComparison.

/**
 * Emit code to perform an unsigned comparison on 2 address values
 * @param cc condition to test
 */
private void generateAddrComparison(boolean signed, int cc) {
    popAddr(T1);
    popAddr(T0);
    asm.emitLVAL(T2, 1);
    if (signed) {
        asm.emitCMPAddr(T0, T1);
    } else {
        asm.emitCMPLAddr(T0, T1);
    }
    ForwardReference fr = asm.emitForwardBC(cc);
    asm.emitLVAL(T2, 0);
    fr.resolve(asm);
    pushInt(T2);
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference)

Example 38 with ForwardReference

use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.

the class BaselineCompilerImpl method emit_invokeinterface.

@Override
protected void emit_invokeinterface(MethodReference methodRef) {
    // +1 for "this" parameter
    int count = methodRef.getParameterWords() + 1;
    RVMMethod resolvedMethod = null;
    resolvedMethod = methodRef.peekInterfaceMethod();
    // do so inline.
    if (VM.BuildForIMTInterfaceInvocation) {
        if (methodRef.isMiranda()) {
        // TODO: It's not entirely clear that we can just assume that
        // the class actually implements the interface.
        // However, we don't know what interface we need to be checking
        // so there doesn't appear to be much else we can do here.
        } else {
            if (resolvedMethod == null) {
                // Can't successfully resolve it at compile time.
                // Call uncommon case typechecking routine to do the right thing when this code actually executes.
                asm.emitLAddrToc(T0, Entrypoints.unresolvedInvokeinterfaceImplementsTestMethod.getOffset());
                asm.emitMTCTR(T0);
                // id of method reference we are trying to call
                asm.emitLVAL(T0, methodRef.getId());
                // the "this" object
                peekAddr(T1, count - 1);
                // throw exception, if link error
                asm.emitBCCTRL();
            } else {
                RVMClass interfaceClass = resolvedMethod.getDeclaringClass();
                int interfaceIndex = interfaceClass.getDoesImplementIndex();
                int interfaceMask = interfaceClass.getDoesImplementBitMask();
                // the "this" object
                peekAddr(T0, count - 1);
                // TIB of "this" object
                asm.baselineEmitLoadTIB(T0, T0);
                // implements bit vector
                asm.emitLAddr(T0, TIB_DOES_IMPLEMENT_INDEX << LOG_BYTES_IN_ADDRESS, T0);
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    // must do arraybounds check of implements bit vector
                    // T1 gets array length
                    asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset());
                    asm.emitLVAL(T2, interfaceIndex);
                    asm.emitCMPL(T2, T1);
                    // if in bounds, jump around trap.  TODO: would like to encode "y" bit that this branch is expected to be takem.
                    ForwardReference fr1 = asm.emitForwardBC(LT);
                    // encoding of TRAP_ALWAYS MUST_IMPLEMENT_INTERFACE
                    asm.emitTWI(31, GPR.R12, MUST_IMPLEMENT_TRAP);
                    fr1.resolve(asm);
                }
                // Test the appropriate bit and if set, branch around another trap imm
                asm.emitLInt(T1, interfaceIndex << LOG_BYTES_IN_INT, T0);
                if ((interfaceMask & 0xffff) == interfaceMask) {
                    asm.emitANDI(S0, T1, interfaceMask);
                } else {
                    if (VM.VerifyAssertions)
                        VM._assert((interfaceMask & 0xffff0000) == interfaceMask);
                    asm.emitANDIS(S0, T1, interfaceMask);
                }
                // TODO: encode "y" bit that branch is likely taken.
                ForwardReference fr2 = asm.emitForwardBC(NE);
                // encoding of TRAP_ALWAYS MUST_IMPLEMENT_INTERFACE
                asm.emitTWI(31, GPR.R12, MUST_IMPLEMENT_TRAP);
                fr2.resolve(asm);
            }
        }
    }
    // (2) Emit interface invocation sequence.
    if (VM.BuildForIMTInterfaceInvocation) {
        InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(methodRef);
        // T0 is "this"
        genMoveParametersToRegisters(true, methodRef);
        asm.baselineEmitLoadTIB(S0, T0);
        // Load the IMT base into S0
        asm.emitLAddr(S0, TIB_INTERFACE_DISPATCH_TABLE_INDEX << LOG_BYTES_IN_ADDRESS, S0);
        // the method address
        asm.emitLAddrOffset(S0, S0, sig.getIMTOffset());
        asm.emitMTCTR(S0);
        // pass "hidden" parameter in S1 scratch  register
        asm.emitLVAL(S1, sig.getId());
        asm.emitBCCTRL();
    } else {
        int itableIndex = -1;
        if (VM.BuildForITableInterfaceInvocation && resolvedMethod != null) {
            // get the index of the method in the Itable
            itableIndex = InterfaceInvocation.getITableIndex(resolvedMethod.getDeclaringClass(), methodRef.getName(), methodRef.getDescriptor());
        }
        if (itableIndex == -1) {
            // itable index is not known at compile-time.
            // call "invokeInterface" to resolve object + method id into method address
            int methodRefId = methodRef.getId();
            asm.emitLAddrToc(T0, Entrypoints.invokeInterfaceMethod.getOffset());
            asm.emitMTCTR(T0);
            // object
            peekAddr(T0, count - 1);
            // method id
            asm.emitLVAL(T1, methodRefId);
            // T0 := resolved method address
            asm.emitBCCTRL();
            asm.emitMTCTR(T0);
            genMoveParametersToRegisters(true, methodRef);
            asm.emitBCCTRL();
        } else {
            // itable index is known at compile-time.
            // call "findITable" to resolve object + interface id into
            // itable address
            asm.emitLAddrToc(T0, Entrypoints.findItableMethod.getOffset());
            asm.emitMTCTR(T0);
            // object
            peekAddr(T0, count - 1);
            asm.baselineEmitLoadTIB(T0, T0);
            // interface id
            asm.emitLVAL(T1, resolvedMethod.getDeclaringClass().getInterfaceId());
            // T0 := itable reference
            asm.emitBCCTRL();
            // T0 := the method to call
            asm.emitLAddr(T0, itableIndex << LOG_BYTES_IN_ADDRESS, T0);
            asm.emitMTCTR(T0);
            // T0 is "this"
            genMoveParametersToRegisters(true, methodRef);
            asm.emitBCCTRL();
        }
    }
    genPopParametersAndPushReturnValue(true, methodRef);
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference) InterfaceMethodSignature(org.jikesrvm.classloader.InterfaceMethodSignature) RVMMethod(org.jikesrvm.classloader.RVMMethod) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 39 with ForwardReference

use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.

the class BaselineCompilerImpl method generateInlineCode.

// *************************************************************************
// MAGIC
// *************************************************************************
/*
   *  Generate inline machine instructions for special methods that cannot be
   *  implemented in java bytecodes. These instructions are generated whenever
   *  we encounter an "invokestatic" bytecode that calls a method with a
   *  signature of the form "static native Magic.xxx(...)".
   *
   * NOTE: when adding a new "methodName" to "generate()", be sure to also
   * consider how it affects the values on the stack and update
   * "checkForActualCall()" accordingly.
   * If no call is actually generated, the map will reflect the status of the
   * locals (including parameters) at the time of the call but nothing on the
   * operand stack for the call site will be mapped.
   */
/**
 * Generate inline code sequence for specified method.
 * @param methodToBeCalled method whose name indicates semantics of code to be generated
 * @return true if there was magic defined for the method
 */
private boolean generateInlineCode(MethodReference methodToBeCalled) {
    Atom methodName = methodToBeCalled.getName();
    if (methodToBeCalled.isSysCall()) {
        TypeReference[] args = methodToBeCalled.getParameterTypes();
        // (1) Set up arguments according to OS calling convention, excluding the first
        // which is not an argument to the native function but the address of the function to call
        int paramWords = methodToBeCalled.getParameterWords();
        int gp = FIRST_OS_PARAMETER_GPR.value();
        int fp = FIRST_OS_PARAMETER_FPR.value();
        int stackIndex = paramWords - 1;
        int paramBytes = ((VM.BuildFor64Addr ? args.length : paramWords) - 1) * BYTES_IN_STACKSLOT;
        int callee_param_index = -BYTES_IN_STACKSLOT - paramBytes;
        for (int i = 1; i < args.length; i++) {
            TypeReference t = args[i];
            if (t.isLongType()) {
                stackIndex -= 2;
                callee_param_index += BYTES_IN_LONG;
                if (VM.BuildFor64Addr) {
                    if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                        peekLong(GPR.lookup(gp), GPR.lookup(gp), stackIndex);
                        gp++;
                    } else {
                        peekLong(S0, S0, stackIndex);
                        asm.emitSTD(S0, callee_param_index - BYTES_IN_LONG, FP);
                    }
                } else {
                    if (VM.BuildForLinux) {
                        /* NOTE: following adjustment is not stated in SVR4 ABI, but
               * was implemented in GCC.
               */
                        // if gpr is even, gpr += 1
                        gp += (gp + 1) & 0x01;
                    }
                    if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                        peekInt(GPR.lookup(gp++), stackIndex);
                    }
                    // lo register := lo mem (== hi order word)
                    if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                        // hi register := hi mem (== lo order word)
                        peekInt(GPR.lookup(gp++), stackIndex + 1);
                    } else {
                        peekLong(S0, S1, stackIndex);
                        asm.emitSTW(S0, callee_param_index - BYTES_IN_LONG, FP);
                        asm.emitSTW(S1, callee_param_index - BYTES_IN_INT, FP);
                    }
                }
            } else if (t.isFloatType()) {
                stackIndex -= 1;
                callee_param_index += BYTES_IN_STACKSLOT;
                if (fp <= LAST_OS_PARAMETER_FPR.value()) {
                    peekFloat(FPR.lookup(fp++), stackIndex);
                } else {
                    peekFloat(FIRST_SCRATCH_FPR, stackIndex);
                    asm.emitSTFS(FIRST_SCRATCH_FPR, callee_param_index - BYTES_IN_FLOAT, FP);
                }
            } else if (t.isDoubleType()) {
                stackIndex -= 2;
                callee_param_index += BYTES_IN_DOUBLE;
                if (fp <= LAST_OS_PARAMETER_FPR.value()) {
                    peekDouble(FPR.lookup(fp++), stackIndex);
                } else {
                    peekDouble(FIRST_SCRATCH_FPR, stackIndex);
                    asm.emitSTFD(FIRST_SCRATCH_FPR, callee_param_index - BYTES_IN_DOUBLE, FP);
                }
            } else if (t.isIntLikeType()) {
                stackIndex -= 1;
                callee_param_index += BYTES_IN_STACKSLOT;
                if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                    peekInt(GPR.lookup(gp++), stackIndex);
                } else {
                    peekInt(S0, stackIndex);
                    // save int zero-extended to be sure
                    asm.emitSTAddr(S0, callee_param_index - BYTES_IN_ADDRESS, FP);
                }
            } else {
                // t is object
                stackIndex -= 1;
                callee_param_index += BYTES_IN_STACKSLOT;
                if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                    peekAddr(GPR.lookup(gp++), stackIndex);
                } else {
                    peekAddr(S0, stackIndex);
                    asm.emitSTAddr(S0, callee_param_index - BYTES_IN_ADDRESS, FP);
                }
            }
        }
        if (VM.VerifyAssertions) {
            VM._assert(stackIndex == 0);
        }
        // (2) Call it
        // Load addres of function into S0
        peekAddr(S0, paramWords - 1);
        // make the call
        generateSysCall(paramBytes);
        // (3) Pop Java expression stack
        discardSlots(paramWords);
        // (4) Push return value (if any)
        TypeReference rtype = methodToBeCalled.getReturnType();
        if (rtype.isIntLikeType()) {
            pushInt(T0);
        } else if (rtype.isWordLikeType() || rtype.isReferenceType()) {
            pushAddr(T0);
        } else if (rtype.isDoubleType()) {
            pushDouble(FIRST_OS_PARAMETER_FPR);
        } else if (rtype.isFloatType()) {
            pushFloat(FIRST_OS_PARAMETER_FPR);
        } else if (rtype.isLongType()) {
            pushLong(T0, VM.BuildFor64Addr ? T0 : T1);
        }
        return true;
    }
    if (methodToBeCalled.getType() == TypeReference.Address) {
        // Address.xyz magic
        TypeReference[] types = methodToBeCalled.getParameterTypes();
        if (methodName == MagicNames.loadAddress || methodName == MagicNames.loadObjectReference || methodName == MagicNames.loadWord) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base)
                asm.emitLAddr(T0, 0, T0);
                // push *(base)
                pushAddr(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // *(base+offset)
                asm.emitLAddrX(T0, T1, T0);
                // push *(base+offset)
                pushAddr(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadChar) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLHZ(T0, 0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLHZX(T0, T1, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadShort) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // load with sign extension.
                asm.emitLHA(T0, 0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // load with sign extension.
                asm.emitLHAX(T0, T1, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadByte) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLBZ(T0, 0, T0);
                // sign extend
                asm.emitEXTSB(T0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLBZX(T0, T1, T0);
                // sign extend
                asm.emitEXTSB(T0, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadInt || methodName == MagicNames.loadFloat) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base)
                asm.emitLInt(T0, 0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // *(base+offset)
                asm.emitLIntX(T0, T1, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadDouble || methodName == MagicNames.loadLong) {
            if (types.length == 0) {
                // pop base
                popAddr(T1);
                // *(base)
                asm.emitLFD(F0, 0, T1);
                // push double
                pushDouble(F0);
            } else {
                // pop offset
                popOffset(T2);
                // pop base
                popAddr(T1);
                // *(base+offset)
                asm.emitLFDX(F0, T1, T2);
                // push *(base+offset)
                pushDouble(F0);
            }
            return true;
        }
        if ((methodName == MagicNames.prepareInt) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareWord)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareObjectReference)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareAddress))) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base), setting reservation address
                asm.emitLWARX(T0, GPR.R0, T0);
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // *(base+offset), setting reservation address
                asm.emitLWARX(T0, T1, T0);
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if ((methodName == MagicNames.prepareLong) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareWord)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareObjectReference)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareAddress))) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base), setting reservation address
                asm.emitLDARX(T0, GPR.R0, T0);
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushAddr(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                if (VM.BuildFor64Addr) {
                    // *(base+offset), setting reservation address
                    asm.emitLDARX(T0, T1, T0);
                } else {
                // TODO: handle 64bit prepares in 32bit environment
                }
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushAddr(T0);
            }
            return true;
        }
        if (methodName == MagicNames.attempt && ((types[0] == TypeReference.Int) || (VM.BuildFor32Addr && (types[0] == TypeReference.Address)) || (VM.BuildFor32Addr && (types[0] == TypeReference.Word)))) {
            if (types.length == 2) {
                // pop newValue
                popInt(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                // store new value and set CR0
                asm.emitSTWCXr(T2, GPR.R0, T0);
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop newValue
                popInt(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                // store new value and set CR0
                asm.emitSTWCXr(T2, T1, T0);
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.attempt && ((types[0] == TypeReference.Long) || (VM.BuildFor64Addr && (types[0] == TypeReference.Address)) || (VM.BuildFor64Addr && (types[0] == TypeReference.Word)))) {
            if (types.length == 2) {
                // pop newValue
                popAddr(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                // store new value and set CR0
                asm.emitSTDCXr(T2, GPR.R0, T0);
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop newValue
                popAddr(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                if (VM.BuildFor64Addr) {
                    // store new value and set CR0
                    asm.emitSTDCXr(T2, T1, T0);
                } else {
                // TODO: handle 64bit attempts in 32bit environment
                }
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            }
            return true;
        }
        // ..., Address, Value, [Offset] -> ...
        if (methodName == MagicNames.store) {
            if (types[0] == TypeReference.Word || types[0] == TypeReference.ObjectReference || types[0] == TypeReference.Address) {
                if (types.length == 1) {
                    // pop newvalue
                    popAddr(T1);
                    // pop base
                    popAddr(T0);
                    // *(base) = newvalue
                    asm.emitSTAddrX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popAddr(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTAddrX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Byte || types[0] == TypeReference.Boolean) {
                if (types.length == 1) {
                    // pop newvalue
                    popInt(T1);
                    // pop base
                    popAddr(T0);
                    // *(base) = newvalue
                    asm.emitSTBX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popInt(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTBX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Int || types[0] == TypeReference.Float) {
                if (types.length == 1) {
                    // pop newvalue
                    popInt(T1);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTWX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popInt(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTWX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Short || types[0] == TypeReference.Char) {
                if (types.length == 1) {
                    // pop newvalue
                    popInt(T1);
                    // pop base
                    popAddr(T0);
                    // *(base) = newvalue
                    asm.emitSTHX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popInt(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTHX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Double || types[0] == TypeReference.Long) {
                if (types.length == 1) {
                    // pop newvalue low and high
                    popLong(T2, T1);
                    // pop base
                    popAddr(T0);
                    if (VM.BuildFor32Addr) {
                        // *(base) = newvalue low
                        asm.emitSTW(T2, 0, T0);
                        // *(base+4) = newvalue high
                        asm.emitSTW(T1, BYTES_IN_INT, T0);
                    } else {
                        // *(base) = newvalue
                        asm.emitSTD(T1, 0, T0);
                    }
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue low and high
                    popLong(T3, T2);
                    // pop base
                    popAddr(T0);
                    if (VM.BuildFor32Addr) {
                        // *(base+offset) = newvalue low
                        asm.emitSTWX(T3, T1, T0);
                        // offset += 4
                        asm.emitADDI(T1, BYTES_IN_INT, T1);
                        // *(base+offset) = newvalue high
                        asm.emitSTWX(T2, T1, T0);
                    } else {
                        // *(base+offset) = newvalue
                        asm.emitSTDX(T2, T1, T0);
                    }
                }
                return true;
            }
        }
    }
    if (methodName == MagicNames.getFramePointer) {
        pushAddr(FP);
    } else if (methodName == MagicNames.getCallerFramePointer) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load frame pointer of caller frame
        asm.emitLAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
        // push frame pointer of caller frame
        pushAddr(T1);
    } else if (methodName == MagicNames.setCallerFramePointer) {
        // value
        popAddr(T1);
        // fp
        popAddr(T0);
        // *(address+SFPO) := value
        asm.emitSTAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
    } else if (methodName == MagicNames.getCompiledMethodID) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load compiled method id
        asm.emitLInt(T1, STACKFRAME_METHOD_ID_OFFSET.toInt(), T0);
        // push method ID
        pushInt(T1);
    } else if (methodName == MagicNames.setCompiledMethodID) {
        // value
        popInt(T1);
        // fp
        popAddr(T0);
        // *(address+SNIO) := value
        asm.emitSTW(T1, STACKFRAME_METHOD_ID_OFFSET.toInt(), T0);
    } else if (methodName == MagicNames.getNextInstructionAddress) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load frame pointer of caller frame
        asm.emitLAddr(T1, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), T0);
        // push frame pointer of caller frame
        pushAddr(T1);
    } else if (methodName == MagicNames.getReturnAddressLocation) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load frame pointer of caller frame
        asm.emitLAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
        // get location containing ret addr
        asm.emitADDI(T2, STACKFRAME_RETURN_ADDRESS_OFFSET, T1);
        // push frame pointer of caller frame
        pushAddr(T2);
    } else if (methodName == MagicNames.getTocPointer || methodName == MagicNames.getJTOC) {
        pushAddr(JTOC);
    } else if (methodName == MagicNames.getThreadRegister) {
        pushAddr(THREAD_REGISTER);
    } else if (methodName == MagicNames.setThreadRegister) {
        popAddr(THREAD_REGISTER);
    } else if (methodName == MagicNames.getTimeBase) {
        if (VM.BuildFor64Addr) {
            // T1 := time base
            asm.emitMFTB(T1);
        } else {
            int label = asm.getMachineCodeIndex();
            // T0 := time base, upper
            asm.emitMFTBU(T0);
            // T1 := time base, lower
            asm.emitMFTB(T1);
            // T2 := time base, upper
            asm.emitMFTBU(T2);
            // T0 == T2?
            asm.emitCMP(T0, T2);
            // lower rolled over, try again
            asm.emitBC(NE, label);
        }
        pushLong(T0, T1);
    } else if (methodName == MagicNames.invokeClassInitializer) {
        // t0 := address to be called
        popAddr(T0);
        asm.emitMTCTR(T0);
        // call
        asm.emitBCCTRL();
    } else if (methodName == MagicNames.invokeMethodReturningVoid) {
        // call method
        generateMethodInvocation();
    } else if (methodName == MagicNames.invokeMethodReturningInt) {
        // call method
        generateMethodInvocation();
        // push result
        pushInt(T0);
    } else if (methodName == MagicNames.invokeMethodReturningLong) {
        // call method
        generateMethodInvocation();
        // push result
        pushLong(T0, VM.BuildFor64Addr ? T0 : T1);
    } else if (methodName == MagicNames.invokeMethodReturningFloat) {
        // call method
        generateMethodInvocation();
        // push result
        pushFloat(F0);
    } else if (methodName == MagicNames.invokeMethodReturningDouble) {
        // call method
        generateMethodInvocation();
        // push result
        pushDouble(F0);
    } else if (methodName == MagicNames.invokeMethodReturningObject) {
        // call method
        generateMethodInvocation();
        // push result
        pushAddr(T0);
    } else if (methodName == MagicNames.addressArrayCreate) {
        RVMArray type = methodToBeCalled.getType().resolve().asArray();
        emit_resolved_newarray(type);
    } else if (methodName == MagicNames.addressArrayLength) {
        emit_arraylength();
    } else if (methodName == MagicNames.addressArrayGet) {
        genBoundsCheck();
        if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
            // convert index to offset
            asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);
            // load desired int array element
            asm.emitLIntX(T2, T0, T1);
            pushInt(T2);
        } else {
            // convert index to offset
            asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);
            // load desired array element
            asm.emitLAddrX(T2, T0, T1);
            pushAddr(T2);
        }
    } else if (methodName == MagicNames.addressArraySet) {
        // T2 is value to store
        popAddr(T2);
        genBoundsCheck();
        if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
            // convert index to offset
            asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);
            // store 32-bit value in array
            asm.emitSTWX(T2, T0, T1);
        } else {
            // convert index to offset
            asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);
            // store value in array
            asm.emitSTAddrX(T2, T0, T1);
        }
    } else if (methodName == MagicNames.getIntAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset)
        asm.emitLIntX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getFloatAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset)
        asm.emitLWZX(T0, T1, T0);
        // push *(object+offset),
        pushInt(T0);
    // asm.emitLFSX  (F0, T1, T0); // *(object+offset)
    // pushFloat(F0);
    } else if (methodName == MagicNames.getObjectAtOffset || methodName == MagicNames.getWordAtOffset || methodName == MagicNames.getAddressAtOffset || methodName == MagicNames.getOffsetAtOffset || methodName == MagicNames.getExtentAtOffset || methodName == MagicNames.getTIBAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 3) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset)
        asm.emitLAddrX(T0, T1, T0);
        // push *(object+offset)
        pushAddr(T0);
    } else if (methodName == MagicNames.getUnsignedByteAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load byte with zero extension.
        asm.emitLBZX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getByteAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load byte with zero extension.
        asm.emitLBZX(T0, T1, T0);
        // sign extend
        asm.emitEXTSB(T0, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getCharAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load char with zero extension.
        asm.emitLHZX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getShortAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load short with sign extension.
        asm.emitLHAX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.setIntAtOffset || methodName == MagicNames.setFloatAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popInt(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTWX(T2, T1, T0);
    } else if (methodName == MagicNames.setObjectAtOffset || methodName == MagicNames.setWordAtOffset || methodName == MagicNames.setAddressAtOffset || methodName == MagicNames.setOffsetAtOffset || methodName == MagicNames.setExtentAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popAddr(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTAddrX(T2, T1, T0);
    } else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popInt(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTBX(T2, T1, T0);
    } else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popInt(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTHX(T2, T1, T0);
    } else if (methodName == MagicNames.getLongAtOffset || methodName == MagicNames.getDoubleAtOffset) {
        // pop offset
        popOffset(T2);
        // pop object
        popAddr(T1);
        asm.emitLFDX(F0, T1, T2);
        pushDouble(F0);
    } else if ((methodName == MagicNames.setLongAtOffset) || (methodName == MagicNames.setDoubleAtOffset)) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        popLong(T3, T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        if (VM.BuildFor32Addr) {
            // *(object+offset) = newvalue low
            asm.emitSTWX(T3, T1, T0);
            // offset += 4
            asm.emitADDI(T1, BYTES_IN_INT, T1);
            // *(object+offset) = newvalue high
            asm.emitSTWX(T2, T1, T0);
        } else {
            // *(object+offset) = newvalue
            asm.emitSTDX(T2, T1, T0);
        }
    } else if (methodName == MagicNames.getMemoryInt) {
        // address
        popAddr(T0);
        // *address
        asm.emitLInt(T0, 0, T0);
        // *sp := *address
        pushInt(T0);
    } else if (methodName == MagicNames.getMemoryWord || methodName == MagicNames.getMemoryAddress) {
        // address
        popAddr(T0);
        // *address
        asm.emitLAddr(T0, 0, T0);
        // *sp := *address
        pushAddr(T0);
    } else if (methodName == MagicNames.setMemoryInt) {
        // value
        popInt(T1);
        // address
        popAddr(T0);
        // *address := value
        asm.emitSTW(T1, 0, T0);
    } else if (methodName == MagicNames.setMemoryWord) {
        if (methodToBeCalled.getParameterTypes().length == 3) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // value
        popAddr(T1);
        // address
        popAddr(T0);
        // *address := value
        asm.emitSTAddr(T1, 0, T0);
    } else if ((methodName == MagicNames.prepareInt) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareObject)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareAddress)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareWord))) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset), setting thread's reservation address
        asm.emitLWARX(T0, T1, T0);
        // this Integer is not sign extended !!
        // push *(object+offset)
        pushInt(T0);
    } else if ((methodName == MagicNames.prepareLong) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareObject)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareAddress)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareWord))) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        if (VM.BuildFor64Addr) {
            // *(object+offset), setting thread's reservation address
            asm.emitLDARX(T0, T1, T0);
        } else {
        // TODO: handle 64bit prepares in 32bit environment
        }
        // push *(object+offset)
        pushAddr(T0);
    } else if ((methodName == MagicNames.attemptInt) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptObject)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptObjectReference)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptAddress)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptWord))) {
        // pop newValue
        popInt(T2);
        // ignore oldValue
        discardSlot();
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // store new value and set CR0
        asm.emitSTWCXr(T2, T1, T0);
        // T0 := false
        asm.emitLVAL(T0, 0);
        // skip, if store failed
        ForwardReference fr = asm.emitForwardBC(NE);
        // T0 := true
        asm.emitLVAL(T0, 1);
        fr.resolve(asm);
        // push success of conditional store
        pushInt(T0);
    } else if (methodName == MagicNames.attemptLong) {
        // pop newValue
        popLong(T3, T2);
        // ignore oldValue which is a long and thus takes 2 slots
        discardSlots(2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        if (VM.BuildFor64Addr) {
            // store new value and set CR0
            asm.emitSTDCXr(T2, T1, T0);
        } else {
        // TODO: handle 64bit attempts in 32bit environment
        }
        // T0 := false
        asm.emitLVAL(T0, 0);
        // skip, if store failed
        ForwardReference fr = asm.emitForwardBC(NE);
        // T0 := true
        asm.emitLVAL(T0, 1);
        fr.resolve(asm);
        // push success of conditional store
        pushInt(T0);
    } else if (VM.BuildFor64Addr && ((methodName == MagicNames.attemptObject) || (methodName == MagicNames.attemptObjectReference) || (methodName == MagicNames.attemptAddress) || (methodName == MagicNames.attemptWord))) {
        // pop newValue
        popAddr(T2);
        // ignore oldValue
        discardSlot();
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // store new value and set CR0
        asm.emitSTDCXr(T2, T1, T0);
        // T0 := false
        asm.emitLVAL(T0, 0);
        // skip, if store failed
        ForwardReference fr = asm.emitForwardBC(NE);
        // T0 := true
        asm.emitLVAL(T0, 1);
        fr.resolve(asm);
        // push success of conditional store
        pushInt(T0);
    } else if (methodName == MagicNames.saveThreadState) {
        // T0 := address of Registers object
        peekAddr(T0, 0);
        asm.emitLAddrToc(S0, ArchEntrypoints.saveThreadStateInstructionsField.getOffset());
        asm.emitMTCTR(S0);
        // call out of line machine code
        asm.emitBCCTRL();
        // pop arg
        discardSlot();
    } else if (methodName == MagicNames.threadSwitch) {
        // T1 := address of Registers of new thread
        peekAddr(T1, 0);
        // T0 := address of previous RVMThread object
        peekAddr(T0, 1);
        asm.emitLAddrToc(S0, ArchEntrypoints.threadSwitchInstructionsField.getOffset());
        asm.emitMTCTR(S0);
        asm.emitBCCTRL();
        // pop two args
        discardSlots(2);
    } else if (methodName == MagicNames.restoreHardwareExceptionState) {
        // T0 := address of Registers object
        peekAddr(T0, 0);
        asm.emitLAddrToc(S0, ArchEntrypoints.restoreHardwareExceptionStateInstructionsField.getOffset());
        asm.emitMTLR(S0);
        // branch to out of line machine code (does not return)
        asm.emitBCLR();
    } else if (methodName == MagicNames.returnToNewStack) {
        // FP := new stackframe
        peekAddr(FP, 0);
        // fetch...
        asm.emitLAddr(S0, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), FP);
        // ...return address
        asm.emitMTLR(S0);
        // return to caller
        asm.emitBCLR();
    } else if (methodName == MagicNames.dynamicBridgeTo) {
        if (VM.VerifyAssertions)
            VM._assert(klass.hasDynamicBridgeAnnotation());
        // fetch parameter (address to branch to) into CT register
        // 
        peekAddr(T0, 0);
        asm.emitMTCTR(T0);
        // restore volatile and non-volatile registers
        // (note that these are only saved for "dynamic bridge" methods)
        // 
        int offset = frameSize;
        // restore non-volatile and volatile fprs
        for (int i = LAST_NONVOLATILE_FPR.value(); i >= FIRST_VOLATILE_FPR.value(); --i) {
            asm.emitLFD(FPR.lookup(i), offset -= BYTES_IN_DOUBLE, FP);
        }
        // restore non-volatile gprs
        for (int i = LAST_NONVOLATILE_GPR.value(); i >= FIRST_NONVOLATILE_GPR.value(); --i) {
            asm.emitLAddr(GPR.lookup(i), offset -= BYTES_IN_ADDRESS, FP);
        }
        // skip saved thread-id, thread, and scratch registers
        offset -= (FIRST_NONVOLATILE_GPR.value() - LAST_VOLATILE_GPR.value() - 1) * BYTES_IN_ADDRESS;
        // restore volatile gprs
        for (int i = LAST_VOLATILE_GPR.value(); i >= FIRST_VOLATILE_GPR.value(); --i) {
            asm.emitLAddr(GPR.lookup(i), offset -= BYTES_IN_ADDRESS, FP);
        }
        // pop stackframe
        asm.emitLAddr(FP, 0, FP);
        // restore link register
        asm.emitLAddr(S0, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), FP);
        asm.emitMTLR(S0);
        // branch always, through count register
        asm.emitBCCTR();
    } else if (methodName == MagicNames.objectAsAddress || methodName == MagicNames.addressAsByteArray || methodName == MagicNames.addressAsObject || methodName == MagicNames.addressAsTIB || methodName == MagicNames.objectAsType || methodName == MagicNames.objectAsShortArray || methodName == MagicNames.objectAsIntArray || methodName == MagicNames.objectAsThread || methodName == MagicNames.floatAsIntBits || methodName == MagicNames.intBitsAsFloat || methodName == MagicNames.doubleAsLongBits || methodName == MagicNames.longBitsAsDouble) {
    // no-op (a type change, not a representation change)
    } else if (methodName == MagicNames.getObjectType) {
        // get object pointer
        popAddr(T0);
        asm.baselineEmitLoadTIB(T0, T0);
        // get "type" field from type information block
        asm.emitLAddr(T0, TIB_TYPE_INDEX << LOG_BYTES_IN_ADDRESS, T0);
        // *sp := type
        pushAddr(T0);
    } else if (methodName == MagicNames.getArrayLength) {
        // get object pointer
        popAddr(T0);
        // get array length field
        asm.emitLIntOffset(T0, T0, ObjectModel.getArrayLengthOffset());
        // *sp := length
        pushInt(T0);
    } else if (methodName == MagicNames.synchronizeInstructionCache) {
        asm.emitISYNC();
    } else if (methodName == MagicNames.pause) {
    // NO-OP
    } else if (methodName == MagicNames.combinedLoadBarrier) {
        asm.emitHWSYNC();
    } else if (methodName == MagicNames.storeStoreBarrier) {
        asm.emitSYNC();
    } else if (methodName == MagicNames.fence) {
        asm.emitHWSYNC();
    } else if (methodName == MagicNames.illegalInstruction) {
        asm.emitIllegalInstruction();
    } else if (methodName == MagicNames.dcbst) {
        // address
        popAddr(T0);
        asm.emitDCBST(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbt || methodName == MagicNames.prefetch) {
        // address
        popAddr(T0);
        asm.emitDCBT(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbtst) {
        // address
        popAddr(T0);
        asm.emitDCBTST(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbz) {
        // address
        popAddr(T0);
        asm.emitDCBZ(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbzl) {
        // address
        popAddr(T0);
        asm.emitDCBZL(GPR.R0, T0);
    } else if (methodName == MagicNames.icbi) {
        // address
        popAddr(T0);
        asm.emitICBI(GPR.R0, T0);
    } else if (methodName == MagicNames.sqrt) {
        TypeReference argType = method.getParameterTypes()[0];
        if (argType == TypeReference.Float) {
            popFloat(F0);
            asm.emitFSQRTS(F0, F0);
            pushFloat(F0);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(argType == TypeReference.Double);
            popDouble(F0);
            asm.emitFSQRT(F0, F0);
            pushDouble(F0);
        }
    } else if (methodName == MagicNames.getInlineDepth || methodName == MagicNames.isConstantParameter) {
        emit_iconst(0);
    } else if (methodName == MagicNames.getCompilerLevel) {
        emit_iconst(-1);
    } else if (methodName == MagicNames.getFrameSize) {
        emit_iconst(frameSize);
    } else if (methodName == MagicNames.wordToInt || methodName == MagicNames.wordToAddress || methodName == MagicNames.wordToOffset || methodName == MagicNames.wordToObject || methodName == MagicNames.wordFromObject || methodName == MagicNames.wordToObjectReference || methodName == MagicNames.wordToExtent || methodName == MagicNames.wordToWord || methodName == MagicNames.codeArrayAsObject || methodName == MagicNames.tibAsObject) {
    // no-op
    } else if (methodName == MagicNames.wordToLong) {
        asm.emitLVAL(T0, 0);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordFromInt || methodName == MagicNames.wordFromIntSignExtend) {
        if (VM.BuildFor64Addr) {
            popInt(T0);
            pushAddr(T0);
        }
    // else no-op
    } else if (methodName == MagicNames.wordFromIntZeroExtend) {
        if (VM.BuildFor64Addr) {
            asm.emitLWZ(T0, spTopOffset + BYTES_IN_STACKSLOT - BYTES_IN_INT, FP);
            pokeAddr(T0, 0);
        }
    // else no-op
    } else if (methodName == MagicNames.wordFromLong) {
        discardSlot();
    } else if (methodName == MagicNames.wordPlus) {
        if (VM.BuildFor64Addr && (methodToBeCalled.getParameterTypes()[0] == TypeReference.Int)) {
            popInt(T0);
        } else {
            popAddr(T0);
        }
        popAddr(T1);
        asm.emitADD(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordMinus || methodName == MagicNames.wordDiff) {
        if (VM.BuildFor64Addr && (methodToBeCalled.getParameterTypes()[0] == TypeReference.Int)) {
            popInt(T0);
        } else {
            popAddr(T0);
        }
        popAddr(T1);
        asm.emitSUBFC(T2, T0, T1);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordEQ) {
        generateAddrComparison(false, EQ);
    } else if (methodName == MagicNames.wordNE) {
        generateAddrComparison(false, NE);
    } else if (methodName == MagicNames.wordLT) {
        generateAddrComparison(false, LT);
    } else if (methodName == MagicNames.wordLE) {
        generateAddrComparison(false, LE);
    } else if (methodName == MagicNames.wordGT) {
        generateAddrComparison(false, GT);
    } else if (methodName == MagicNames.wordGE) {
        generateAddrComparison(false, GE);
    } else if (methodName == MagicNames.wordsLT) {
        generateAddrComparison(true, LT);
    } else if (methodName == MagicNames.wordsLE) {
        generateAddrComparison(true, LE);
    } else if (methodName == MagicNames.wordsGT) {
        generateAddrComparison(true, GT);
    } else if (methodName == MagicNames.wordsGE) {
        generateAddrComparison(true, GE);
    } else if (methodName == MagicNames.wordIsZero || methodName == MagicNames.wordIsNull) {
        // unsigned comparison generating a boolean
        popAddr(T0);
        asm.emitLVAL(T1, 0);
        asm.emitLVAL(T2, 1);
        asm.emitCMPLAddr(T0, T1);
        ForwardReference fr = asm.emitForwardBC(EQ);
        asm.emitLVAL(T2, 0);
        fr.resolve(asm);
        pushInt(T2);
    } else if (methodName == MagicNames.wordIsMax) {
        // unsigned comparison generating a boolean
        popAddr(T0);
        asm.emitLVAL(T1, -1);
        asm.emitLVAL(T2, 1);
        asm.emitCMPLAddr(T0, T1);
        ForwardReference fr = asm.emitForwardBC(EQ);
        asm.emitLVAL(T2, 0);
        fr.resolve(asm);
        pushInt(T2);
    } else if (methodName == MagicNames.wordZero || methodName == MagicNames.wordNull) {
        asm.emitLVAL(T0, 0);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordOne) {
        asm.emitLVAL(T0, 1);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordMax) {
        asm.emitLVAL(T0, -1);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordAnd) {
        popAddr(T0);
        popAddr(T1);
        asm.emitAND(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordOr) {
        popAddr(T0);
        popAddr(T1);
        asm.emitOR(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordNot) {
        popAddr(T0);
        asm.emitLVAL(T1, -1);
        asm.emitXOR(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordXor) {
        popAddr(T0);
        popAddr(T1);
        asm.emitXOR(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordLsh) {
        popInt(T0);
        popAddr(T1);
        asm.emitSLAddr(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordRshl) {
        popInt(T0);
        popAddr(T1);
        asm.emitSRAddr(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordRsha) {
        popInt(T0);
        popAddr(T1);
        asm.emitSRA_Addr(T2, T1, T0);
        pushAddr(T2);
    } else {
        return false;
    }
    return true;
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference) RVMArray(org.jikesrvm.classloader.RVMArray) TypeReference(org.jikesrvm.classloader.TypeReference) Atom(org.jikesrvm.classloader.Atom)

Example 40 with ForwardReference

use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.

the class BaselineCompilerImpl method emit_instanceof_resolvedClass.

@Override
protected void emit_instanceof_resolvedClass(RVMClass type) {
    int LHSDepth = type.getTypeDepth();
    int LHSId = type.getId();
    // load object from stack and check for null
    popAddr(T0);
    asm.emitCMPAddrI(T0, 0);
    ForwardReference isNull = asm.emitForwardBC(EQ);
    // get superclass display from object's TIB
    asm.baselineEmitLoadTIB(T0, T0);
    asm.emitLAddr(T0, TIB_SUPERCLASS_IDS_INDEX << LOG_BYTES_IN_ADDRESS, T0);
    ForwardReference outOfBounds = null;
    if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
        // must do arraybounds check of superclass display
        // T1 gets array length
        asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset());
        asm.emitLVAL(T2, LHSDepth);
        asm.emitCMPL(T1, T2);
        outOfBounds = asm.emitForwardBC(LE);
    }
    // Load id from display at required depth and compare against target id; set T0 to 1 (true) if matched
    asm.emitLHZ(T0, LHSDepth << LOG_BYTES_IN_CHAR, T0);
    if (Assembler.fits(LHSId, 16)) {
        asm.emitCMPI(T0, LHSId);
    } else {
        asm.emitLVAL(T1, LHSId);
        asm.emitCMP(T0, T1);
    }
    ForwardReference notMatched = asm.emitForwardBC(NE);
    asm.emitLVAL(T0, 1);
    ForwardReference done = asm.emitForwardB();
    // set T0 to 0 (false)
    isNull.resolve(asm);
    if (outOfBounds != null)
        outOfBounds.resolve(asm);
    notMatched.resolve(asm);
    asm.emitLVAL(T0, 0);
    // push T0, containing the result of the instanceof comparision, to the stack.
    done.resolve(asm);
    pushInt(T0);
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference)

Aggregations

ForwardReference (org.jikesrvm.compilers.common.assembler.ForwardReference)71 Offset (org.vmmagic.unboxed.Offset)13 TypeReference (org.jikesrvm.classloader.TypeReference)5 RVMClass (org.jikesrvm.classloader.RVMClass)4 Assembler (org.jikesrvm.compilers.common.assembler.ppc.Assembler)4 RVMMethod (org.jikesrvm.classloader.RVMMethod)3 GPR (org.jikesrvm.ia32.RegisterConstants.GPR)3 XMM (org.jikesrvm.ia32.RegisterConstants.XMM)3 InterfaceMethodSignature (org.jikesrvm.classloader.InterfaceMethodSignature)2 RVMArray (org.jikesrvm.classloader.RVMArray)2 Assembler (org.jikesrvm.compilers.common.assembler.ia32.Assembler)2 FloatingPointMachineRegister (org.jikesrvm.ia32.RegisterConstants.FloatingPointMachineRegister)2 JNICompiledMethod (org.jikesrvm.jni.JNICompiledMethod)2 Entrypoint (org.vmmagic.pragma.Entrypoint)2 Inline (org.vmmagic.pragma.Inline)2 Address (org.vmmagic.unboxed.Address)2 Atom (org.jikesrvm.classloader.Atom)1 FieldReference (org.jikesrvm.classloader.FieldReference)1 MethodReference (org.jikesrvm.classloader.MethodReference)1 RVMType (org.jikesrvm.classloader.RVMType)1