Esempio n. 1
0
TR::Register *OMR::Power::Linkage::pushLongArg(TR::Node *child)
   {
   TR::Register *pushRegister = NULL;
   if (child->getRegister() == NULL && child->getOpCode().isLoadConst())
      {
      if (TR::Compiler->target.is64Bit())
         {
         pushRegister = self()->cg()->allocateRegister();
         loadConstant(self()->cg(), child, child->getLongInt(), pushRegister);
         }
      else
         {
         TR::Register   *lowRegister = self()->cg()->allocateRegister();
         TR::Register   *highRegister = self()->cg()->allocateRegister();
         pushRegister = self()->cg()->allocateRegisterPair(lowRegister, highRegister);
         loadConstant(self()->cg(), child, child->getLongIntLow(), lowRegister);
         loadConstant(self()->cg(), child, child->getLongIntHigh(), highRegister);
         }
      child->setRegister(pushRegister);
      }
   else
      {
      pushRegister = self()->cg()->evaluate(child);
      }
   self()->cg()->decReferenceCount(child);
   return pushRegister;
   }
Esempio n. 2
0
static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
{
    int flags = dexGetFlagsFromOpcode(mir->dalvikInsn.opcode);
    int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
                       kInstrCanThrow;

    //If already optimized out, just ignore
    if (mir->dalvikInsn.opcode == OP_NOP)
        return;

    //Ugly, but necessary.  Flush all Dalvik regs so Interp can find them
    dvmCompilerFlushAllRegs(cUnit);

    if ((mir->next == NULL) || (flags & flagsToCheck)) {
       genPuntToInterp(cUnit, mir->offset);
       return;
    }
    int entryAddr = offsetof(Thread,
                             jitToInterpEntries.dvmJitToInterpSingleStep);
    loadWordDisp(cUnit, rEBP, 0, rECX);  // Get glue
    loadWordDisp(cUnit, rECX, entryAddr, rEAX); // rEAX<- entry address
    /* rPC = dalvik pc */
    loadConstant(cUnit, rPC, (int) (cUnit->method->insns + mir->offset));
    /* rECX = dalvik pc of following instruction */
    loadConstant(cUnit, rECX, (int) (cUnit->method->insns + mir->next->offset));
    /* Pass on the stack */
    storeWordDisp(cUnit, rESP, OUT_ARG0, rECX);
    opReg(cUnit, kOpCall, rEAX);
}
Esempio n. 3
0
/*
 * 64-bit 3way compare function.
 *     mov   r7, #-1
 *     cmp   op1hi, op2hi
 *     blt   done
 *     bgt   flip
 *     sub   r7, op1lo, op2lo (treat as unsigned)
 *     beq   done
 *     ite   hi
 *     mov(hi)   r7, #-1
 *     mov(!hi)  r7, #1
 * flip:
 *     neg   r7
 * done:
 */
static void genCmpLong(CompilationUnit *cUnit, MIR *mir,
                       RegLocation rlDest, RegLocation rlSrc1,
                       RegLocation rlSrc2)
{
    RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change
    ArmLIR *target1;
    ArmLIR *target2;
    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
    rlTemp.lowReg = dvmCompilerAllocTemp(cUnit);
    loadConstant(cUnit, rlTemp.lowReg, -1);
    opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
    ArmLIR *branch1 = opCondBranch(cUnit, kArmCondLt);
    ArmLIR *branch2 = opCondBranch(cUnit, kArmCondGt);
    opRegRegReg(cUnit, kOpSub, rlTemp.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
    ArmLIR *branch3 = opCondBranch(cUnit, kArmCondEq);

    genIT(cUnit, kArmCondHi, "E");
    newLIR2(cUnit, kThumb2MovImmShift, rlTemp.lowReg, modifiedImmediate(-1));
    loadConstant(cUnit, rlTemp.lowReg, 1);
    genBarrier(cUnit);

    target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
    target2->defMask = -1;
    opRegReg(cUnit, kOpNeg, rlTemp.lowReg, rlTemp.lowReg);

    target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
    target1->defMask = -1;

    storeValue(cUnit, rlDest, rlTemp);

    branch1->generic.target = (LIR *)target1;
    branch2->generic.target = (LIR *)target2;
    branch3->generic.target = branch1->generic.target;
}
/*
 * Rebuild the interpreter frame then punt to the interpreter to execute
 * instruction at specified PC.
 *
 * Currently parameters are passed to the current frame, so we just need to
 * grow the stack save area above it, fill certain fields in StackSaveArea and
 * Thread that are skipped during whole-method invocation (specified below),
 * then return to the interpreter.
 *
 * StackSaveArea:
 *  - prevSave
 *  - prevFrame
 *  - savedPc
 *  - returnAddr
 *  - method
 *
 * Thread:
 *  - method
 *  - methodClassDex
 *  - curFrame
 */
static void genMethodInflateAndPunt(CompilationUnit *cUnit, MIR *mir,
                                    BasicBlock *bb)
{
    int oldStackSave = r0;
    int newStackSave = r1;
    int oldFP = r2;
    int savedPC = r3;
    int currentPC = r4PC;
    int returnAddr = r7;
    int method = r8;
    int pDvmDex = r9;

    /*
     * TODO: check whether to raise the stack overflow exception when growing
     * the stack save area.
     */

    /* Send everything to home location */
    dvmCompilerFlushAllRegs(cUnit);

    /* oldStackSave = r5FP + sizeof(current frame) */
    opRegRegImm(cUnit, kOpAdd, oldStackSave, r5FP,
                cUnit->method->registersSize * 4);
    /* oldFP = oldStackSave + sizeof(stackSaveArea) */
    opRegRegImm(cUnit, kOpAdd, oldFP, oldStackSave, sizeof(StackSaveArea));
    /* newStackSave = r5FP - sizeof(StackSaveArea) */
    opRegRegImm(cUnit, kOpSub, newStackSave, r5FP, sizeof(StackSaveArea));

    loadWordDisp(cUnit, r13sp, 0, savedPC);
    loadConstant(cUnit, currentPC, (int) (cUnit->method->insns + mir->offset));
    loadConstant(cUnit, method, (int) cUnit->method);
    loadConstant(cUnit, pDvmDex, (int) cUnit->method->clazz->pDvmDex);
#ifdef EASY_GDB
    /* newStackSave->prevSave = oldStackSave */
    storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, prevSave),
                  oldStackSave);
#endif
    /* newStackSave->prevSave = oldStackSave */
    storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, prevFrame),
                  oldFP);
    /* newStackSave->savedPc = savedPC */
    storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, savedPc),
                  savedPC);
    /* return address */
    loadConstant(cUnit, returnAddr, 0);
    storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, returnAddr),
                  returnAddr);
    /* newStackSave->method = method */
    storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, method), method);
    /* thread->method = method */
    storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, method), method);
    /* thread->interpSave.curFrame = current FP */
    storeWordDisp(cUnit, r6SELF, offsetof(Thread, interpSave.curFrame), r5FP);
    /* thread->methodClassDex = pDvmDex */
    storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, methodClassDex),
                  pDvmDex);
    /* Restore the stack pointer */
    opRegImm(cUnit, kOpAdd, r13sp, 16);
    genPuntToInterp(cUnit, mir->offset);
}
Esempio n. 5
0
static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
                     RegLocation rlSrc1, RegLocation rlSrc2)
{
    bool isDouble;
    int defaultResult;
    bool ltNaNBias;
    RegLocation rlResult;

    switch(mir->dalvikInsn.opCode) {
        case OP_CMPL_FLOAT:
            isDouble = false;
            defaultResult = -1;
            break;
        case OP_CMPG_FLOAT:
            isDouble = false;
            defaultResult = 1;
            break;
        case OP_CMPL_DOUBLE:
            isDouble = true;
            defaultResult = -1;
            break;
        case OP_CMPG_DOUBLE:
            isDouble = true;
            defaultResult = 1;
            break;
        default:
            return true;
    }
    if (isDouble) {
        rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
        rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
        dvmCompilerClobberSReg(cUnit, rlDest.sRegLow);
        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
        loadConstant(cUnit, rlResult.lowReg, defaultResult);
        newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
                S2D(rlSrc2.lowReg, rlSrc2.highReg));
    } else {
        rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
        rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
        dvmCompilerClobberSReg(cUnit, rlDest.sRegLow);
        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
        loadConstant(cUnit, rlResult.lowReg, defaultResult);
        newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
    }
    assert(!FPREG(rlResult.lowReg));
    newLIR0(cUnit, kThumb2Fmstat);
    genIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
    newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
            modifiedImmediate(-defaultResult)); // Must not alter ccodes
    genIT(cUnit, kArmCondEq, "");
    loadConstant(cUnit, rlResult.lowReg, 0);
    storeValue(cUnit, rlDest, rlResult);
    return false;
}
Esempio n. 6
0
/*
 * For monitor unlock, we don't have to use ldrex/strex.  Once
 * we've determined that the lock is thin and that we own it with
 * a zero recursion count, it's safe to punch it back to the
 * initial, unlock thin state with a store word.
 */
static void genMonitorExit(CompilationUnit *cUnit, MIR *mir)
{
    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
    ArmLIR *target;
    ArmLIR *branch;
    ArmLIR *hopTarget;
    ArmLIR *hopBranch;

    assert(LW_SHAPE_THIN == 0);
    loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
    dvmCompilerLockAllTemps(cUnit);  // Prepare for explicit register usage
    dvmCompilerFreeTemp(cUnit, r4PC);  // Free up r4 for general use
    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
    loadWordDisp(cUnit, r1, offsetof(Object, lock), r2); // Get object->lock
    loadWordDisp(cUnit, r6SELF, offsetof(Thread, threadId), r3); // Get threadId
    // Is lock unheld on lock or held by us (==threadId) on unlock?
    opRegRegImm(cUnit, kOpAnd, r7, r2,
                (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
    opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner
    newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT,
            LW_LOCK_OWNER_SHIFT - 1);
    opRegReg(cUnit, kOpSub, r2, r3);
    hopBranch = opCondBranch(cUnit, kArmCondNe);
    dvmCompilerGenMemBarrier(cUnit, kSY);
    storeWordDisp(cUnit, r1, offsetof(Object, lock), r7);
    branch = opNone(cUnit, kOpUncondBr);

    hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
    hopTarget->defMask = ENCODE_ALL;
    hopBranch->generic.target = (LIR *)hopTarget;

    // Export PC (part 1)
    loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset));

    LOAD_FUNC_ADDR(cUnit, r7, (int)dvmUnlockObject);
    genRegCopy(cUnit, r0, r6SELF);
    // Export PC (part 2)
    newLIR3(cUnit, kThumb2StrRRI8Predec, r3, r5FP,
            sizeof(StackSaveArea) -
            offsetof(StackSaveArea, xtra.currentPc));
    opReg(cUnit, kOpBlx, r7);
    /* Did we throw? */
    ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
    loadConstant(cUnit, r0,
                 (int) (cUnit->method->insns + mir->offset +
                 dexGetWidthFromOpcode(OP_MONITOR_EXIT)));
    genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);

    // Resume here
    target = newLIR0(cUnit, kArmPseudoTargetLabel);
    target->defMask = ENCODE_ALL;
    branch->generic.target = (LIR *)target;
    branchOver->generic.target = (LIR *) target;
}
Esempio n. 7
0
/*
 * Handle simple case (thin lock) inline.  If it's complicated, bail
 * out to the heavyweight lock/unlock routines.  We'll use dedicated
 * registers here in order to be in the right position in case we
 * to bail to dvm[Lock/Unlock]Object(self, object)
 *
 * r0 -> self pointer [arg0 for dvm[Lock/Unlock]Object
 * r1 -> object [arg1 for dvm[Lock/Unlock]Object
 * r2 -> intial contents of object->lock, later result of strex
 * r3 -> self->threadId
 * r7 -> temp to hold new lock value [unlock only]
 * r4 -> allow to be used by utilities as general temp
 *
 * The result of the strex is 0 if we acquire the lock.
 *
 * See comments in Sync.c for the layout of the lock word.
 * Of particular interest to this code is the test for the
 * simple case - which we handle inline.  For monitor enter, the
 * simple case is thin lock, held by no-one.  For monitor exit,
 * the simple case is thin lock, held by the unlocking thread with
 * a recurse count of 0.
 *
 * A minor complication is that there is a field in the lock word
 * unrelated to locking: the hash state.  This field must be ignored, but
 * preserved.
 *
 */
static void genMonitorEnter(CompilationUnit *cUnit, MIR *mir)
{
    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
    bool enter = (mir->dalvikInsn.opCode == OP_MONITOR_ENTER);
    ArmLIR *target;
    ArmLIR *hopTarget;
    ArmLIR *branch;
    ArmLIR *hopBranch;

    assert(LW_SHAPE_THIN == 0);
    loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
    dvmCompilerLockAllTemps(cUnit);  // Prepare for explicit register usage
    dvmCompilerFreeTemp(cUnit, r4PC);  // Free up r4 for general use
    loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0); // Get self
    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
    loadWordDisp(cUnit, r0, offsetof(Thread, threadId), r3); // Get threadId
    newLIR3(cUnit, kThumb2Ldrex, r2, r1,
            offsetof(Object, lock) >> 2); // Get object->lock
    opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner
    // Is lock unheld on lock or held by us (==threadId) on unlock?
    newLIR4(cUnit, kThumb2Bfi, r3, r2, 0, LW_LOCK_OWNER_SHIFT - 1);
    newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT,
            LW_LOCK_OWNER_SHIFT - 1);
    hopBranch = newLIR2(cUnit, kThumb2Cbnz, r2, 0);
    newLIR4(cUnit, kThumb2Strex, r2, r3, r1, offsetof(Object, lock) >> 2);
    branch = newLIR2(cUnit, kThumb2Cbz, r2, 0);

    hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
    hopTarget->defMask = ENCODE_ALL;
    hopBranch->generic.target = (LIR *)hopTarget;

    // Clear the lock
    ArmLIR *inst = newLIR0(cUnit, kThumb2Clrex);
    // ...and make it a scheduling barrier
    inst->defMask = ENCODE_ALL;

    // Export PC (part 1)
    loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset));

    /* Get dPC of next insn */
    loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
                                    dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
    // Export PC (part 2)
    newLIR3(cUnit, kThumb2StrRRI8Predec, r3, rFP,
            sizeof(StackSaveArea) -
            offsetof(StackSaveArea, xtra.currentPc));
    /* Call template, and don't return */
    genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
    // Resume here
    target = newLIR0(cUnit, kArmPseudoTargetLabel);
    target->defMask = ENCODE_ALL;
    branch->generic.target = (LIR *)target;
}
Esempio n. 8
0
/*
 * Bail to the interpreter.  Will not return to this trace.
 * On entry, rPC must be set correctly.
 */
static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
{
    dvmCompilerFlushAllRegs(cUnit);
    loadConstant(cUnit, rPC, (int)(cUnit->method->insns + offset));
    loadWordDisp(cUnit, rEBP, 0, rECX);  // Get glue
    loadWordDisp(cUnit, rECX,
                 offsetof(Thread, jitToInterpEntries.dvmJitToInterpPunt),
                 rEAX);
    opReg(cUnit, kOpUncondBr, rEAX);
}
Esempio n. 9
0
/* Export the Dalvik PC assicated with an instruction to the StackSave area */
static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir)
{
    ArmLIR *res;
    int offset = offsetof(StackSaveArea, xtra.currentPc);
    int rDPC = dvmCompilerAllocTemp(cUnit);
    res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
    newLIR3(cUnit, kThumb2StrRRI8Predec, rDPC, r5FP,
            sizeof(StackSaveArea) - offset);
    dvmCompilerFreeTemp(cUnit, rDPC);
    return res;
}
Esempio n. 10
0
/* Export the Dalvik PC assicated with an instruction to the StackSave area */
static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir)
{
    ArmLIR *res;
    int rDPC = dvmCompilerAllocTemp(cUnit);
    int rAddr = dvmCompilerAllocTemp(cUnit);
    int offset = offsetof(StackSaveArea, xtra.currentPc);
    res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
    newLIR2(cUnit, kThumbMovRR, rAddr, rFP);
    newLIR2(cUnit, kThumbSubRI8, rAddr, sizeof(StackSaveArea) - offset);
    storeWordDisp( cUnit, rAddr, 0, rDPC);
    return res;
}
Esempio n. 11
0
static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
{
    int offset = offsetof(InterpState, retval);
    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
    int reg0 = loadValue(cUnit, rlSrc, kCoreReg).lowReg;
    int signMask = dvmCompilerAllocTemp(cUnit);
    loadConstant(cUnit, signMask, 0x7fffffff);
    newLIR2(cUnit, kThumbAndRR, reg0, signMask);
    dvmCompilerFreeTemp(cUnit, signMask);
    storeWordDisp(cUnit, rGLUE, offset, reg0);
    //TUNING: rewrite this to not clobber
    dvmCompilerClobber(cUnit, reg0);
    return true;
}
Esempio n. 12
0
TR::Register *OMR::Power::Linkage::pushIntegerWordArg(TR::Node *child)
   {
   TR::Register *pushRegister = NULL;
   TR_ASSERT(child->getDataType() != TR::Address, "assumption violated");
   if (child->getRegister() == NULL && child->getOpCode().isLoadConst())
      {
      pushRegister = self()->cg()->allocateRegister();
      loadConstant(self()->cg(), child, (int32_t)child->get64bitIntegralValue(), pushRegister);
      child->setRegister(pushRegister);
      }
   else
      {
      pushRegister = self()->cg()->evaluate(child);
      }
   self()->cg()->decReferenceCount(child);
   return pushRegister;
   }
Esempio n. 13
0
static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
{
    int offset = offsetof(Thread, interpSave.retval);
    RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
    RegLocation regSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
    int reglo = regSrc.lowReg;
    int reghi = regSrc.highReg;
    int signMask = dvmCompilerAllocTemp(cUnit);
    loadConstant(cUnit, signMask, 0x7fffffff);
    storeWordDisp(cUnit, r6SELF, offset, reglo);
    newLIR2(cUnit, kThumbAndRR, reghi, signMask);
    dvmCompilerFreeTemp(cUnit, signMask);
    storeWordDisp(cUnit, r6SELF, offset + 4, reghi);
    //TUNING: rewrite this to not clobber
    dvmCompilerClobber(cUnit, reghi);
    return false;
}
/*
 * Jump to the out-of-line handler in ARM mode to finish executing the
 * remaining of more complex instructions.
 */
static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode)
{
#if USE_IN_CACHE_HANDLER
    /*
     * NOTE - In practice BLX only needs one operand, but since the assembler
     * may abort itself and retry due to other out-of-range conditions we
     * cannot really use operand[0] to store the absolute target address since
     * it may get clobbered by the final relative offset. Therefore,
     * we fake BLX_1 is a two operand instruction and the absolute target
     * address is stored in operand[1].
     */
    newLIR2(cUnit, THUMB_BLX_1,
            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
    newLIR2(cUnit, THUMB_BLX_2,
            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
#else
    /*
     * In case we want to access the statically compiled handlers for
     * debugging purposes, define USE_IN_CACHE_HANDLER to 0
     */
    void *templatePtr;

#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
#include "../../../template/armv5te-vfp/TemplateOpList.h"
#undef JIT_TEMPLATE
    switch (opCode) {
#define JIT_TEMPLATE(X) \
        case TEMPLATE_##X: { templatePtr = dvmCompiler_TEMPLATE_##X; break; }
#include "../../../template/armv5te-vfp/TemplateOpList.h"
#undef JIT_TEMPLATE
        default: templatePtr = NULL;
    }
    loadConstant(cUnit, r7, (int) templatePtr);
    newLIR1(cUnit, THUMB_BLX_R, r7);
#endif
}
Esempio n. 15
0
/*
 * Jump to the out-of-line handler to finish executing the
 * remaining of more complex instructions.
 */
static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpcode opCode)
{
    /*
     * We're jumping from a trace to a template. Using jal is preferable to jalr,
     * but we need to ensure source and target addresses allow the use of jal.
     * This should almost always be the case, but if source and target are in
     * different 256mb regions then use jalr.  The test below is very conservative
     * since we don't have a source address yet, but this is ok for now given that
     * we expect this case to be very rare. The test can be made less conservative
     * as needed in the future in coordination with address assignment during
     * the assembly process.
     */
    dvmCompilerClobberHandlerRegs(cUnit);
    int targetAddr = (int) gDvmJit.codeCache + templateEntryOffsets[opCode];
    int maxSourceAddr = (int) gDvmJit.codeCache + gDvmJit.codeCacheSize;

    if ((targetAddr & 0xF0000000) == (maxSourceAddr & 0xF0000000)) {
        newLIR1(cUnit, kMipsJal, targetAddr);
    } else {
        loadConstant(cUnit, r_T9, targetAddr);
        newLIR2(cUnit, kMipsJalr, r_RA, r_T9);
    }
}
Esempio n. 16
0
void GPUProgram::setArgs(RenderDevice* renderDevice, const ArgList& args) {
    int numVariables = 0;

    // Iterate through formal bindings
    for (int b = 0; b < bindingTable.bindingArray.size(); ++b) {
        const BindingTable::Binding& binding = bindingTable.bindingArray[b];
        
        if (binding.source == VARIABLE) {
            ++numVariables;
            alwaysAssertM(args.argTable.containsKey(binding.name),
                std::string("No value provided for GPUProgram variable \"") + binding.name + "\"");

            const ArgList::Arg& arg = args.argTable[binding.name];

            // check the type
            alwaysAssertM(arg.type == binding.type,
                std::string("Variable \"") + binding.name +
                "\" was declared as type " + GPUProgram::toString(binding.type) + " and the values supplied" +
                " at runtime had type " + GPUProgram::toString(arg.type));

            if (binding.slot != BindingTable::Binding::UNASSIGNED) {
                switch (binding.type) {
                case SAMPLER1D:
			    case SAMPLER2D:
			    case SAMPLER3D:
			    case SAMPLERCUBE:
			    case SAMPLERRECT:
				    renderDevice->setTexture(binding.slot, arg.texture);
				    break;

                case FLOAT4:
                case FLOAT3:
                case FLOAT2:
                case FLOAT1:
                    loadConstant(binding.slot, arg.vector[0]);
                    break;

                case FLOAT2X2:
                    alwaysAssertM(false, "FLOAT2X2 not implemented.");
                    break;

                case FLOAT3X3:
                    for (int s = 0; s < 3; ++s) {
                        loadConstant(binding.slot + s, arg.vector[s]);
                    }
                    break;

                case FLOAT4X4:
                    for (int s = 0; s < 4; ++s) {
                        loadConstant(binding.slot + s, arg.vector[s]);
                    }
                    break;
                }
            }
        }
    }

    if (numVariables < args.argTable.size()) {
        // Some variables were unused.  Figure out which they were.
        Table<std::string, ArgList::Arg>::Iterator arg = args.argTable.begin();
        Table<std::string, ArgList::Arg>::Iterator end = args.argTable.end();

        while (arg != end) {
            // See if this arg was in the formal binding list

            bool foundArgument = false;
            
            for (int b = 0; b < bindingTable.bindingArray.size(); ++b) {
                if (bindingTable.bindingArray[b].name == arg->key) {
                    foundArgument = true;
                    break;
                }
            }

            debugAssertM(foundArgument, 
                std::string("Unused GPU program argument specified: \"") + arg->key + "\".");

            ++arg;
        }
    }

}
Esempio n. 17
0
// operand count((operand0 flags, operand0 operator index, operand0 result index)...(operand0 flags, [operandN operator index, operandN result index|operandN constant value]))
// alternate operand specification:
// (operand0 flags, constant count(constant0 value,...,constantN value))
bool ATKIOperator::load(Stream *program) {
	if (!loadProperties(program)) {
		program->flush();
		return false;
	}

	char buffer[21];
	memset(buffer, 0, 21);
	int index = 0;
	bool valid = false;
	while(Antikythera::readProgram(program)) {
		char c = (char)program->read();
		program->print(c);

		if (c == '(') {
			valid = true;
			break;
		}
		if (index == 3) {
#ifdef ANTIKYTHERA_DEBUG
			m_lastErrorString = m_name + "::load() - operand count has too many digits.";
#endif
			program->flush();
			return false;
		}
		if (!isdigit(c)) {
#ifdef ANTIKYTHERA_DEBUG
			m_lastErrorString = m_name + "::load() - operand count contains invalid character: " + String(c);
#endif
			program->flush();
			return false;
		}
		buffer[index++] = c;
	}
	if (!valid) {
#ifdef ANTIKYTHERA_DEBUG
		m_lastErrorString = m_name + "::load() - unexpected end of stream while reading operand count.";
#endif
		program->flush();
		return false;
	}

	initializeOperands((uint8_t)strtoul(buffer, NULL, 10));
#ifdef ANTIKYTHERA_DEBUG
	program->print("[num operands:");
	program->print(buffer);
	program->println("]");
#endif

	for (int count = 0; count < m_numOperands; count++) {
		valid = false;
		while(Antikythera::readProgram(program)) {
			char c = (char)program->read();
			program->print(c);

			if (c == '(') {
				valid = true;
				break;
			}
#ifdef ANTIKYTHERA_DEBUG
			m_lastErrorString = m_name + "::load() - operand[" + String(count) + "] expected opening parenthesis, read invalid character: " + String(c);
#endif
			program->flush();
			return false;
		}
		if (!valid) {
#ifdef ANTIKYTHERA_DEBUG
			m_lastErrorString = m_name + "::load() - operand[" + String(count) + "] unexpected end of stream while reading opening parenthesis.";
#endif
			program->flush();
			return false;
		}

		if (!loadFlags(program, &m_operands[count].flags)) {
			return false;
		}
		if (m_operands[count].flags & OPERANDFLAG_LINK) {
			if (!loadOperatorIndex(program, &m_operands[count].operatorIndex)) {
				return false;
			}
			if (!loadResultIndex(program, &m_operands[count].resultIndex)) {
				return false;
			}
		} else {
			if (!loadConstant(program, count, m_operands[count].flags)) {
				return false;
			}

			valid = false;
			while(Antikythera::readProgram(program)) {
				char c = (char)program->read();
				program->print(c);

				if (c == ')') {
					valid = true;
					break;
				}
#ifdef ANTIKYTHERA_DEBUG
				m_lastErrorString = m_name + "::load() - expected closing parenthesis, read invalid character: " + String(c);
#endif
				program->flush();
				return false;
			}
			if (!valid) {
#ifdef ANTIKYTHERA_DEBUG
				m_lastErrorString = m_name + "::load() - unexpected end of stream while reading closing parenthesis.";
#endif
				program->flush();
				return false;
			}
		}
	}

	valid = false;
	while(Antikythera::readProgram(program)) {
		char c = (char)program->read();
		program->print(c);

		if (c == ')') {
			valid = true;
			break;
		}
#ifdef ANTIKYTHERA_DEBUG
		m_lastErrorString = m_name + "::load() - expected closing parenthesis, read invalid character: " + String(c);
#endif
		program->flush();
		return false;
	}
	if (!valid) {
#ifdef ANTIKYTHERA_DEBUG
		m_lastErrorString = m_name + "::load() - unexpected end of stream while reading closing parenthesis.";
#endif
		program->flush();
		return false;
	}

	// connect root to leaf nodes

	return true;
}
Esempio n. 18
0
MainWindow::MainWindow(QDesktopWidget * d):QMainWindow()
{
	this->setMinimumSize(d->availableGeometry().width()/1.15, d->availableGeometry().height()/1.25);
	this->setDockNestingEnabled(false);
	this->setDockOptions(NULL);
	this->setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
	this->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
	this->setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
	this->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
	
	databackend=new DataBackend();
	databackend->setDataInserter(new ChangeFactory(databackend));
	databrowser=new DataBrowser(databackend,d);
	dataeditor=new DataEditor(databackend,d);
	
	QObject::connect(databrowser,SIGNAL(editObject(QString)),dataeditor,SLOT(loadObject(QString)));
	QObject::connect(databrowser,SIGNAL(editForce(QString)),dataeditor,SLOT(loadForce(QString)));
	QObject::connect(databrowser,SIGNAL(editMacro(QString)),dataeditor,SLOT(loadMacro(QString)));
	QObject::connect(databrowser,SIGNAL(editConstant(QString)),dataeditor,SLOT(loadConstant(QString)));
	QObject::connect(databrowser,SIGNAL(deleteObject(QString)),dataeditor,SLOT(loadBlank()));
	QObject::connect(databrowser,SIGNAL(deleteForce(QString)),dataeditor,SLOT(loadBlank()));
	QObject::connect(databrowser,SIGNAL(deleteMacro(QString)),dataeditor,SLOT(loadBlank()));
	QObject::connect(databrowser,SIGNAL(deleteConstant(QString)),dataeditor,SLOT(loadBlank()));
	
	simcontrol=new SimulationControl(databackend);
	openglpane=new GLDrawPane(databackend,d);

	timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), openglpane, SLOT(updateGL()));
	connect(qApp, SIGNAL(lastWindowClosed()),timer,SLOT(stop()));
	timer -> start(15);

	this->setCentralWidget(openglpane);

	this->addDockWidget(Qt::RightDockWidgetArea, databrowser);
	this->addDockWidget(Qt::RightDockWidgetArea, dataeditor);
	this->addDockWidget(Qt::BottomDockWidgetArea, simcontrol);
	
	QMenu * fileMenu = this->menuBar()->addMenu(tr("File"));
	QMenu * newMenu=fileMenu->addMenu("New Project");
	newMenu->addAction("Blank Project",databackend,SLOT(newFromBlank()),QKeySequence("Ctrl+N"));
	newMenu->addAction("From Default",databackend,SLOT(newFromDefault()),QKeySequence("Ctrl+Shift+N"));
	fileMenu->addAction("Open Project",databackend,SLOT(load()),QKeySequence("Ctrl+O"));
	fileMenu->addAction("Save Project",databackend,SLOT(save()),QKeySequence("Ctrl+S"));
	fileMenu->addAction("Save Project As",databackend,SLOT(saveAs()),QKeySequence("Ctrl+Shift+S"));
	fileMenu->addAction("Exit",databackend, SLOT(quit()));
	QMenu * editMenu = this->menuBar()->addMenu(tr("Edit"));
	QAction * undo=databackend->getUndoStack()->createUndoAction(this);
	undo->setShortcut(QKeySequence(QKeySequence::Undo));
	editMenu->addAction(undo);
	QAction * redo=databackend->getUndoStack()->createRedoAction(this);
	redo->setShortcut(QKeySequence(QKeySequence::Redo));
	editMenu->addAction(redo);
	QMenu * viewMenu = this->menuBar()->addMenu(tr("View"));
	QMenu * cameraMenu=viewMenu->addMenu("Camera Presets");
	cameraMenu->addAction("Isometric",this,SLOT(view_setIsometric()));
	cameraMenu->addAction("View XY Plane",this,SLOT(view_setXY()));
	cameraMenu->addAction("View XZ Plane",this,SLOT(view_setXZ()));
	cameraMenu->addAction("View YZ Plane",this,SLOT(view_setYZ()));
	QMenu * zoomMenu=viewMenu->addMenu("Zoom");
	QActionGroup * zoomGroup=new QActionGroup(NULL);
	zoomGroup->addAction(zoomMenu->addAction("10%",this,SLOT(view_zoom10())))->setCheckable(true);
	zoomGroup->addAction(zoomMenu->addAction("50%",this,SLOT(view_zoom50())))->setCheckable(true);
	zoomGroup->addAction(zoomMenu->addAction("100%",this,SLOT(view_zoom100())))->setCheckable(true);
	zoomGroup->addAction(zoomMenu->addAction("150%",this,SLOT(view_zoom150())))->setCheckable(true);
	zoomGroup->addAction(zoomMenu->addAction("200%",this,SLOT(view_zoom200())))->setCheckable(true);
	view_zoom50();
	viewMenu->addSeparator();
	viewMenu->addAction(databrowser->toggleViewAction());
	viewMenu->addAction(dataeditor->toggleViewAction());
	viewMenu->addAction(simcontrol->toggleViewAction());
	QMenu * simulationMenu = this->menuBar()->addMenu(tr("Simulation"));
	simulationMenu->addAction("Run",simcontrol->getStepEngine(),SLOT(startPull()),QKeySequence("Ctrl+R"));
	simulationMenu->addAction("Pause",simcontrol->getStepEngine(),SLOT(stopPull()),QKeySequence("Ctrl+P"));
	simulationMenu->addAction("Reset to Initial Conditions",databackend->getUndoStack(),SLOT(undo()),QKeySequence("Ctrl+Shift+R"));
	QAction * a=simulationMenu->addAction("Warn Before Clearing Undo Stack");
	a->setCheckable(true);
	a->setChecked(true);
	QObject::connect(a,SIGNAL(toggled(bool)),databackend,SLOT(setWarning(bool)));
	QMenu * dataMenu = this->menuBar()->addMenu(tr("Data"));
	dataMenu->addAction("Clear All Objects",databackend->getDataInserter(),SLOT(clearObjects()));
	dataMenu->addAction("Clear All Forces",databackend->getDataInserter(),SLOT(clearForces()));
	dataMenu->addAction("Clear All Macros",databackend->getDataInserter(),SLOT(clearMacros()));
	dataMenu->addAction("Clear All Constants",databackend->getDataInserter(),SLOT(clearConstants()));
	QMenu * helpMenu = this->menuBar()->addMenu(tr("Help"));
	helpMenu->addAction("Manual",this,SLOT(showManual()));
	helpMenu->addAction("About",this,SLOT(showAbout()));
}