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++; } } }
void Cpu::runProcessor() { unsigned int timer = 0; do { _ir = fetchInstruction(); processInstruction(); timer = checkAndUpdateTimer(timer); } while (endNotReached()); }
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; } } }
/* * 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; }
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)); } }
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); }