/* * * 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; }
/* * 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; }