bool ZMProcessor::executeVariableInstruction() { uint8_t inst = _memory[_pc]; uint8_t opCode = inst & 0x1f; // opcode is bottom five bits int operands = (inst & 0x20) ? -1 : 2; uint8_t operandTypeFields = _memory[_pc + 1]; int operandFieldCount; _operandOffset = 2; _operandTypes[0] = operandType(operandTypeFields >> 6); _operandTypes[1] = operandType(operandTypeFields >> 4); _operandTypes[2] = operandType(operandTypeFields >> 2); _operandTypes[3] = operandType(operandTypeFields); if (operands == 2) { _instructionLength = 2; operandFieldCount = 4; } else if (_version >= 4 && (opCode == 0x0c || opCode == 0x1a)) { _instructionLength = 3; operandFieldCount = 8; operandTypeFields = _memory[_pc + 2]; _operandTypes[4] = operandType(operandTypeFields >> 6); _operandTypes[5] = operandType(operandTypeFields >> 4); _operandTypes[6] = operandType(operandTypeFields >> 2); _operandTypes[7] = operandType(operandTypeFields); }
static int pattern1 (iCode *sic) { /* this is what we do. look for sequences like iTempX := _SOME_POINTER_; iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next _SOME_POINTER_ := iTempY; sic->next->next either iTempZ := @[iTempX]; sic->next->next->next or *(iTempX) := ..something.. sic->next->next->next if we find this then transform this to iTempX := _SOME_POINTER_; either iTempZ := @[iTempX]; or *(iTempX) := ..something.. iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) _SOME_POINTER_ := iTempY; */ /* sounds simple enough so let's start , here I use negative tests all the way to return if any test fails */ iCode *pgs, *sh, *st; if (!(sic->next && sic->next->next && sic->next->next->next)) return 0; if (sic->next->op != '+' && sic->next->op != '-') return 0; if (!(sic->next->next->op == '=' && !POINTER_SET (sic->next->next))) return 0; if (!isOperandEqual (IC_LEFT (sic->next), IC_RIGHT (sic)) || !IS_OP_LITERAL (IC_RIGHT (sic->next))) return 0; if (operandLitValue (IC_RIGHT (sic->next)) != getSize (operandType (IC_RIGHT (sic))->next)) return 0; if (!isOperandEqual (IC_RESULT (sic->next->next), IC_RIGHT (sic))) return 0; if (!isOperandEqual (IC_RESULT (sic->next), IC_RIGHT (sic->next->next))) return 0; if (!(pgs = findPointerGetSet (sic->next->next, IC_RESULT (sic)))) return 0; /* found the pattern .. now do the transformation */ sh = sic->next; st = sic->next->next; /* take the two out of the chain */ sic->next = st->next; st->next->prev = sic; /* and put them after the pointer get/set icode */ if ((st->next = pgs->next)) st->next->prev = st; pgs->next = sh; sh->prev = pgs; return 1; }
static int pattern2 (iCode *sic) { /* this is what we do. look for sequences like iTempX := _SOME_POINTER_; iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next iTempK := iTempY; sic->next->next _SOME_POINTER_ := iTempK; sic->next->next->next either iTempZ := @[iTempX]; sic->next->next->next->next or *(iTempX) := ..something.. sic->next->next->next->next if we find this then transform this to iTempX := _SOME_POINTER_; either iTempZ := @[iTempX]; or *(iTempX) := ..something.. iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) iTempK := iTempY; _SOME_POINTER_ := iTempK; */ /* sounds simple enough so let's start , here I use negative tests all the way to return if any test fails */ iCode *pgs, *sh, *st; if (!(sic->next && sic->next->next && sic->next->next->next && sic->next->next->next->next)) return 0; /* yes I can OR them together and make one large if... but I have simple mind and like to keep things simple & readable */ if (!(sic->next->op == '+' || sic->next->op == '-')) return 0; if (!isOperandEqual(IC_RIGHT(sic),IC_LEFT(sic->next))) return 0; if (!IS_OP_LITERAL (IC_RIGHT (sic->next))) return 0; if (operandLitValue (IC_RIGHT (sic->next)) != getSize (operandType (IC_RIGHT (sic))->next)) return 0; if (!IS_ASSIGN_ICODE(sic->next->next)) return 0; if (!isOperandEqual(IC_RIGHT(sic->next->next),IC_RESULT(sic->next))) return 0; if (!IS_ASSIGN_ICODE(sic->next->next->next)) return 0; if (!isOperandEqual(IC_RIGHT(sic->next->next->next),IC_RESULT(sic->next->next))) return 0; if (!isOperandEqual(IC_RESULT(sic->next->next->next),IC_LEFT(sic->next))) return 0; if (!(pgs = findPointerGetSet (sic->next->next->next, IC_RESULT (sic)))) return 0; /* found the pattern .. now do the transformation */ sh = sic->next; st = sic->next->next->next; /* take the three out of the chain */ sic->next = st->next; st->next->prev = sic; /* and put them after the pointer get/set icode */ if ((st->next = pgs->next)) st->next->prev = st; pgs->next = sh; sh->prev = pgs; return 1; }
bool ZMProcessor::executeExtendedInstruction() { uint8_t inst = _memory[_pc + 1]; uint8_t opCode = inst & 0x1f; // opcode is bottom five bits int operands = (inst & 0x20) ? -1 : 2; uint8_t operandTypeFields = _memory[_pc + 2]; int operandFieldCount; _operandOffset = 3; _operandTypes[0] = operandType(operandTypeFields >> 6); _operandTypes[1] = operandType(operandTypeFields >> 4); _operandTypes[2] = operandType(operandTypeFields >> 2); _operandTypes[3] = operandType(operandTypeFields); if (operands == 2) { _instructionLength = 3; operandFieldCount = 4; } else { _instructionLength = 3; operandFieldCount = 4; _operandTypes[4] = kOmitted; _operandTypes[5] = kOmitted; _operandTypes[6] = kOmitted; _operandTypes[7] = kOmitted; } _operandCount = 0; for (int i = 0; i < operandFieldCount; ++i) { if (_operandTypes[i] == kOmitted) break; else if (_operandTypes[i] == kLargeConstant) { _operands[_operandCount] = ZMMemory::readWordFromData(_memory.getData() + _pc + _instructionLength); _instructionLength += 2; } else if (_operandTypes[i] == kSmallConstant) { _operands[_operandCount] = _memory[_pc + _instructionLength]; ++_instructionLength; } else if (_operandTypes[i] == kVariable) { _operands[_operandCount] = getVariable(_memory[_pc + _instructionLength]); _operandVariables[_operandCount] = _memory[_pc + _instructionLength]; ++_instructionLength; } ++_operandCount; } return dispatchEXT(opCode); }
/* * Calculates command size in bytes assuming labels are numbers (32bit) * return command_size_in_bytes */ int calculateCommandSizeInBytes(tLine command_text) { char cmd_name[MAX_COMMAND_LENGTH]; sscanf(command_text.str, "%s", cmd_name); tCommand cmd = parseCommand(cmd_name); tCommandWithOperands command_with_operands = {cmd, {0, 0}, {0, 0}}; int operands_number = getOperandsNumberForCommandType(cmd.type); if (operands_number == 0) { //just do nothing } else if (operands_number == 1) { char operand_name[MAX_OPERAND_LEXEM_LENGTH]; sscanf(command_text.str, "%s %s", cmd_name, operand_name); command_with_operands.left.type = operandType(operand_name); } else if (operands_number == 2) { char operand1_name[MAX_OPERAND_LEXEM_LENGTH], operand2_name[MAX_OPERAND_LEXEM_LENGTH]; *strchr(command_text.str, ',') = ' '; //FIXME: HARDCORE in source code... sscanf(command_text.str, "%s %s %s", cmd_name, operand1_name, operand2_name); command_with_operands.left.type = operandType(operand1_name); command_with_operands.right.type = operandType(operand2_name); } else //exception { printf("Wrong number of operands!!!\n"); exit(-1); } tCode code = makeCodeFromCommandWithOperands(command_with_operands); int command_size_in_bytes = codeSize(code); free(code.words); return command_size_in_bytes; }
/*-----------------------------------------------------------------*/ static bool canOverlayLocals (eBBlock ** ebbs, int count) { int i; /* if staticAuto is in effect or the current function being compiled is reentrant or the overlay segment is empty or no overlay option is in effect then */ if (options.noOverlay || options.stackAuto || (currFunc && (IFFUNC_ISREENT (currFunc->type) || FUNC_ISISR (currFunc->type))) || elementsInSet (overlay->syms) == 0) { return FALSE; } /* if this is a forces overlay */ if (IFFUNC_ISOVERLAY(currFunc->type)) return TRUE; /* otherwise do thru the blocks and see if there any function calls if found then return false */ for (i = 0; i < count; i++) { iCode *ic; for (ic = ebbs[i]->sch; ic; ic = ic->next) if (ic) { if (ic->op == CALL) { sym_link *ftype = operandType(IC_LEFT(ic)); /* builtins only can use overlays */ if (!IFFUNC_ISBUILTIN(ftype)) return FALSE; } else if (ic->op == PCALL) { return FALSE; } } } /* no function calls found return TRUE */ return TRUE; }
/* Do CSE estimation */ static bool cseCostEstimation (iCode *ic, iCode *pdic) { operand *result = IC_RESULT(ic); sym_link *result_type = operandType(result); /* if it is a pointer then return ok for now */ if (IC_RESULT(ic) && IS_PTR(result_type)) return 1; /* if bitwise | add & subtract then no since xa51 is pretty good at it so we will cse only if they are local (i.e. both ic & pdic belong to the same basic block */ if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') { /* then if they are the same Basic block then ok */ if (ic->eBBlockNum == pdic->eBBlockNum) return 1; else return 0; } /* for others it is cheaper to do the cse */ return 1; }
static int implement_lospre_assignment(const assignment_lospre a, T_t &T, G_t &G, const iCode *ic) // Assignment has to be passed as a copy (not reference), since the transformations on the tree-decomposition will invalidate it otherwise. { operand *tmpop; unsigned substituted = 0, split = 0; typedef typename boost::graph_traits<G_t>::edge_iterator edge_iter_t; typedef typename boost::graph_traits<G_t>::edge_descriptor edge_desc_t; std::set<edge_desc_t> calculation_edges; // Use descriptor, not iterator due to possible invalidation of iterators when inserting vertices or edges. edge_iter_t e, e_end; for(boost::tie(e, e_end) = boost::edges(G); e != e_end; ++e) if(!((a.global[boost::source(*e, G)] & true) && !G[boost::source(*e, G)].invalidates) && (a.global[boost::target(*e, G)] & true)) calculation_edges.insert(*e); if(!calculation_edges.size()) return(0); #ifdef DEBUG_LOSPRE std::cout << "Optimizing at " << ic->key << "\n"; std::cout.flush(); #endif tmpop = newiTempOperand (operandType (IC_RESULT (ic)), TRUE); tmpop->isvolatile = false; #ifdef DEBUG_LOSPRE std::cout << "New tmpop: " << OP_SYMBOL_CONST(tmpop)->name << " "; printTypeChain(operandType (IC_RESULT(ic)), stdout); std::cout << "\n"; #endif for(typename std::set<edge_desc_t>::iterator i = calculation_edges.begin(); i != calculation_edges.end(); ++i) { split_edge(T, G, *i, ic, tmpop); split++; } typedef typename boost::graph_traits<G_t>::vertex_iterator vertex_iter_t; vertex_iter_t v, v_end; for(boost::tie(v, v_end) = boost::vertices(G); v != v_end; ++v) { if(!G[*v].uses) continue; typename boost::graph_traits<G_t>::in_edge_iterator e = in_edges(*v, G).first; if (a.global.size() <= *v) continue; if(!((a.global[*v] & true) && !G[*v].invalidates || boost::source(*e, G) < a.global.size() && (a.global[boost::source(*e, G)] & true))) continue; #ifdef DEBUG_LOSPRE std::cout << "Substituting ic " << G[*v].ic->key << "\n"; #endif substituted++; iCode *ic = G[*v].ic; //if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic))) // bitVectUnSetBit (OP_SYMBOL (IC_LEFT (ic))->uses, ic->key); //if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic))) // bitVectUnSetBit (OP_SYMBOL (IC_RIGHT (ic))->uses, ic->key); IC_RIGHT(ic) = tmpop; //bitVectSetBit (OP_SYMBOL (IC_RIGHT(ic))->uses, ic->key); if (!POINTER_SET (ic)) { IC_LEFT(ic) = 0; ic->op = '='; IC_RESULT(ic) = operandFromOperand (IC_RESULT (ic)); IC_RESULT(ic)->isaddr = 0; } if(IS_OP_VOLATILE(IC_RESULT (ic))) continue; { typedef typename boost::graph_traits<G_t>::adjacency_iterator adjacency_iter_t; adjacency_iter_t c, c_end; boost::tie(c, c_end) = adjacent_vertices(*v, G); if (c != c_end) forward_lospre_assignment(G, *c, ic, a); } } if(substituted <= 0) { std::cerr << "Introduced " << OP_SYMBOL_CONST(tmpop)->name << ", but did not substitute any calculations.\n"; return (-1); } if(substituted < split) // Todo: Remove this warning when optimization for speed instead of code size is implemented! std::cout << "Introduced " << OP_SYMBOL_CONST(tmpop)->name << ", but did substitute only " << substituted << " calculations, while introducing "<< split << ".\n"; std::cout.flush(); return(1); }
static void forward_lospre_assignment(G_t &G, typename boost::graph_traits<G_t>::vertex_descriptor i, const iCode *ic, const assignment_lospre& a) { typedef typename boost::graph_traits<G_t>::adjacency_iterator adjacency_iter_t; adjacency_iter_t c, c_end; operand *tmpop = IC_RIGHT(ic); const std::pair<int, int> forward(IC_RESULT(ic)->key, IC_RIGHT(ic)->key); for(;;) { if (G[i].forward == forward) break; // Was here before. iCode *nic = G[i].ic; if (isOperandEqual(IC_RESULT(ic), IC_LEFT(nic)) && nic->op != ADDRESS_OF && (!POINTER_GET(nic) || !IS_PTR(operandType(IC_RESULT(nic))) || !IS_BITFIELD(operandType(IC_LEFT(nic))->next) || compareType(operandType(IC_LEFT(nic)), operandType(tmpop)) == 1)) { bool isaddr = IC_LEFT (nic)->isaddr; #ifdef DEBUG_LOSPRE std::cout << "Forward substituted left operand " << OP_SYMBOL_CONST(IC_LEFT(nic))->name << " at " << nic->key << "\n"; #endif //bitVectUnSetBit (OP_SYMBOL (IC_LEFT (nic))->uses, nic->key); IC_LEFT(nic) = operandFromOperand (tmpop); //bitVectSetBit (OP_SYMBOL (IC_LEFT (nic))->uses, nic->key); IC_LEFT (nic)->isaddr = isaddr; } if (isOperandEqual(IC_RESULT(ic), IC_RIGHT(nic))) { #ifdef DEBUG_LOSPRE std::cout << "Forward substituted right operand " << OP_SYMBOL_CONST(IC_RIGHT(nic))->name << " at " << nic->key << "\n"; #endif //bitVectUnSetBit (OP_SYMBOL (IC_RIGHT (nic))->uses, nic->key); IC_RIGHT(nic) = operandFromOperand (tmpop); //bitVectSetBit (OP_SYMBOL (IC_RIGHT (nic))->uses, nic->key); } if (POINTER_SET(nic) && isOperandEqual(IC_RESULT(ic), IC_RESULT(nic)) && (!IS_PTR(operandType(IC_RESULT(nic))) || !IS_BITFIELD(operandType(IC_RESULT(nic))->next) || compareType(operandType(IC_RESULT(nic)), operandType(tmpop)) == 1)) { #ifdef DEBUG_LOSPRE std::cout << "Forward substituted result operand " << OP_SYMBOL_CONST(IC_RESULT(nic))->name << " at " << nic->key << "\n"; #endif //bitVectUnSetBit (OP_SYMBOL (IC_RESULT (nic))->uses, nic->key); IC_RESULT(nic) = operandFromOperand (tmpop); IC_RESULT(nic)->isaddr = true; //bitVectSetBit (OP_SYMBOL (IC_RESULT (nic))->uses, nic->key); } if (nic->op == LABEL) // Reached label. Continue only if all edges goining here are safe. { typedef typename boost::graph_traits<G_t>::in_edge_iterator in_edge_iter_t; in_edge_iter_t e, e_end; for (boost::tie(e, e_end) = boost::in_edges(i, G); e != e_end; ++e) if (G[boost::source(*e, G)].forward != forward) break; if(e != e_end) break; } if (isOperandEqual(IC_RESULT (ic), IC_RESULT(nic)) && !POINTER_SET(nic) /*|| G[i].uses*/) break; if ((nic->op == CALL || nic->op == PCALL || POINTER_SET(nic)) && IS_TRUE_SYMOP(IC_RESULT(ic))) break; G[i].forward = forward; if (nic->op == GOTO || nic->op == IFX || nic->op == JUMPTABLE) { adjacency_iter_t c, c_end; for(boost::tie(c, c_end) = boost::adjacent_vertices(i, G); c != c_end; ++c) { if(!((a.global[i] & true) && !G[i].invalidates) && (a.global[*c] & true)) // Calculation edge continue; forward_lospre_assignment(G, *c, ic, a); } break; } boost::tie(c, c_end) = adjacent_vertices(i, G); if(c == c_end) break; if(!((a.global[i] & true) && !G[i].invalidates) && (a.global[*c] & true)) // Calculation edge break; i = *c; } }
/*-----------------------------------------------------------------*/ static void convertToFcall (eBBlock ** ebbs, int count) { int i; /* for all blocks do */ for (i = 0; i < count; i++) { iCode *ic; /* for all instructions in the block do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { /* floating point operations are converted to function calls */ if ((IS_CONDITIONAL (ic) || IS_ARITHMETIC_OP (ic)) && (IS_FLOAT (operandType (IC_RIGHT (ic))))) { cnvToFcall (ic, ebbs[i]); } /* casting is a little different */ if (ic->op == CAST) { if (IS_FLOAT (operandType (IC_RIGHT (ic)))) cnvFromFloatCast (ic, ebbs[i]); else if (IS_FLOAT (operandType (IC_LEFT (ic)))) cnvToFloatCast (ic, ebbs[i]); } /* if long / int mult or divide or mod */ if (ic->op == '*' || ic->op == '/' || ic->op == '%') { sym_link *leftType = operandType (IC_LEFT (ic)); if (IS_INTEGRAL (leftType) && getSize (leftType) > port->support.muldiv) { sym_link *rightType = operandType (IC_RIGHT (ic)); if (port->hasNativeMulFor != NULL && port->hasNativeMulFor (ic, leftType, rightType)) { /* Leave as native */ } else { convilong (ic, ebbs[i], leftType, ic->op); } } } if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP) { sym_link *type = operandType (IC_LEFT (ic)); if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0) { convilong (ic, ebbs[i], type, ic->op); } } } } }
/*-----------------------------------------------------------------*/ static void convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) { symbol *func = NULL; iCode *ip = ic->next; iCode *newic; int lineno = ic->lineno; int bwd; int su; int bytesPushed=0; remiCodeFromeBBlock (ebp, ic); /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { if (compareType (type, __multypes[bwd][su]) == 1) { if (op == '*') func = __muldiv[0][bwd][su]; else if (op == '/') func = __muldiv[1][bwd][su]; else if (op == '%') func = __muldiv[2][bwd][su]; else if (op == RRC) func = __rlrr[1][bwd][su]; else if (op == RLC) func = __rlrr[0][bwd][su]; else if (op == RIGHT_OP) func = __rlrr[1][bwd][su]; else if (op == LEFT_OP) func = __rlrr[0][bwd][su]; else assert (0); goto found; } } } assert (0); found: /* if int & long support routines NOT compiled as reentrant */ if (!options.intlong_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_LEFT (ic), NULL); else { newic = newiCode ('=', NULL, IC_LEFT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* compiled as reentrant then push */ /* push right */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, IC_RIGHT (ic), NULL); } else { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* insert push left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode (IPUSH, IC_LEFT (ic), NULL); newic->parmPush = 1; bytesPushed += getSize(operandType(IC_LEFT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* for the result */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; // to clear the stack after the call addiCodeToeBBlock (ebp, newic, ip); }
/*-----------------------------------------------------------------*/ static void cnvFromFloatCast (iCode * ic, eBBlock * ebp) { iCode *ip, *newic; symbol *func; sym_link *type = operandType (IC_LEFT (ic)); int lineno = ic->lineno; int bwd, su; ip = ic->next; /* remove it from the iCode */ remiCodeFromeBBlock (ebp, ic); /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { if (compareType (type, __multypes[bwd][su]) == 1) { func = __conv[1][bwd][su]; goto found; } } } assert (0); found: /* if float support routines NOT compiled as reentrant */ if (!options.float_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* push the left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; }
/** Mark variables for assignment by the register allocator. */ static void serialRegMark (eBBlock ** ebbs, int count) { int i; short int max_alloc_bytes = SHRT_MAX; // Byte limit. Set this to a low value to pass only few variables to the register allocator. This can be useful for debugging. stm8_call_stack_size = 2; // Saving of register to stack temporarily. /* for all blocks */ for (i = 0; i < count; i++) { iCode *ic; if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel)) continue; /* for all instructions do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { if ((ic->op == CALL || ic->op == PCALL) && ic->parmBytes + 5 > stm8_call_stack_size) { sym_link *dtype = operandType (IC_LEFT (ic)); sym_link *ftype = IS_FUNCPTR (dtype) ? dtype->next : dtype; /* 5 for saving all registers at call site + 2 for big return value */ stm8_call_stack_size = ic->parmBytes + 5 + 2 * (getSize (ftype->next) > 4); } if (ic->op == IPOP) wassert (0); /* if result is present && is a true symbol */ if (IC_RESULT (ic) && ic->op != IFX && IS_TRUE_SYMOP (IC_RESULT (ic))) OP_SYMBOL (IC_RESULT (ic))->allocreq++; /* some don't need registers, since there is no result. */ if (SKIP_IC2 (ic) || ic->op == JUMPTABLE || ic->op == IFX || ic->op == IPUSH || ic->op == IPOP || (IC_RESULT (ic) && POINTER_SET (ic))) continue; /* now we need to allocate registers only for the result */ if (IC_RESULT (ic)) { symbol *sym = OP_SYMBOL (IC_RESULT (ic)); D (D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym)); if (sym->isspilt && sym->usl.spillLoc) // todo: Remove once remat is supported! { sym->usl.spillLoc->allocreq--; sym->isspilt = FALSE; } /* Make sure any spill location is definately allocated */ if (sym->isspilt && !sym->remat && sym->usl.spillLoc && !sym->usl.spillLoc->allocreq) sym->usl.spillLoc->allocreq++; /* if it does not need or is spilt or is already marked for the new allocator or will not live beyond this instructions */ if (!sym->nRegs || sym->isspilt || sym->for_newralloc || sym->liveTo <= ic->seq) { D (D_ALLOC, ("serialRegAssign: won't live long enough.\n")); continue; } if (sym->nRegs > 4 && ic->op == CALL) { spillThis (sym, TRUE); } else if (max_alloc_bytes >= sym->nRegs) { sym->for_newralloc = 1; max_alloc_bytes -= sym->nRegs; } else if (!sym->for_newralloc) { spillThis (sym, TRUE); printf ("Spilt %s due to byte limit.\n", sym->name); } } } } }
/** Register reduction for assignment. */ static int packRegsForAssign (iCode *ic, eBBlock *ebp) { iCode *dic, *sic; if (!IS_ITEMP (IC_RIGHT (ic)) || OP_SYMBOL (IC_RIGHT (ic))->isind || OP_LIVETO (IC_RIGHT (ic)) > ic->seq) return 0; /* Avoid having multiple named address spaces in one iCode. */ if (IS_SYMOP (IC_RESULT (ic)) && SPEC_ADDRSPACE (OP_SYMBOL (IC_RESULT (ic))->etype)) return 0; /* find the definition of iTempNN scanning backwards if we find a a use of the true symbol in before we find the definition then we cannot */ for (dic = ic->prev; dic; dic = dic->prev) { /* PENDING: Don't pack across function calls. */ if (dic->op == CALL || dic->op == PCALL) { dic = NULL; break; } if (SKIP_IC2 (dic)) continue; if (dic->op == IFX) { if (IS_SYMOP (IC_COND (dic)) && (IC_COND (dic)->key == IC_RESULT (ic)->key || IC_COND (dic)->key == IC_RIGHT (ic)->key)) { dic = NULL; break; } } else { if (IS_TRUE_SYMOP (IC_RESULT (dic)) && IS_OP_VOLATILE (IC_RESULT (dic))) { dic = NULL; break; } if (IS_SYMOP (IC_RESULT (dic)) && IC_RESULT (dic)->key == IC_RIGHT (ic)->key) { if (POINTER_SET (dic)) dic = NULL; break; } if (IS_SYMOP (IC_RIGHT (dic)) && (IC_RIGHT (dic)->key == IC_RESULT (ic)->key || IC_RIGHT (dic)->key == IC_RIGHT (ic)->key)) { dic = NULL; break; } if (IS_SYMOP (IC_LEFT (dic)) && (IC_LEFT (dic)->key == IC_RESULT (ic)->key || IC_LEFT (dic)->key == IC_RIGHT (ic)->key)) { dic = NULL; break; } if (IS_SYMOP (IC_RESULT (dic)) && IC_RESULT (dic)->key == IC_RESULT (ic)->key) { dic = NULL; break; } } } if (!dic) return 0; /* did not find */ /* if assignment then check that right is not a bit */ if (ASSIGNMENT (ic) && !POINTER_SET (ic)) { sym_link *etype = operandType (IC_RESULT (dic)); if (IS_BITFIELD (etype)) { /* if result is a bit too then it's ok */ etype = operandType (IC_RESULT (ic)); if (!IS_BITFIELD (etype)) { return 0; } } } /* if the result is on stack or iaccess then it must be the same atleast one of the operands */ if (OP_SYMBOL (IC_RESULT (ic))->onStack || OP_SYMBOL (IC_RESULT (ic))->iaccess) { /* the operation has only one symbol operator then we can pack */ if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) || (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic)))) goto pack; if (!((IC_LEFT (dic) && IC_RESULT (ic)->key == IC_LEFT (dic)->key) || (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key))) return 0; } pack: /* found the definition */ /* replace the result with the result of */ /* this assignment and remove this assignment */ bitVectUnSetBit (OP_SYMBOL (IC_RESULT (dic))->defs, dic->key); IC_RESULT (dic) = IC_RESULT (ic); if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq) { OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq; } /* delete from liverange table also delete from all the points inbetween and the new one */ for (sic = dic; sic != ic; sic = sic->next) { bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key); if (IS_ITEMP (IC_RESULT (dic))) bitVectSetBit (sic->rlive, IC_RESULT (dic)->key); } remiCodeFromeBBlock (ebp, ic); // PENDING: Check vs mcs51 bitVectUnSetBit (OP_SYMBOL (IC_RESULT (ic))->defs, ic->key); hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); return 1; }
/*-----------------------------------------------------------------*/ eBBlock * iCode2eBBlock (iCode * ic) { iCode *loop; eBBlock *ebb = neweBBlock (); /* allocate an entry */ /* put the first one unconditionally */ ebb->sch = ic; ic->seq = 0; /* if this is a label then */ if (ic->op == LABEL) ebb->entryLabel = ic->label; else { struct dbuf_s dbuf; dbuf_init (&dbuf, 128); dbuf_printf (&dbuf, "_eBBlock%d", eBBNum++); ebb->entryLabel = newSymbol (dbuf_c_str (&dbuf), 1); dbuf_destroy (&dbuf); ebb->entryLabel->key = labelKey++; } if (ic && (ic->op == GOTO || ic->op == JUMPTABLE || ic->op == IFX)) { ebb->ech = ebb->sch; return ebb; } /* if this is a function call */ if (ic->op == CALL || ic->op == PCALL) { sym_link *type = operandType (IC_LEFT (ic)); ebb->hasFcall = 1; if (currFunc) FUNC_HASFCALL (currFunc->type) = 1; if (IS_FUNCPTR (type)) type = type->next; if (type && FUNC_ISNORETURN (type)) { ebb->ech = ebb->sch; return ebb; } } if ((ic->next && ic->next->op == LABEL) || !ic->next) { ebb->ech = ebb->sch; return ebb; } /* loop thru till we find one with a label */ for (loop = ic->next; loop; loop = loop->next) { loop->seq = 0; /* if this is the last one */ if (!loop->next) break; /* if this is a function call */ if (loop->op == CALL || loop->op == PCALL) { sym_link *type = operandType (IC_LEFT (loop)); ebb->hasFcall = 1; if (currFunc) FUNC_HASFCALL (currFunc->type) = 1; if (IS_FUNCPTR (type)) type = type->next; if (type && FUNC_ISNORETURN (type)) break; } /* if the next one is a label */ /* if this is a goto or ifx */ if (loop->next->op == LABEL || loop->op == GOTO || loop->op == JUMPTABLE || loop->op == IFX) break; } /* mark the end of the chain */ ebb->ech = loop; return ebb; }
/*-----------------------------------------------------------------*/ void separateLiveRanges (iCode *sic, ebbIndex *ebbi) { iCode *ic; set *candidates = 0; symbol *sym; // printf("separateLiveRanges()\n"); for (ic = sic; ic; ic = ic->next) { if (ic->op == IFX || ic->op == GOTO || ic->op == JUMPTABLE || !IC_RESULT (ic) || !IS_ITEMP (IC_RESULT (ic)) || bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) <= 1 || isinSet (candidates, OP_SYMBOL (IC_RESULT (ic)))) continue; addSet (&candidates, OP_SYMBOL (IC_RESULT (ic))); } if (!candidates) return; for(sym = setFirstItem (candidates); sym; sym = setNextItem (candidates)) { // printf("Looking at %s, %d definitions\n", sym->name, bitVectnBitsOn (sym->defs)); int i; set *defs = 0; for (i = 0; i < sym->defs->size; i++) if (bitVectBitValue (sym->defs, i)) { iCode *dic; if(dic = hTabItemWithKey (iCodehTab, i)) addSet (&defs, hTabItemWithKey (iCodehTab, i)); else { werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Definition not found"); return; } } do { set *visited = 0; set *newdefs = 0; int oldsize; wassert (defs); wassert (setFirstItem (defs)); // printf("Looking at def at %d now\n", ((iCode *)(setFirstItem (defs)))->key); if (!bitVectBitValue (((iCode *)(setFirstItem (defs)))->rlive, sym->key)) { werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Variable is not alive at one of its definitions"); break; } visit (&visited, setFirstItem (defs), sym->key); addSet (&newdefs, setFirstItem (defs)); do { oldsize = elementsInSet(visited); ic = setFirstItem (defs); for(ic = setNextItem (defs); ic; ic = setNextItem (defs)) { // printf("Looking at other def at %d now\n", ic->key); set *visited2 = 0; set *intersection = 0; visit (&visited2, ic, sym->key); intersection = intersectSets (visited, visited2, THROW_NONE); intersection = subtractFromSet (intersection, defs, THROW_DEST); if (intersection) { visited = unionSets (visited, visited2, THROW_DEST); addSet (&newdefs, ic); } deleteSet (&intersection); deleteSet (&visited2); } } while (oldsize < elementsInSet(visited)); defs = subtractFromSet (defs, newdefs, THROW_DEST); if (newdefs && defs) { operand *tmpop = newiTempOperand (operandType (IC_RESULT ((iCode *)(setFirstItem (newdefs)))), TRUE); // printf("Splitting %s from %s, using def at %d, op %d\n", OP_SYMBOL_CONST(tmpop)->name, sym->name, ((iCode *)(setFirstItem (newdefs)))->key, ((iCode *)(setFirstItem (newdefs)))->op); for (ic = setFirstItem (visited); ic; ic = setNextItem (visited)) { if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic)) == sym) IC_LEFT (ic) = operandFromOperand (tmpop); if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic)) == sym) IC_RIGHT (ic) = operandFromOperand (tmpop); if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym && !POINTER_SET(ic) && ic->next && !isinSet (visited, ic->next)) continue; if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym) { bool pset = POINTER_SET(ic); IC_RESULT (ic) = operandFromOperand (tmpop); if (pset) IC_RESULT(ic)->isaddr = TRUE; } bitVectUnSetBit (sym->uses, ic->key); } } deleteSet (&newdefs); deleteSet (&visited); } while (elementsInSet(defs) > 1); deleteSet (&defs); } deleteSet (&candidates); }
/*-----------------------------------------------------------------*/ static void eBBSuccessors (ebbIndex * ebbi) { eBBlock ** ebbs = ebbi->bbOrder; int count = ebbi->count; int i = 0; /* for all the blocks do */ for (; i < count; i++) { iCode *ic; if (ebbs[i]->noPath) continue; ebbs[i]->succVect = newBitVect (count); /* if the next on exists & this one does not */ /* end in a GOTO or RETURN then the next is */ /* a natural successor of this. Note we have */ /* consider eBBlocks with no instructions */ if (ebbs[i + 1]) { if (ebbs[i]->ech) { bool foundNoReturn = FALSE; if (ebbs[i]->ech->op == CALL || ebbs[i]->ech->op == PCALL) { sym_link *type = operandType (IC_LEFT (ebbs[i]->ech)); if (IS_FUNCPTR (type)) type = type->next; if (type && FUNC_ISNORETURN (type)) foundNoReturn = TRUE; } if (!foundNoReturn && ebbs[i]->ech->op != GOTO && ebbs[i]->ech->op != RETURN && ebbs[i]->ech->op != JUMPTABLE) { int j = i + 1; while (ebbs[j] && ebbs[j]->noPath) j++; addSuccessor (ebbs[i], ebbs[j]); /* add it */ } else { if (i && ebbs[i-1]->ech && ebbs[i-1]->ech->op==IFX) { ebbs[i]->isConditionalExitFrom=ebbs[i-1]; } } } /* no instructions in the block */ /* could happen for dummy blocks */ else addSuccessor (ebbs[i], ebbs[i + 1]); } /* go thru all the instructions: if we find a */ /* goto or ifx or a return then we have a succ */ if ((ic = ebbs[i]->ech)) { eBBlock *succ; /* special case for jumptable */ if (ic->op == JUMPTABLE) { symbol *lbl; for (lbl = setFirstItem (IC_JTLABELS (ic)); lbl; lbl = setNextItem (IC_JTLABELS (ic))) addSuccessor (ebbs[i], eBBWithEntryLabel (ebbi, lbl)); } else { succ = NULL; /* depending on the instruction operator */ switch (ic->op) { case GOTO: /* goto has edge to label */ succ = eBBWithEntryLabel (ebbi, ic->label); break; case IFX: /* conditional jump */ /* if true label is present */ if (IC_TRUE (ic)) succ = eBBWithEntryLabel (ebbi, IC_TRUE (ic)); else succ = eBBWithEntryLabel (ebbi, IC_FALSE (ic)); break; case RETURN: /* block with return */ succ = eBBWithEntryLabel (ebbi, returnLabel); break; } /* if there is a successor add to the list */ /* if it is not already present in the list */ if (succ) addSuccessor (ebbs[i], succ); } } } }