peepc30.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,250 行 · 第 1/5 页
C
2,250 行
* no exchange possible */ return FALSE; } /*lint -fallthrough */#else /* PEEP_CALL_ALSO_VIA_TABLE */ case op_callu: case op_trapu: case op_call: case op_xcall: /* if search_reg or dest is a temporary we cannot do any replacements */ if (is_temporary_register (search_reg) || is_temporary_register (replace)) return FALSE; if (search_reg == STACKPTR) return FALSE; /*lint -fallthrough */#endif /* PEEP_CALL_ALSO_VIA_TABLE */ default: map = GET_PEEP_INFO (ip2, &StaticMemory); changed = map->write | map->modified | map->updated; needed = map->read | map->modified | map->used | map->updated; /* * if replaceregister is modified we can do no further replacements */ if (changed & (replacebit)) { replacement_forbidden = TRUE; } /* * Check if register is used in any indirect way * if so, replace must be of same type * (if search is ar, replace must be ar * if search is index, replace must be index) */ if (((map->used | map->updated) & (searchbit)) != 0) { if (!is_same_register_type (search_reg, replace)) { return FALSE; } } /* * Check for any pending replacements if replacement is forbidden */ if (replacement_forbidden == TRUE) { if (needed & (searchbit)) { return FALSE; } } /* * if Search is overwritten, we can end remap here */ if (map->write & (searchbit)) { return TRUE; } /* * if searchregister is modified, we may only replace * if replaceregister is not used anymore */ if (changed & (searchbit)) { if (is_value_used (replace, ip2)) { return FALSE; } } break; case op_label:#if 1 if (is_peep_phase (peep_level, PEEP_HARD_REMAP)) { result = is_value_used (search_reg, ip2); result = result || is_value_used (replace, ip2); if (result == TRUE) { return FALSE; } return TRUE; }#endif return FALSE; case op_line: break; } } return TRUE;}/* * Checks to see if a remap of registers is possible in the backward direction * e.g. if register 'search_reg' may be replaced with 'replace' in the * following instruction sequence. * * This is not possible if: * * 'search_reg' is STACKPTR. * * 'replace' is temporary and we have a call in the sequence. * * 'search_reg' is temporary and we have a call in the sequence. * * an asm-statement is in the sequence. * * 'replace' is used and more replacements follow in * this sequence upwards. * * 'replace' is not an address register and search_reg is used * as an address register or index register in an indirect * address mode. * * By branches, labels and jumps we return FALSE, because following * all paths and do all replacements correctly is somewhat hairy * (I just dont know how to do it, so I let it be). * * The sequence ends if a block begin is found or 'search_reg' is overwritten. */static BOOL is_remap_possible_bwd P3 (REG, search_reg, REG, replace,
const CODE *, ip){ CODE *ip2; BOOL result; REGBITMAP changed; REGBITMAP needed; REGBITMAP replacebit = (1UL << (int) replace); REGBITMAP searchbit = (1UL << (int) search_reg); PEEPINFO *map;#ifdef SAVE_PEEP_MEMORY PEEPINFO StaticMemory;#endif /* SAVE_PEEP_MEMORY */ if (ip == NIL_CODE) return FALSE; for (ip2 = ip->back; ip2 != NIL_CODE; ip2 = ip2->back) { switch (ip2->opcode) { case op_retsu: case op_retiu: /* We should have found a label before we reach here, else * this is dead code, so we can swap what we want */ return TRUE; case op_abort: /* we have closed a loop, so replace must be possible */ return TRUE;#ifdef ASM case op_asm: /* really it in unknown */ return FALSE;#endif /* ASM */ 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: /* may be too complicated to follow, so we let it be for now */ /* so we use the simpler variant of just checking if search */ /* and replace are not used anymore on jumpdestination */#if 1 if (is_peep_phase (peep_level, PEEP_HARD_REMAP)) { result = is_value_used (search_reg, find_label (ip2->src1->u.offset->v.l)); result = result || is_value_used (replace, find_label (ip2->src1->u.offset->v.l)); if (result == TRUE) { return FALSE; } } else { return FALSE; } break;#else return FALSE;#endif case op_br: case op_bu: case op_bud: case op_brd: /* We should have found a label before we reach here, else * this is dead code, so we can swap what we want */ return TRUE; case op_callu: case op_call: case op_trapu: case op_xcall: if (is_temporary_register (replace)) return FALSE; if ((search_reg == STACKPTR) || (search_reg == RESULT)) return FALSE; if (is_temporary_register (search_reg)) return TRUE; /*lint -fallthrough */ default: map = GET_PEEP_INFO (ip2, &StaticMemory); changed = map->write | map->modified | map->updated; needed = map->read | map->modified | map->used | map->updated; /* if search_reg is overwritten, sequence ends here * replace is possible if it was not forbidden * (If sequence would not end with overwrite, * replacement would be possible independent of forbidden) */ if (map->write & (searchbit)) { /* * was return !replacement_forbidden; * (see comment somwhat farther down) */ return TRUE; } /* * Check if register is used in any indirect way * if so, replace must be of same type * (if search is ar, replace must be ar * if search is index, replace must be index) */ if (((map->used | map->updated) & (searchbit)) != 0) { if (!is_same_register_type (search_reg, replace)) { return FALSE; } } /* * Check if replaceregister is modified in any way * if so, replace is not possible * but there is also a register, whose value is not * used (-> we started by an ldi search, replace * and did not found any instruction using * contents of replace, so this modifications * of replace are used nowhere) * theoretically, this should not happen :-) * */ if (((changed) & (replacebit)) != 0) { return FALSE; } /* * if contents of replace are needed here, further * replacement is not possible * * theoretically I should use here (map->read | map->used) * instead of needed, but the cases map->modified and map->updated * which are also contained in needed are already handled in the * precedent statement, so no problem at all */ if (((needed) & (replacebit)) != 0) { /* * Was replacement_forbidden = TRUE; * but I don't see what what difference that makes * to directly returning FALSE * (There was only one possibility to return TRUE, * when we reached the head of the function without * any further references of search, which means we * worked with uninitialized registers, which should * never happen */ return FALSE; } break; case op_label: /* we wont follow jumps now */ if (ip2->back != NIL_CODE) return FALSE; else return TRUE; /* Functionshead allways starts with a label */ case op_line: break; } } return TRUE;}static ADDRESS *replace_register P3 (ADDRESS *, ap, REG, search_reg, REG, replace){ ADDRESS *newap; if (ap == NIL_ADDRESS) return ap; switch (ap->mode) { case am_areg: case am_dreg: case am_ireg: case am_sreg: if (ap->preg == search_reg) { return mk_reg (replace); } break; case am_freg: if (ap->preg == search_reg) { return mk_freg (replace); } break; case am_ainc: case am_adec: case am_preinc: case am_predec: case am_ind: case am_const_ind: case am_indx: if (ap->preg == search_reg) { if (is_address_register (replace)) { newap = copy_addr (ap, ap->mode); newap->preg = replace; return newap; } } break; case am_indx2: case am_indxs: if (ap->preg == search_reg) { if (is_address_register (replace)) { newap = copy_addr (ap, ap->mode); newap->preg = replace; return newap; } } if (ap->sreg == search_reg) { if ((replace == REG_IR0) || (replace == REG_IR1)) { newap = copy_addr (ap, ap->mode); newap->sreg = replace; return newap; } } break; case am_immed: case am_direct: case am_const_direct: case am_none: case am_line: break; default: break; } FATAL ((__FILE__, "replace_register", "inconsistency")); return ap;}/* * Replaces in the given instruction all references to * register 'search_reg' with references to 'replace'. * */static void replace_all_registers P3 (CODE *, ip, REG, search_reg, REG, replace){ if (is_register_used (search_reg, ip->src1)) { ip->src1 = replace_register (ip->src1, search_reg, replace); } if (is_register_used (search_reg, ip->src2)) { ip->src2 = replace_register (ip->src2, search_reg, replace); } if (is_register_used (search_reg, ip->src21)) { ip->src21 = replace_register (ip->src21, search_reg, replace); } if (is_register_used (search_reg, ip->src22)) { ip->src22 = replace_register (ip->src22, search_reg, replace); } if (is_register_used (search_reg, ip->dst)) { ip->dst = replace_register (ip->dst, search_reg, replace); } if (is_register_used (search_reg, ip->dst2)) { ip->dst2 = replace_register (ip->dst2, search_reg, replace); } /* * Not forgetting to update infofield in instruction !!! */ Update_Peep_Info (ip);}/* * Replaces in the given instruction all source references to * register 'search_reg' with references to 'replace'. * */static void replace_source_registers P3 (CODE *, ip, REG, search_reg, REG, replace){ if (is_register_used (search_reg, ip->src1)) { ip->src1 = replace_register (ip->src1, search_reg, replace); } if (is_register_used (search_reg, ip->src2)) { ip->src2 = replace_register (ip->src2, search_reg, replace); } if (is_register_used (search_reg, ip->src21)) { ip->src21 = replace_register (ip->src21, search_reg, replace); } if (is_register_used (search_reg, ip->src22)) { ip->src22 = replace_register (ip->src22, search_reg, replace); } /* * Not forgetting to update infofield in instruction !!! */ Update_Peep_Info (ip);}/* * Replaces in the given instruction all destination references to * register 'search_reg' with references to 'replace'. * */static void replace_destination_registers P3 (CODE *, ip, REG, search_reg, REG, replace){ if (is_register_used (search_reg, ip->dst)) { ip->dst = replace_register (ip->dst, search_reg, replace); } if (is_register_used (search_reg, ip->dst2)) { ip->dst2 = replace_register (ip->dst2, search_reg, replace); } /* * Not forgetting to update infofield in instruction !!! */ Update_Peep_Info (ip);}/* * Remaps registers, eg replaces register 'search_reg' with 'replace' in the * following instruction sequence until 'search_reg' is overwritten. * * This routine is only to be called if replace is really possible * (Check with 'is_remap_possible_fwd') else FATAL will be called. * * Remap is not possible if: * * 'search_reg' is STACKPTR. * * 'search_reg' is RESULT and sequence ends with return. * * An asm-statement is in the sequence. * * 'replace' is used o
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?