/* 
 * Description: 
 * 	Moves an instruction from the execution stage to common data bus (if possible)
 * Inputs:
 * 	current_cycle: the cycle we are at
 * Returns:
 * 	None
 */
void execute_To_CDB(int current_cycle) {

  /* ECE552: YOUR CODE GOES HERE */
  // Remove all finished stores.
  {
    int i, j;
    for (i = 0; i < FU_INT_SIZE; i++) {
      if (fuINT[i] != NULL && IS_STORE(fuINT[i]->op) && current_cycle >= FU_INT_LATENCY + fuINT[i]->tom_execute_cycle) {
        remove_insn(fuINT[i], reservINT, RESERV_INT_SIZE);
        fuINT[i] = NULL;
      }
    }
  }
  // Find oldest instruction that is ready to be broadcasted on the CDB.
  {
    int i;
    instruction_t* insn = NULL;

    for (i = 0; i < FU_INT_SIZE; i++) {
      if (fuINT[i] != NULL && current_cycle >= FU_INT_LATENCY + fuINT[i]->tom_execute_cycle && (insn == NULL || fuINT[i]->index < insn->index)) {
        insn = fuINT[i];
      }
    }
    for (i = 0; i < FU_FP_SIZE; i++) {
      if (fuFP[i] != NULL && current_cycle >= FU_FP_LATENCY + fuFP[i]->tom_execute_cycle && (insn == NULL || fuFP[i]->index < insn->index)) {
        insn = fuFP[i];
      }
    }

    // If instruction is found, remove it from RSs and FUs.
    // Then, set cycle it enters CDB and put it on the CDB.
    if (insn != NULL) {
      remove_insn(insn, reservINT, RESERV_INT_SIZE);
      remove_insn(insn, reservFP, RESERV_FP_SIZE);
      remove_insn(insn, fuINT, FU_INT_SIZE);
      remove_insn(insn, fuFP, FU_FP_SIZE);
      insn->tom_cdb_cycle = current_cycle;
      commonDataBus = insn;
    }
  }
}
Beispiel #2
0
void
replace_call_placeholder (rtx insn, sibcall_use_t use)
{
  if (use == sibcall_use_tail_recursion)
    emit_insn_before (XEXP (PATTERN (insn), 2), insn);
  else if (use == sibcall_use_sibcall)
    emit_insn_before (XEXP (PATTERN (insn), 1), insn);
  else if (use == sibcall_use_normal)
    emit_insn_before (XEXP (PATTERN (insn), 0), insn);
  else
    abort ();

  /* Turn off LABEL_PRESERVE_P for the tail recursion label if it
     exists.  We only had to set it long enough to keep the jump
     pass above from deleting it as unused.  */
  if (XEXP (PATTERN (insn), 3))
    LABEL_PRESERVE_P (XEXP (PATTERN (insn), 3)) = 0;

  /* "Delete" the placeholder insn.  */
  remove_insn (insn);
}
static unsigned int
rest_of_handle_simplify_got (void)
{
  df_ref ref;
  rtx use = NULL_RTX;
  int i, n_symbol, n_access = 0;
  struct got_access_info* got_accesses;
  htab_t var_table = htab_create (VAR_TABLE_SIZE,
				  htab_hash_pointer,
				  htab_eq_pointer,
				  NULL);
  rtx pic_reg = targetm.got_access.get_pic_reg ();
  gcc_assert (pic_reg);

  ref = DF_REG_USE_CHAIN (REGNO (pic_reg));
  got_accesses = XNEWVEC(struct got_access_info,
			 DF_REG_USE_COUNT (REGNO (pic_reg)));

  /* Check if all uses of pic_reg are loading global address through the
     default method.  */
  while (ref)
    {
      rtx_insn* insn = DF_REF_INSN (ref);

      /* Check for the special USE insn, it is not a real usage of pic_reg.  */
      if (GET_CODE (PATTERN (insn)) == USE)
	use = insn;
      else
	{
	  /* If an insn both set and use pic_reg, it is in the process of
	     constructing the value of pic_reg. We should also ignore it.  */
	  rtx set = single_set (insn);
	  if (!(set && SET_DEST (set) == pic_reg))
	    {
	      rtx offset_reg;
	      rtx offset_insn;
	      rtx symbol = targetm.got_access.loaded_global_var (insn,
								 &offset_reg,
								 &offset_insn);
	      if (symbol)
		{
		  rtx* slot = (rtx*) htab_find_slot (var_table, symbol, INSERT);
		  if (*slot == HTAB_EMPTY_ENTRY)
		    *slot = symbol;

		  gcc_assert (set);
		  got_accesses[n_access].symbol = symbol;
		  got_accesses[n_access].offset_reg = offset_reg;
		  got_accesses[n_access].address_reg = SET_DEST (set);
		  got_accesses[n_access].load_insn = insn;
		  got_accesses[n_access].offset_insn = offset_insn;
		  n_access++;
		}
	      else
		{
		  /* This insn doesn't load a global address, but it has
		     other unexpected usage of pic_reg, give up.  */
		  free (got_accesses);
		  htab_delete (var_table);
		  return 0;
		}
	    }
	}
      ref = DF_REF_NEXT_REG(ref);
    }

  /* Check if we can simplify it.  */
  n_symbol = htab_elements (var_table);
  gcc_assert (n_symbol <= n_access);
  if (!targetm.got_access.can_simplify_got_access (n_symbol, n_access))
    {
      free (got_accesses);
      htab_delete (var_table);
      return 0;
    }

  /* Rewrite the global address loading insns.  */
  for (i=0; i<n_access; i++)
    targetm.got_access.load_global_address (got_accesses[i].symbol,
					    got_accesses[i].offset_reg,
					    got_accesses[i].address_reg,
					    got_accesses[i].load_insn,
					    got_accesses[i].offset_insn);

  /* Since there is no usage of pic_reg now, we can remove it.  */
  if (use)
    remove_insn (use);
  targetm.got_access.clear_pic_reg ();
  free (got_accesses);
  htab_delete (var_table);
  return 0;
}