📄 flow68k.c
字号:
return reg; } } return NO_REG;}/* * Produces a copy of an registerusage-list and returns a pointer to it */static REGENTRY **copy_regusage P1 (REGENTRY **, regusage){ REGENTRY **new_regusage; REG reg; new_regusage = (REGENTRY **) xalloc (sizeof (REGENTRY *[MAX_REG + 1])); for (reg = D0; reg <= MAX_REG; reg++) { new_regusage[reg] = copy_regentry (regusage[reg]); } return new_regusage;}/* * Merges the largest common registerusage-set from dst and src * into src * * Returns the number of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */static int merge_regusage P2 (REGENTRY **, dest, REGENTRY **, src){ REG reg; int changes = 0; for (reg = D0; reg <= MAX_REG; reg++) { changes += merge_regentry (&(dest[reg]), src[reg]); } return changes;}/* * Removes all references to and from register reg */static void remove_regusage P2 (REGENTRY **, regusage, REG, reg){ REG r; if (reg != REG_MEMORY) { regusage[reg] = NIL_REGENTRY; } for (r = D0; r <= MAX_REG; r++) { remove_regentry (&(regusage[r]), reg); }}/* * Removes all references to and from all temporary registers */static void clear_tempreg_usage P1 (REGENTRY **, regusage){ REG reg; for (reg = D0; reg <= MAX_REG; reg++) { if (is_temporary_register (reg)) { regusage[reg] = NIL_REGENTRY; remove_regusage (regusage, reg); } }}/* * Attachs the Regusagelist to the Label which is the destination of * ip (ip must be jump or branch). * The usagelist of the label is corrected to the biggest common set * of regusage and the old list of the label. * * Returns the number of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */static int attach_regusage_to_label P2 (REGENTRY **, regusage, CODE *, ip){ LABEL label; CODE *target; assert (ip->oper1->mode == am_direct); label = ip->oper1->u.offset->v.l; target = find_label (label); assert (target != NIL_CODE); if (target->oper2 == NIL_ADDRESS) { target->oper2 = (ADDRESS *) copy_regusage (regusage); return 1; } else { return merge_regusage ((REGENTRY **) target->oper2, regusage); }}/* * Merges the Regusage list from the Label ip (ip must be a label) * and the Regusage list (result is the largest common set of both * lists.) * * Both lists are overwritten with the newly generated common list. * * If the label is referenced in an switch-table, an empty-list * is provided, since we dont know anything about register usage * after a switch. * * Returns the number of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes have been done */static int merge_regusage_from_label P2 (REGENTRY **, regusage, CODE *, ip){ LABEL label; SWITCH *sw; BOOL is_found = FALSE; assert (ip->opcode == op_label); label = ip->oper1->u.offset->v.l; for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { LABEL i; for (i = 0; i < sw->numlabs; i++) { if (sw->labels[i] == label) { is_found = TRUE;; } } } if (is_found) { clear_regusage (regusage); if (ip->oper2 == NIL_ADDRESS) { ip->oper2 = (ADDRESS *) copy_regusage (regusage); return 1; } else { clear_regusage (regusage); return merge_regusage ((REGENTRY **) ip->oper2, regusage); } } else { if (ip->oper2 == NIL_ADDRESS) { ip->oper2 = (ADDRESS *) copy_regusage (regusage); return 1; } else { int count; count = merge_regusage ((REGENTRY **) ip->oper2, regusage); VOIDCAST merge_regusage (regusage, (REGENTRY **) ip->oper2); return count; } }}/* * Copies the Regusage list from the label ip (ip must be a label) * to the Regusage list (old contents are overwritten). * If the label is referenced in an switch-table, an empty-list * is provided, since we dont know anything about register usage * after an switch. */static void copy_regusage_from_label P2 (REGENTRY **, regusage, CODE *, ip){ LABEL label; SWITCH *sw; BOOL is_found = FALSE; assert (ip->opcode == op_label); label = ip->oper1->u.offset->v.l; for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { LABEL i; for (i = 0; i < sw->numlabs; i++) { if (sw->labels[i] == label) { is_found = TRUE; } } } if (is_found) { clear_regusage (regusage); if (ip->oper2 == NIL_ADDRESS) { ip->oper2 = (ADDRESS *) copy_regusage (regusage); } else { clear_regusage ((REGENTRY **) ip->oper2); } } else { if (ip->oper2 == NIL_ADDRESS) { clear_regusage (regusage); } else { REG r; REGENTRY **p; REGENTRY **src = (REGENTRY **) ip->oper2; for (r = D0, p = regusage; r < MAX_REG; r++, p++) { *p = copy_regentry (src[r]); } } }}/* * Invalidates (throws out) all references in registers and * to registers, which are changed by the instruction ip, * including memory references */static void validate_regusage P2 (REGENTRY **, regusage, CODE *, ip){ REGMAP *map; REGBITMAP changed; REGBITMAP current = 1; REG reg; if (ip->opcode == op_label) return; map = build_regmap (ip); changed = map->write | map->modified | map->updated; for (reg = D0; reg <= MAX_REG; reg++) { if ((changed & current) != 0) { remove_regusage (regusage, reg); } current <<= 1; } if ((changed & MEMBER (REG_MEMORY)) != 0) { remove_regusage (regusage, REG_MEMORY); }}/*****************************************************************************//* Is called if an amode could be exchanged with register reg; * that is if both contain the same value * * We only do the replace if we think it is useful * * We replace following cases * * Old New * Temporary D-Reg D-Reg * Temporary A-Reg Not A-Reg Reduces Pipelineconflicts * Memory Any Reg Avoids Memory-access * frees busbandwith * */static BOOL is_exchangable P2 (ADDRESS **, apptr, REG, reg){ ADDRESS *ap = *apptr; switch (ap->mode) { case am_dreg: case am_freg: if (is_temporary_data_register (ap->preg) && (is_data_register (reg))) { /* * replace only if temporary */ *apptr = mk_reg (reg); (*apptr)->mode = ap->mode; return TRUE; } break; case am_areg: if (!is_address_register (reg) || is_temporary_address_register (ap->preg)) { *apptr = mk_reg (reg); return TRUE; } break; default: *apptr = mk_reg (reg); return TRUE; } return FALSE;}/* * 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 P1 (CODE *, peep_head){ REGENTRY *regusage[MAX_REG + 1]; int label_changes; BOOL is_headless; 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++)); label_changes = 0; is_headless = FALSE; clear_regusage (regusage); for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { validate_regusage (regusage, ip); switch (ip->opcode) { case op_move: case op_movea: case op_moveq: new_regentry (regusage, ip->oper2, ip->oper1); switch (ip->oper2->mode) { case am_dreg: case am_areg: case am_freg: reg = ip->oper2->preg; regusage[reg] = add_regentry (regusage[reg], ip->oper1);#ifdef DEBUG DPRINTF ((DEBUG_FLOW, "ADD: ")); if (is_debugging (DEBUG_FLOW)) { print_regusage (reg, regusage); }#endif /* DEBUG */ switch (ip->oper1->mode) { REG reg2; case am_dreg: case am_areg: case am_freg: reg2 = ip->oper1->preg; regusage[reg2] = add_regentries (regusage[reg], regusage[reg2]);#ifdef DEBUG DPRINTF ((DEBUG_FLOW, "ADD: ")); if (is_debugging (DEBUG_FLOW)) { print_regusage (reg2, regusage); }#endif /* DEBUG */ break; default: break; } break; default: break; } switch (ip->oper1->mode) { case am_dreg: case am_areg: case am_freg: reg = ip->oper1->preg; regusage[reg] = add_regentry (regusage[reg], ip->oper2);#ifdef DEBUG DPRINTF ((DEBUG_FLOW, "ADD: ")); if (is_debugging (DEBUG_FLOW)) { print_regusage (reg, regusage); }#endif /* DEBUG */ break; default: break; } 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: label_changes += attach_regusage_to_label (regusage, ip); break; case op_label: if (is_headless) { copy_regusage_from_label (regusage, ip); is_headless = FALSE; } else { label_changes += merge_regusage_from_label (regusage, ip); }#ifdef DEBUG DPRINTF ( (DEBUG_FLOW, "LABEL: I_%d\n", ip->oper1->u.offset->v.l)); if (is_debugging (DEBUG_FLOW)) { print_regusages (regusage); }#endif /* DEBUG */ break; case op_bra: label_changes += attach_regusage_to_label (regusage, ip); /* FALLTHRU */ case op_rts: case op_rte: clear_regusage (regusage); is_headless = TRUE; break;#ifdef ASM case op_asm: clear_regusage (regusage); break;#endif /* ASM */ case op_jsr: clear_tempreg_usage (regusage); /* * we do not know what called routine does * with memory */ remove_regusage (regusage, REG_MEMORY); /* FALLTHRU */ default: break; } } DPRINTF ((DEBUG_FLOW, " %d changes \n", label_changes)); } while (label_changes > 0); DPRINTF ((DEBUG_FLOW, "%s\n", "Dataflow, REPLACEMENT ROUND")); label_changes = 0; is_headless = FALSE; clear_regusage (regusage); for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { /* * invalidate all entries with references to registers * modified in this instruction */ validate_regusage (regusage, ip); switch (ip->opcode) { case op_label:#ifdef DEBUG DPRINTF ((DEBUG_FLOW, "LABEL: I_%d\n", ip->oper1->u.offset->v.l)); if (is_debugging (DEBUG_FLOW)) { print_regusages (regusage); }#endif /* DEBUG */ if (is_headless) {#ifdef DEBUG DPRINTF ((DEBUG_FLOW, "Headless\n")); if (is_debugging (DEBUG_FLOW) && ip->oper2 != NIL_ADDRESS) { print_regusages ((REGENTRY **) ip->oper2); }#endif /* DEBUG */ copy_regusage_from_label (regusage, ip); is_headless = FALSE; } else { label_changes += merge_regusage_from_label (regusage, ip); }#ifdef DEBUG DPRINTF ((DEBUG_FLOW, "-----------\n")); if (is_debugging (DEBUG_FLOW)) { print_regusages (regusage); }#endif /* DEBUG */ break; case op_bra: /* FALLTHRU */ case op_rts: case op_rte: clear_regusage (regusage); is_headless = TRUE; break;#ifdef ASM case op_asm: clear_regusage (regusage); break;#endif /* ASM */ case op_jsr: clear_tempreg_usage (regusage); /* * we do not know what the called routine does with memory */ remove_regusage (regusage, REG_MEMORY); regusage[A7] = NIL_REGENTRY; /* FALLTHRU */ default: if (ip->oper1 != NIL_ADDRESS) { reg = search_regusage (regusage, ip->oper1); if (reg != NO_REG) { DPRINTF ( (DEBUG_FLOW, "Found replacement for oper1 %d\n", (int) reg)); if (is_exchangable (&(ip->oper1), reg)) { replacecount++; totreplace++; } } } if ((ip->oper2 != NIL_ADDRESS) && (ip->oper2->mode == am_areg)) { regusage[ip->oper2->preg] = NIL_REGENTRY; } break; }#ifdef DEBUG if (is_debugging (DEBUG_FLOW)) { print_regusages (regusage); }#endif /* DEBUG */ } DPRINTF ( (DEBUG_FLOW, "Replaced %d Total %d\n", replacecount, totreplace)); return replacecount;}#endif /* MC680X0 */#endif /* PEEPFLOW */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -