Esempio n. 1
0
/* *
 * cons_getc - return the next input character from console,
 * or 0 if none waiting.
 * */
int cons_getc(void)
{
	int c = 0;
	bool intr_flag;
	local_intr_save(intr_flag);
	{
		// poll for any pending input characters,
		// so that this function works even when interrupts are disabled
		// (e.g., when called from the kernel monitor).
#ifdef USE_UART
		serial_intr();
#endif
#ifdef HAS_SDS
		if (check_sds() && is_debugging())
			sds_poll_proc();
		sds_intr();
#endif
		//kbd_intr();

		// grab the next character from the input buffer.
		if (cons.rpos != cons.wpos) {
			c = cons.buf[cons.rpos++];
			if (cons.rpos == CONSBUFSIZE) {
				cons.rpos = 0;
			}
		}
	}
	local_intr_restore(intr_flag);
	return c;
}
Esempio n. 2
0
/*
 *  Examines dataflow and checks if data is already in a register
 *  when read-accesses to external ram occurs
 *  needs multiple-passes to work
 */
int flow_dataflow P2 (CODE *, peep_head, int, level)
{
    FLOWLISTENTRY *RegUsage[MAX_REG + 1];
    int     LabelChanges;
    BOOL    headless;		/* is true when currently no entrypoint for code was found 

				 * (after a jump before the first label is found 
				 */
    REG     reg;
    register CODE *ip;
    int     replacecount = 0;
    static int totreplace = 0;

#ifdef DEBUG
    int     Round = 1;

#endif /* DEBUG */

    do {
	DPRINTF ((DEBUG_FLOW, "Dataflow, round %d...", Round++));
	LabelChanges = 0;
	/* currently no entrypoint found */
	headless = FALSE;
	/* clear all lists to start analysis */
	clear_regusage (&(RegUsage[0]));
	for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {
	    /*
	     * invalidate all entries with references to registers
	     * modified in this instruction
	     */
	    validate_regusage (ip, &(RegUsage[0]));

	    switch (ip->opcode) {
	    case op_ldi_ldi:
	    case op_ldf_ldf:
		/* destination now references to source */
		new_flow_list (&(RegUsage[ip->dst2->preg]), ip->dst2->preg,
			       ip->src21, ip->type);
		if (is_am_register (ip->src21)) {
		    /* dest references now to the same list of values as source */
		    add_list_to_flow_list (&(RegUsage[ip->dst2->preg]),
					   RegUsage[ip->src21->preg]);
		    /* source refers now also to destination */
		    add_flow_list (&(RegUsage[ip->src21->preg]),
				   ip->src21->preg, ip->dst2, ip->type);
		}
		/*FALLTHRU */
	    case op_ldi:
	    case op_ldf:
	    case op_ldiu:
	    case op_ldfu:
		/* destination now references to source */
		new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,
			       ip->src1, ip->type);
		if (is_am_register (ip->src1)) {
		    /* dest references now to the same list of values as source */
		    add_list_to_flow_list (&(RegUsage[ip->dst->preg]),
					   RegUsage[ip->src1->preg]);
		    /* source refers now also to destination */
		    add_flow_list (&(RegUsage[ip->src1->preg]),
				   ip->src1->preg, ip->dst, ip->type);
		}
		break;

	    case op_ldi_sti:
	    case op_ldf_stf:
		/* destination now references to source */
		new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,
			       ip->src1, ip->type);
		if (is_am_register (ip->src1)) {
		    /* dest references now to the same list of values as source */
		    add_list_to_flow_list (&(RegUsage[ip->dst->preg]),
					   RegUsage[ip->src1->preg]);
		    /* source refers now also to destination */
		    add_flow_list (&(RegUsage[ip->src1->preg]),
				   ip->src1->preg, ip->dst, ip->type);
		}
		/* source of sti refers now also to destination */
		add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg,
			       ip->dst2, ip->type);
		break;

	    case op_sti_sti:
	    case op_stf_stf:
		/* source refers now also to destination */
		add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg,
			       ip->dst2, ip->type);
		/*FALLTHRU */
	    case op_sti:
	    case op_stf:
		/* source refers now also to destination */
		add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,
			       ip->dst, ip->type);
		break;

	    case op_absf_stf:
	    case op_absi_sti:
	    case op_addf3_stf:
	    case op_addi3_sti:
	    case op_and3_sti:
	    case op_ash3_sti:
	    case op_fix_sti:
	    case op_float_stf:
	    case op_lsh3_sti:
	    case op_mpyf3_stf:
	    case op_mpyi3_sti:
	    case op_negf_stf:
	    case op_negi_sti:
	    case op_not_sti:
	    case op_or3_sti:
	    case op_subf3_stf:
	    case op_subi3_sti:
	    case op_xor3_sti:
		/* source of sti refers now also to destination */
		add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg,
			       ip->dst2, ip->type);
		if ((ip->dst != NULL) && (is_am_register (ip->dst))) {
		    /* destination of operation does not reference to anywhere now */
		    RegUsage[ip->dst->preg] = NULL;
		}
		break;

	    case op_blo:
	    case op_bls:
	    case op_bhi:
	    case op_bhs:
	    case op_beq:
	    case op_bne:
	    case op_blt:
	    case op_ble:
	    case op_bgt:
	    case op_bge:
	    case op_bz:
	    case op_bnz:
	    case op_bp:
	    case op_bn:
	    case op_bnn:
		/* attach aktual registerusageinfo to label of jumpdestination */
		LabelChanges +=
		    attach_regusage_to_label (ip, &(RegUsage[0]), level);
		break;

	    case op_label:
		if (headless == TRUE) {
		    /* first entrypoint of this piece of code, so use whole information from label */
		    copy_regusage_from_label (ip, &(RegUsage[0]), level);
		    headless = FALSE;
		} else {
		    /* not first entrypoint, so merge information from label */
		    LabelChanges +=
			merge_regusage_from_label (ip, &(RegUsage[0]), level);
		}
		break;

	    case op_bu:
	    case op_br:
		/* attach aktual registerusageinfo to label of jumpdestination */
		LabelChanges +=
		    attach_regusage_to_label (ip, &(RegUsage[0]), level);
		/* FALLTHRU */

	    case op_retsu:
	    case op_retiu:
		/* no information abaout registers availlable now */
		clear_regusage (&(RegUsage[0]));
		/* since no entrypoint found now (unconditional controltransfer) */
		headless = TRUE;
		break;

	    case op_asm:
		/* clear whole list, asm can do anything to registers and memory */
		clear_regusage (&(RegUsage[0]));
		break;

	    case op_rpts:
	    case op_rptb:
		/* remove all references to and from blockrepeatregisters */
		RegUsage[REG_RC] = NULL;
		RegUsage[REG_RS] = NULL;
		RegUsage[REG_RE] = NULL;
		remove_from_regusage (RegUsage, REG_RC);
		remove_from_regusage (RegUsage, REG_RS);
		remove_from_regusage (RegUsage, REG_RE);
		break;

	    case op_call:
	    case op_trapu:
	    case op_xcall:
	    case op_callu:
		/* remove all references to and from temporary registers */
		clear_tempreg_usage (&(RegUsage[0]));
		/*
		 * we do not know what called routine does
		 * with memory
		 */
		remove_from_regusage (RegUsage, REG_MEMORY);
		/* FALLTHRU */

	    case op_push:
	    case op_pop:
	    case op_pushf:
	    case op_popf:
	    case op_pushnopeep:
	    case op_pushfnopeep:
		/* references from SP are no longer valid */
		RegUsage[REG_SP] = NULL;
		/* FALLTHRU */

	    default:
		if ((ip->dst != NULL) && (is_am_register (ip->dst))) {
		    /* destination of operation does not reference to anywhere now */
		    RegUsage[ip->dst->preg] = NULL;
		}
		if ((ip->dst2 != NULL) && (is_am_register (ip->dst2))) {
		    /* destination of operation does not reference to anywhere now */
		    RegUsage[ip->dst2->preg] = NULL;
		}
		break;

	    }
	}
	DPRINTF ((DEBUG_FLOW, " %d changes \n", LabelChanges));
    } while (LabelChanges != 0);

    DPRINTF ((DEBUG_FLOW, "%s\n", "Dataflow, REPLACEMENT ROUND"));
    LabelChanges = 0;
    /* currently no entrypoint found */
    headless = FALSE;
    /* clear all lists to start analysis */
    clear_regusage (&(RegUsage[0]));
    for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {
	/*
	 * invalidate all entries with references to registers
	 * modified in this instruction
	 */
#ifdef ENHANCED_FLOW
	validate_addressregusage (ip, &(RegUsage[0]));
#else
	validate_regusage (ip, &(RegUsage[0]));
#endif
	switch (ip->opcode) {
	case op_ldi_ldi:
	case op_ldf_ldf:
	    if (
		(reg =
		 search_in_regusage (&(RegUsage[0]), ip->src1,
				     ip->type)) >= 0) {
		DPRINTF (
			 (DEBUG_FLOW, "FoundReplacement for src1 %d",
			  (int) reg));
		if (is_exchangable (&(ip->src1), reg)) {
		    replacecount++;
		    totreplace++;
		    Update_Peep_Info (ip);
		}
	    }
	    if (
		(reg =
		 search_in_regusage (&(RegUsage[0]), ip->src21,
				     ip->type)) >= 0) {
		DPRINTF (
			 (DEBUG_FLOW, "FoundReplacement for src21 %d",
			  (int) reg));
		if (is_exchangable (&(ip->src21), reg)) {
		    replacecount++;
		    totreplace++;
		    Update_Peep_Info (ip);
		}
	    }
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* destination now references to source */
	    new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,
			   ip->src1, ip->type);
	    if (is_am_register (ip->src1)) {
		/* dest references now to the same list of values as source */
		add_list_to_flow_list (&(RegUsage[ip->dst->preg]),
				       RegUsage[ip->src1->preg]);
		/* source refers now also to destination */
		add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,
			       ip->dst, ip->type);
	    }
	    /* destination now references to source */
	    new_flow_list (&(RegUsage[ip->dst2->preg]), ip->dst2->preg,
			   ip->src21, ip->type);
	    if (is_am_register (ip->src21)) {
		/* dest references now to the same list of values as source */
		add_list_to_flow_list (&(RegUsage[ip->dst2->preg]),
				       RegUsage[ip->src21->preg]);
		/* source refers now also to destination */
		add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg,
			       ip->dst2, ip->type);
	    }
	    break;

	case op_ldi:
	case op_ldf:
	case op_ldiu:
	case op_ldfu:
	    if (
		(reg =
		 search_in_regusage (&(RegUsage[0]), ip->src1,
				     ip->type)) >= 0) {
		DPRINTF (
			 (DEBUG_FLOW, "FoundReplacement for src1 %d",
			  (int) reg));
		if (is_exchangable (&(ip->src1), reg)) {
		    replacecount++;
		    totreplace++;
		    Update_Peep_Info (ip);
		}
	    }
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* destination now references to source */
	    new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,
			   ip->src1, ip->type);
	    if (is_am_register (ip->src1)) {
		/* dest references now to the same list of values as source */
		add_list_to_flow_list (&(RegUsage[ip->dst->preg]),
				       RegUsage[ip->src1->preg]);
		/* source refers now also to destination */
		add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,
			       ip->dst, ip->type);
	    }
	    break;

	case op_ldi_sti:
	case op_ldf_stf:
	    if (
		(reg =
		 search_in_regusage (&(RegUsage[0]), ip->src1,
				     ip->type)) >= 0) {
		DPRINTF (
			 (DEBUG_FLOW, "FoundReplacement for src1 %d",
			  (int) reg));
		if (is_exchangable (&(ip->src1), reg)) {
		    replacecount++;
		    totreplace++;
		    Update_Peep_Info (ip);
		}
	    }
	    if (
		(reg =
		 search_in_regusage (&(RegUsage[0]), ip->src21,
				     ip->type)) >= 0) {
		DPRINTF (
			 (DEBUG_FLOW, "FoundReplacement for src21 %d",
			  (int) reg));
		if (is_exchangable (&(ip->src21), reg)) {
		    replacecount++;
		    totreplace++;
		    Update_Peep_Info (ip);
		}
	    }
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* destination now references to source */
	    new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,
			   ip->src1, ip->type);
	    if (is_am_register (ip->src1)) {
		/* dest references now to the same list of values as source */
		add_list_to_flow_list (&(RegUsage[ip->dst->preg]),
				       RegUsage[ip->src1->preg]);
		/* source refers now also to destination */
		add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,
			       ip->dst, ip->type);
	    }
	    /* source of sti refers now also to destination */
	    add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg,
			   ip->dst2, ip->type);
	    break;

	case op_sti_sti:
	case op_stf_stf:
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* source refers now also to destination */
	    add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg,
			   ip->dst2, ip->type);
	    /* source refers now also to destination */
	    add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,
			   ip->dst, ip->type);
	    break;

	case op_sti:
	case op_stf:
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* source refers now also to destination */
	    add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,
			   ip->dst, ip->type);
	    break;


	case op_absf_stf:
	case op_absi_sti:
	case op_addf3_stf:
	case op_addi3_sti:
	case op_and3_sti:
	case op_ash3_sti:
	case op_fix_sti:
	case op_float_stf:
	case op_lsh3_sti:
	case op_mpyf3_stf:
	case op_mpyi3_sti:
	case op_negf_stf:
	case op_negi_sti:
	case op_not_sti:
	case op_or3_sti:
	case op_subf3_stf:
	case op_subi3_sti:
	case op_xor3_sti:
#if 0
/* 
 * sorry, currently no replace possible, since
 * src1 must be r0-r7
 * src2 must be restricted indirect
 * src21 must be r0-r7
 */
	    if (ip->src1 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src1,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src1 %d",
			      reg));
		    if (is_exchangable (&(ip->src1), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    if (ip->src2 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src2,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src2 %d",
			      reg));
		    if (is_exchangable (&(ip->src2), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
#endif
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* source of sti refers now also to destination */
	    add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg,
			   ip->dst2, ip->type);
	    if ((ip->dst != NULL)
		&& (is_am_register (ip->dst))) {
		/* destination of operation does not reference to anywhere now */
		RegUsage[ip->dst->preg] = NULL;
	    }
	    break;
	case op_label:
	    if (headless == TRUE) {
		/* first entrypoint of this piece of code, so use whole information from label */
		copy_regusage_from_label (ip, &(RegUsage[0]), level);
		headless = FALSE;
	    } else {
		/* not first entrypoint, so merge information from label */
		LabelChanges +=
		    merge_regusage_from_label (ip, &(RegUsage[0]), level);
	    }
	    /*
	     *  Remove regusage-entry from label
	     */
	    ip->src21 = NULL;
	    break;

	case op_bu:
	    if ((ip->src1 != NULL) && (ip->src1->mode != am_immed)) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src1,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src1 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src1), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    /* FALLTHRU */
	case op_br:
	    /* FALLTHRU */
	case op_retsu:
	case op_retiu:
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* no information abaout registers availlable now */
	    clear_regusage (&(RegUsage[0]));
	    /* since no entrypoint found now (unconditional controltransfer) */
	    headless = TRUE;
	    break;

	case op_asm:
	    /* clear whole list, asm can do anything to registers and memory */
	    clear_regusage (&(RegUsage[0]));
	    break;

	case op_rpts:
	    if (ip->src1 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src1,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src1 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src1), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    /* FALLTHRU */

	case op_rptb:
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* remove all references to and from blockrepeatregisters */
	    RegUsage[REG_RC] = NULL;
	    RegUsage[REG_RS] = NULL;
	    RegUsage[REG_RE] = NULL;
	    remove_from_regusage (RegUsage, REG_RC);
	    remove_from_regusage (RegUsage, REG_RS);
	    remove_from_regusage (RegUsage, REG_RE);
	    break;

	case op_callu:
	    if ((ip->src1 != NULL) && (ip->src1->mode != am_immed)) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src1,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src1 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src1), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    /* FALLTHRU */
	case op_call:
	case op_trapu:
	case op_xcall:
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    /* remove all references to and from temporary registers */
	    clear_tempreg_usage (&(RegUsage[0]));
	    /*
	     * we do not know what called routine does
	     * with memory
	     */
	    remove_from_regusage (RegUsage, REG_MEMORY);
	    /* FALLTHRU */

	case op_push:
	case op_pop:
	case op_pushf:
	case op_popf:
	case op_pushnopeep:
	case op_pushfnopeep:
	    /* references from SP are no longer valid */
	    RegUsage[REG_SP] = NULL;
	    /* FALLTHRU */

	default:
	    if (ip->src1 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src1,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src1 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src1), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    if (ip->src2 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src2,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src2 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src2), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    if (ip->src21 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src21,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src21 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src21), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
	    if (ip->src22 != NULL) {
		if (
		    (reg =
		     search_in_regusage (&(RegUsage[0]), ip->src22,
					 ip->type)) >= 0) {
		    DPRINTF (
			     (DEBUG_FLOW, "FoundReplacement for src22 %d",
			      (int) reg));
		    if (is_exchangable (&(ip->src22), reg)) {
			replacecount++;
			totreplace++;
			Update_Peep_Info (ip);
		    }
		}
	    }
#ifdef USE_ALL_OPCODES
	    /* FALLTHRU */
	    /* do no replacements with parallel mul/add */
	case op_mpf3_adf3:
	case op_mpf3_sbf3:
	case op_mpi3_adi3:
	case op_mpi3_sbi3:
#endif /* USE_ALL_OPCODES */
#ifdef ENHANCED_FLOW
	    validate_regusage (ip, &(RegUsage[0]));
#endif
	    if ((ip->dst != NULL) && (is_am_register (ip->dst))) {
		/* destination of operation does not reference to anywhere now */
		RegUsage[ip->dst->preg] = NULL;
	    }
	    if ((ip->dst2 != NULL) && (is_am_register (ip->dst2))) {
		/* destination of operation does not reference to anywhere now */
		RegUsage[ip->dst2->preg] = NULL;
	    }
	    break;

	}
#ifdef DEBUG
	if (is_debugging (DEBUG_FLOW)) {
	    FHANDLE save = output;

	    output = debugfile;
	    if (ip->opcode == op_label) {
		put_label (ip->src1->u.offset->v.l);
	    } else {
		put_code (ip);
	    }
	    output = save;
	    print_regusage (&(RegUsage[0]));
	}
#endif /* DEBUG */
    }
    DPRINTF ((DEBUG_FLOW, "Replaced %d ", replacecount));
    DPRINTF ((DEBUG_FLOW, "Total %d \n", totreplace));
    return replacecount;
}