void Vxls::allocate(Interval* current) { PhysReg::Map<unsigned> free_until; // 0 by default RegSet allow; unsigned conflict = constrain(current, allow); allow.forEach([&](PhysReg r) { free_until[r] = conflict; }); for (auto ivl : active) { free_until[ivl->reg] = 0; } for (auto ivl : inactive) { auto until = current->nextIntersect(ivl); free_until[ivl->reg] = std::min(until, free_until[ivl->reg]); } auto r = find(free_until); auto pos = free_until[r]; if (pos >= current->end()) { return assignReg(current, r); } if (pos > current->start()) { // r is free for the first part of current auto prev_use = current->lastUseBefore(pos); auto min_split = std::max(prev_use, current->start() + 1); auto max_split = pos; assert(min_split <= max_split); auto split_pos = std::max(min_split, max_split); // todo: find good spot split_pos = nearestSplitBefore(split_pos); if (split_pos > current->start()) { auto second = current->split(split_pos, true); pending.push(second); return assignReg(current, r); } } // must spill current or another victim allocBlocked(current); }
/*always put first var at RSI,second var at RDI,please note the order of parameters for cmp instruction*/ void genCMP(uint32_t op) { FreeReg(REG_RDI); assignReg(REG_RDI); FreeReg(REG_RSI); assignReg(REG_RSI); asmPrintf_func(" cmpq %%rdi,%%rsi\n"); FreeReg(REG_RDI); FreeReg(REG_RSI); operand_push(NULL, NOT_SPECIFIED); opTop->tk_code = op; }
static void genADD_rax(uint32_t op, uint32_t mode) { char instr[5]; uint32_t reg; switch (op) { case tk_PLUS: strcpy(instr, "addq"); break; case tk_MINUS: strcpy(instr, "subq"); break; default: interERROR("ADD type instruction generating error!"); break; } if (mode == RET_AT_TOP) { operand_pop(); } reg = FindFreeReg(); assignReg(reg); asmPrintf_func(" %s %%%s, %%%s\n", instr, reg_pool[reg].reg_name, reg_pool[REG_RAX].reg_name);/*store to second reg*/ if (mode == RET_AT_SECOND) { operand_pop(); } setReg_Return(REG_RAX); setReg_Unused(reg); operand_push(&ret_sym, NOT_SPECIFIED); }
void AnalogToDigitalConverter::begin(byte analogReference) { assignReg(ADMUX,(1<<REFS0),analogReference); clearAndSetReg(ADCSRA,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0),biggestBit(F_CPU/MAX_ADC_CLOCK)<<ADPS0); // Set the fastest clock possible resume(); sample(0); // Throw away the first sample because its bad. }
static void genMUL_rax(uint32_t op, uint32_t mode) { char instr[6]; uint32_t reg; if (mode == RET_AT_TOP) { operand_pop(); } switch (op) { case tk_STAR: strcpy(instr, "imulq"); reg = FindFreeReg(); assignReg(reg); asmPrintf_func(" %s %%%s, %%%s\n", instr, reg_pool[reg].reg_name, reg_pool[REG_RAX].reg_name);/*store to second reg*/ if (mode == RET_AT_SECOND) { operand_pop(); } setReg_Return(REG_RAX); setReg_Unused(reg); break; case tk_DIVIDE: case tk_MOD: strcpy(instr, "idivq"); FreeReg(REG_RCX); assignReg(REG_RCX); FreeReg(REG_RAX); assignReg(REG_RAX); asmPrintf_func(" cqo\n");/*negative idiv : http://stackoverflow.com/questions/10343155/x86-assembly-handling-the-idiv-instruction*/ asmPrintf_func(" %s %%%s\n", instr, reg_pool[REG_RCX].reg_name); /*quotient:rax , remainder:rdx*/ if (op == tk_MOD) { instrMOV_REG_REG(BYTE_8, reg_pool[REG_RDX].reg_name, reg_pool[REG_RAX].reg_name); } setReg_Return(REG_RAX); setReg_Unused(REG_RDX); setReg_Unused(REG_RCX); break; default: interERROR("MUL type instruction generating error!"); break; } operand_push(&ret_sym, NOT_SPECIFIED); }
uint16_t AnalogToDigitalConverter::sample(byte channel) { //while(getReg(ADCSRA,(1<<ADSC))); // Wait for prior sample clearAndSetReg(ADMUX,AnalogMuxMask,channel); assignReg(ADCSRA,(1<<ADSC),1); while(getReg(ADCSRA,(1<<ADSC))); // Wait for prior sample uint16_t result = ADCL; result = result | (((uint16_t)(ADCH))<<8); return result; }
// When all registers are in use, find a good interval to split and spill, // which could be the current interval. When an interval is split and the // second part is spilled, possibly split the second part again before the // next use-pos that requires a register, and enqueue the third part. void Vxls::allocBlocked(Interval* current) { PhysReg::Map<unsigned> used, blocked; RegSet allow; unsigned conflict = constrain(current, allow); // repeated from allocate allow.forEach([&](PhysReg r) { used[r] = blocked[r] = conflict; }); auto const cur_start = current->start(); // compute next use of active registers, so we can pick the furthest one for (auto ivl : active) { if (ivl->fixed()) { blocked[ivl->reg] = used[ivl->reg] = 0; } else { auto use_pos = ivl->firstUseAfter(cur_start); used[ivl->reg] = std::min(use_pos, used[ivl->reg]); } } // compute next intersection/use of inactive regs to find whats free longest for (auto ivl : inactive) { auto intersect_pos = current->nextIntersect(ivl); if (intersect_pos == kMaxPos) continue; if (ivl->fixed()) { blocked[ivl->reg] = std::min(intersect_pos, blocked[ivl->reg]); used[ivl->reg] = std::min(blocked[ivl->reg], used[ivl->reg]); } else { auto use_pos = ivl->firstUseAfter(cur_start); used[ivl->reg] = std::min(use_pos, used[ivl->reg]); } } // choose the best victim register(s) to spill auto r = find(used); auto used_pos = used[r]; if (used_pos < current->firstUse()) { // all other intervals are used before current's first register-use return spill(current); } auto block_pos = blocked[r]; if (block_pos < current->end()) { auto prev_use = current->lastUseBefore(block_pos); auto min_split = std::max(prev_use, cur_start + 1); auto max_split = block_pos; assert(cur_start < min_split && min_split <= max_split); auto split_pos = std::max(min_split, max_split); split_pos = nearestSplitBefore(split_pos); if (split_pos > current->start()) { auto second = current->split(split_pos, true); pending.push(second); } } spillOthers(current, r); assignReg(current, r); }
void Vxls::walkIntervals() { for (auto ivl : intervals) { if (!ivl) continue; if (ivl->fixed()) { assignReg(ivl, ivl->vreg); } else if (ivl->cns) { spill(ivl); } else { pending.push(ivl); } } while (!pending.empty()) { auto current = pending.top(); pending.pop(); update(current->start()); allocate(current); } }
void AnalogToDigitalConverter::resume() { assignReg(ADCSRA,(1<<ADEN),1); // turn on power }
void AnalogToDigitalConverter::pause() { assignReg(ADCSRA,(1<<ADEN),0); // turn on power }
void AnalogComparator::resume() { assignReg(ACSR,(1<<ACIE) | (1<<ACD),1); // Turn on the interrupt and power }
void AnalogComparator::pause() { assignReg(ACSR,(1<<ACIE) | (1<<ACD),0); // Turn off the interrupt and power }