Esempio n. 1
0
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);
    }
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
/*
*   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;
}
Esempio n. 6
0
/*-----------------------------------------------------------------*/
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;
}
Esempio n. 7
0
/* 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;
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
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;
    }
}
Esempio n. 10
0
/*-----------------------------------------------------------------*/
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);
                }
            }
	}
    }
}
Esempio n. 11
0
/*-----------------------------------------------------------------*/
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);
}
Esempio n. 12
0
/*-----------------------------------------------------------------*/
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;

}
Esempio n. 13
0
/**
  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);
                }
            }
        }
    }
}
Esempio n. 14
0
/** 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;
}
Esempio n. 15
0
/*-----------------------------------------------------------------*/
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;
}
Esempio n. 16
0
/*-----------------------------------------------------------------*/
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);
}
Esempio n. 17
0
/*-----------------------------------------------------------------*/
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);
	    }
	}
    }
}