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 + -
显示快捷键?