示例#1
0
bool DuckCompiler::compile(const QString &code, QByteArray *data)
{
    QStringList lines = code.split(QRegExp("\\n"));
    currentLine = 0;
    int errorCount = 0;
    int processedCount = 0;

    QString prevInstruction;
    QString prevArgument;
    foreach (QString line, lines) {
        currentLine++;
        int defaultDelay = DEFAULT_DELAY;
        int repeat = 0;
        QString cleanLine = line.trimmed();
        if (!cleanLine.isEmpty() && !cleanLine.startsWith("//")) {
            QStringList instructions = cleanLine.split(QRegExp("\\s"));
            const QString &instruction = instructions[0];
            const QString & argument = instructions.length() == 2 ? instructions[1].trimmed() : "";

            if (instruction == "REM") {
                continue;
            }

            bool ok = processInstruction(instruction, argument, data, &repeat, &defaultDelay);

            if (ok) {
                if (repeat > 0 && (prevInstruction.isEmpty() || prevInstruction == "REPEAT" || currentLine == 1)) {
                    emit compileError(currentLine, 0, QString(tr("unable to repeat previous instruction")));
                    errorCount++;
                    continue;
                }

                processedCount++;

                while (ok && repeat > 0) {
                    repeat--;
                    ok = processInstruction(prevInstruction, prevArgument, data);
                }

                prevInstruction = instruction;
                prevArgument = argument;
            } else {
                errorCount++;
            }
        }
    }
示例#2
0
文件: Cpu.cpp 项目: willbush/cpuSim
void Cpu::runProcessor() {
    unsigned int timer = 0;

    do {
        _ir = fetchInstruction();
        processInstruction();
        timer = checkAndUpdateTimer(timer);
    } while (endNotReached());
}
示例#3
0
void ControlUnit::controlUnitBehavior(){
	while(true){
		resetAllLoads();
		//cout<<"\nchecking actual state\n"<<endl;
		switch(state){
			
			/*instruction fetching IR = mem[PC] begin*/
			case 0:
				//AR = PC
				//cout<<"\nfetching new instruction 1.1\n"<<endl;
				loadsARWithPc();
				state ++;
				break;
			case 1:
				//IR = DR
				//cout<<"\nfetching new instruction 1.2\n"<<endl;
				ulaOp = ulaOperation_doNothing;
				ulaInAMuxSel = UlaInputSelection_DR; //DR
				ulaOutDemuxSel = UlaOutputSelection_IR; //IR
				loadRA = 1; //loads RA = DR
				wait(1);
				loadIR = 1; //Loads IR = RA
				wait(1);
				state ++;
				break;
				/*instruction fetching IR = mem[PC] end*/
			case 2:
				/*increment pc PC = PC+1 begin*/
				incrementPC();
				state ++;
				break;
				/*increment pc PC = PC+1 end*/
			case 3:
				//cout<<"\nprocess instruction\n"<<endl;
				if(processInstruction())
					state = 0;
				break;
		}
	}
}
示例#4
0
/*
 * Compute the "liveness" of every register at all GC points.
 */
bool dvmComputeLiveness(VerifierData* vdata)
{
    const InsnFlags* insnFlags = vdata->insnFlags;
    InstructionWidth* backwardWidth;
    VfyBasicBlock* startGuess = NULL;
    BitVector* workBits = NULL;
    bool result = false;

    bool verbose = false; //= dvmWantVerboseVerification(vdata->method);
    if (verbose) {
        const Method* meth = vdata->method;
        ALOGI("Computing liveness for %s.%s:%s",
            meth->clazz->descriptor, meth->name, meth->shorty);
    }

    assert(vdata->registerLines != NULL);

    backwardWidth = createBackwardWidthTable(vdata);
    if (backwardWidth == NULL)
        goto bail;

    /*
     * Allocate space for intra-block work set.  Does not include space
     * for method result "registers", which aren't visible to the GC.
     * (They would be made live by move-result and then die on the
     * instruction immediately before it.)
     */
    workBits = dvmAllocBitVector(vdata->insnRegCount, false);
    if (workBits == NULL)
        goto bail;

    /*
     * We continue until all blocks have been visited, and no block
     * requires further attention ("visited" is set and "changed" is
     * clear).
     *
     * TODO: consider creating a "dense" array of basic blocks to make
     * the walking faster.
     */
    for (int iter = 0;;) {
        VfyBasicBlock* workBlock = NULL;

        if (iter++ > 100000) {
            LOG_VFY_METH(vdata->method, "oh dear");
            dvmAbort();
        }

        /*
         * If a block is marked "changed", we stop and handle it.  If it
         * just hasn't been visited yet, we remember it but keep searching
         * for one that has been changed.
         *
         * The thought here is that this is more likely to let us work
         * from end to start, which reduces the amount of re-evaluation
         * required (both by using "changed" as a work list, and by picking
         * un-visited blocks from the tail end of the method).
         */
        if (startGuess != NULL) {
            assert(startGuess->changed);
            workBlock = startGuess;
        } else {
            for (u4 idx = 0; idx < vdata->insnsSize; idx++) {
                VfyBasicBlock* block = vdata->basicBlocks[idx];
                if (block == NULL)
                    continue;

                if (block->changed) {
                    workBlock = block;
                    break;
                } else if (!block->visited) {
                    workBlock = block;
                }
            }
        }

        if (workBlock == NULL) {
            /* all done */
            break;
        }

        assert(workBlock->changed || !workBlock->visited);
        startGuess = NULL;

        /*
         * Load work bits.  These represent the liveness of registers
         * after the last instruction in the block has finished executing.
         */
        assert(workBlock->liveRegs != NULL);
        dvmCopyBitVector(workBits, workBlock->liveRegs);
        if (verbose) {
            ALOGI("Loaded work bits from last=0x%04x", workBlock->lastAddr);
            dumpLiveState(vdata, 0xfffd, workBlock->liveRegs);
            dumpLiveState(vdata, 0xffff, workBits);
        }

        /*
         * Process a single basic block.
         *
         * If this instruction is a GC point, we want to save the result
         * in the RegisterLine.
         *
         * We don't break basic blocks on every GC point -- in particular,
         * instructions that might throw but have no "try" block don't
         * end a basic block -- so there could be more than one GC point
         * in a given basic block.
         *
         * We could change this, but it turns out to be not all that useful.
         * At first glance it appears that we could share the liveness bit
         * vector between the basic block struct and the register line,
         * but the basic block needs to reflect the state *after* the
         * instruction has finished, while the GC points need to describe
         * the state before the instruction starts.
         */
        u4 curIdx = workBlock->lastAddr;
        while (true) {
            if (!processInstruction(vdata, curIdx, workBits))
                goto bail;

            if (verbose) {
                dumpLiveState(vdata, curIdx + 0x8000, workBits);
            }

            if (dvmInsnIsGcPoint(insnFlags, curIdx)) {
                BitVector* lineBits = vdata->registerLines[curIdx].liveRegs;
                if (lineBits == NULL) {
                    lineBits = vdata->registerLines[curIdx].liveRegs =
                        dvmAllocBitVector(vdata->insnRegCount, false);
                }
                dvmCopyBitVector(lineBits, workBits);
            }

            if (curIdx == workBlock->firstAddr)
                break;
            assert(curIdx >= backwardWidth[curIdx]);
            curIdx -= backwardWidth[curIdx];
        }

        workBlock->visited = true;
        workBlock->changed = false;

        if (verbose) {
            dumpLiveState(vdata, curIdx, workBits);
        }

        /*
         * Merge changes to all predecessors.  If the new bits don't match
         * the old bits, set the "changed" flag.
         */
        PointerSet* preds = workBlock->predecessors;
        size_t numPreds = dvmPointerSetGetCount(preds);
        unsigned int predIdx;

        for (predIdx = 0; predIdx < numPreds; predIdx++) {
            VfyBasicBlock* pred =
                    (VfyBasicBlock*) dvmPointerSetGetEntry(preds, predIdx);

            pred->changed = dvmCheckMergeBitVectors(pred->liveRegs, workBits);
            if (verbose) {
                ALOGI("merging cur=%04x into pred last=%04x (ch=%d)",
                    curIdx, pred->lastAddr, pred->changed);
                dumpLiveState(vdata, 0xfffa, pred->liveRegs);
                dumpLiveState(vdata, 0xfffb, workBits);
            }

            /*
             * We want to set the "changed" flag on unvisited predecessors
             * as a way of guiding the verifier through basic blocks in
             * a reasonable order.  We can't count on variable liveness
             * changing, so we force "changed" to true even if it hasn't.
             */
            if (!pred->visited)
                pred->changed = true;

            /*
             * Keep track of one of the changed blocks so we can start
             * there instead of having to scan through the list.
             */
            if (pred->changed)
                startGuess = pred;
        }
    }

#ifndef NDEBUG
    /*
     * Sanity check: verify that all GC point register lines have a
     * liveness bit vector allocated.  Also, we're not expecting non-GC
     * points to have them.
     */
    u4 checkIdx;
    for (checkIdx = 0; checkIdx < vdata->insnsSize; ) {
        if (dvmInsnIsGcPoint(insnFlags, checkIdx)) {
            if (vdata->registerLines[checkIdx].liveRegs == NULL) {
                LOG_VFY_METH(vdata->method,
                    "GLITCH: no liveRegs for GC point 0x%04x", checkIdx);
                dvmAbort();
            }
        } else if (vdata->registerLines[checkIdx].liveRegs != NULL) {
            LOG_VFY_METH(vdata->method,
                "GLITCH: liveRegs for non-GC point 0x%04x", checkIdx);
            dvmAbort();
        }
        u4 insnWidth = dvmInsnGetWidth(insnFlags, checkIdx);
        checkIdx += insnWidth;
    }
#endif

    /*
     * Factor in the debug info, if any.
     */
    if (!markDebugLocals(vdata))
        goto bail;

    result = true;

bail:
    free(backwardWidth);
    dvmFreeBitVector(workBits);
    return result;
}
示例#5
0
void MemMap::optimizeMemoryAccesses(Trace* trace) {
  StoreList tracking;

  for (IRInstruction* inst : trace->getInstructionList()) {
    // initialize each instruction as live
    inst->setId(LIVE);

    int offset = -1;
    Opcode op = inst->getOpcode();

    if (isLoad(op)) {
      if (op == LdProp) {
        offset = inst->getSrc(1)->getConstValAsInt();
      }

      optimizeLoad(inst, offset);
    } else if (isStore(op)) {
      if (op == StProp || op == StPropNT) {
        offset = inst->getSrc(1)->getConstValAsInt();
      }

      // if we see a store, first check if its last available access is a store
      // if it is, then the last access is a dead store
      IRInstruction* access = getLastAccess(inst->getSrc(0), offset);
      if (access != NULL && isStore(access->getOpcode())) {
        // if a dead St* is followed by a St*NT, then the second store needs to
        // now write in the type because the first store will be removed
        if (access->getOpcode() == StProp && op == StPropNT) {
          inst->setOpcode(StProp);
        } else if (access->getOpcode() == StLoc && op == StLocNT) {
          inst->setOpcode(StLoc);
        } else if (access->getOpcode() == StRef && op == StRefNT) {
          inst->setOpcode(StRef);
        }

        access->setId(DEAD);
      }

      // start tracking the current store
      tracking.push_back(std::make_pair(inst, std::vector<IRInstruction*>()));
    } else if (inst->mayRaiseError()) {
      // if the function has an exit edge that we don't know anything about
      // (raising an error), then all stores we're currently tracking need to
      // be erased. all stores already declared dead are untouched
      StoreList::iterator it, end;
      for (it = tracking.begin(), end = tracking.end(); it != end; ) {
        StoreList::iterator copy = it;
        ++it;
        if (copy->first->getId() != DEAD) {
          // XXX: t1779667
          tracking.erase(copy);
        }
      }
    }

    // if the current instruction is guarded, make sure all of our stores that
    // are not yet dead know about it
    if (inst->getLabel() != NULL) {
      for (auto& entry : tracking) {
        if (entry.first->getId() != DEAD) {
          entry.second.push_back(inst);
        }
      }
    }

    Simplifier::copyProp(inst);
    processInstruction(inst);
  }

  sinkStores(tracking);

  // kill the dead stores
  removeDeadInstructions(trace);
}
void SimulationManager::simulate() {
	Instruction instructionIn;
	Instruction instructionOut;
	//TODO: create FPS manager.
	Uint32 milisecondsTonextFrame = 1000/DESIREDFPS; 
	Uint32 frameStartedAt = 0;
	this->lastBroadcast = "";
	
	unsigned int i = 0;

	while(!this->isStopping()) {
		frameStartedAt = SDL_GetTicks();

		this->getInstructionQueue().lock();
		while (this->getInstructionQueue().getInstructionQueue().size() != 0) {
			instructionIn = this->getInstructionQueue().getInstructionQueue().front();
			processInstruction(instructionIn);
			this->getInstructionQueue().getInstructionQueue().pop();
		}
		this->getInstructionQueue().unLock();

		// AVANZO LA SIMULACIÓN UN DELTA DE TIEMPO.
		GameView::instance().update();

		// HACER UN BROADCAST DEL UPDATE A LOS CLIENTES
		if (GameView::instance().numberOfLoggedInPlayers() > 0) {
			instructionOut.clear();
			instructionOut.setOpCode(OPCODE_SIMULATION_UPDATE);
			std::string argument = GameView::instance().managePlayersUpdate();
			std::string itemsUpdate=GameView::instance().getWorldView()->manageItemsUpdate();
			std::string eventsUpdate=GameView::instance().manageEventsUpdate();
			std::string missionUpdate = GameView::instance().getMission()->manageMissionChange();
			bool send=false;
			if (argument.size() > 0 ) {
				//Logger::instance().log("Argument "+argument);
				if (this->lastBroadcast != argument){
					this->lastBroadcast = argument;
					//argument.append(":");
					//argument.append(stringUtilities::unsignedToString(static_cast<unsigned>(SDL_GetTicks())));
					instructionOut.insertArgument(INSTRUCTION_ARGUMENT_KEY_SIMULATION_UPDATE, argument);
					argument = stringUtilities::unsignedToString(static_cast<unsigned>(SDL_GetTicks()));
					//LOG_DEBUG("SIMULATION GENERATED AT: " + argument);
					instructionOut.insertArgument(INSTRUCTION_ARGUMENT_KEY_CONNECTED_AT, argument);
					send=true;
				}
			if(itemsUpdate.size()>0)
				{
					instructionOut.insertArgument(INSTRUCTION_ARGUMENT_KEY_ITEM_UPDATE,itemsUpdate);
					send=true;
				}
			}
			if(eventsUpdate.size()>0)
			{
					instructionOut.insertArgument(INSTRUCTION_ARGUMENT_KEY_EVENT_UPDATE,eventsUpdate);
					send=true;
			}
			if (missionUpdate.size() > 0) {
				instructionOut.insertArgument(INSTRUCTION_ARGUMENT_KEY_MISSION_UPDATE, missionUpdate);
				send = true;
			}
			if(send)
				this->getClients().addBroadcast(instructionOut);
			i++;
		}

		if (milisecondsTonextFrame >= SDL_GetTicks() - frameStartedAt)
			SDL_Delay(milisecondsTonextFrame - (SDL_GetTicks() - frameStartedAt));
	}
}
示例#7
0
void MemMap::optimizeMemoryAccesses(Trace* trace) {
  if (hasInternalFlow(trace)) {
    // This algorithm only works with linear traces.
    // TODO t2066994: reset state after each block, at least.
    return;
  }
  StoreList tracking;

  const Func* curFunc = nullptr;

  for (Block* block : trace->getBlocks()) {
    for (IRInstruction& inst : *block) {
      if (inst.getOpcode() == Marker) {
        curFunc = inst.getExtra<Marker>()->func;
      }
      // initialize each instruction as live
      setLive(inst, true);

      int offset = -1;
      Opcode op = inst.getOpcode();

      if (isLoad(op)) {
        if (op == LdProp) {
          offset = inst.getSrc(1)->getValInt();
        }
        // initialize each instruction as live
        setLive(inst, true);

        optimizeLoad(&inst, offset);
      } else if (isStore(op)) {
        if (op == StProp || op == StPropNT) {
          offset = inst.getSrc(1)->getValInt();
        }

        // if we see a store, first check if its last available access is a store
        // if it is, then the last access is a dead store
        auto access = inst.getOpcode() == StLoc || inst.getOpcode() == StLocNT
          ? lastLocalAccess(inst.getExtra<LocalId>()->locId)
          : getLastAccess(inst.getSrc(0), offset);
        if (access && isStore(access->getOpcode())) {
          // if a dead St* is followed by a St*NT, then the second store needs to
          // now write in the type because the first store will be removed
          if (access->getOpcode() == StProp && op == StPropNT) {
            inst.setOpcode(StProp);
          } else if (access->getOpcode() == StLoc && op == StLocNT) {
            inst.setOpcode(StLoc);
          } else if (access->getOpcode() == StRef && op == StRefNT) {
            inst.setOpcode(StRef);
          }

          setLive(*access, false);
        }

        // start tracking the current store
        tracking.push_back(std::make_pair(&inst, std::vector<IRInstruction*>()));
      } else if (inst.mayRaiseError()) {
        // if the function has an exit edge that we don't know anything about
        // (raising an error), then all stores we're currently tracking need to
        // be erased. all stores already declared dead are untouched
        StoreList::iterator it, end;
        for (it = tracking.begin(), end = tracking.end(); it != end; ) {
          StoreList::iterator copy = it;
          ++it;
          if (isLive(copy->first)) {
            // XXX: t1779667
            tracking.erase(copy);
          }
        }
      }

      // if the current instruction is guarded, make sure all of our stores that
      // are not yet dead know about it
      if (inst.getTaken()) {
        for (auto& entry : tracking) {
          if (isLive(entry.first)) {
            entry.second.push_back(&inst);
          }
        }
      }
      Simplifier::copyProp(&inst);
      processInstruction(&inst, curFunc && curFunc->isPseudoMain());
    }
  }

  sinkStores(tracking);

  // kill the dead stores
  removeDeadInstructions(trace, m_liveInsts);
}