peepc30.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,250 行 · 第 1/5 页
C
2,250 行
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: case op_bu: case op_br: branches += 3; tot++; group1blocked = 0; group3blocked = 0; break; case op_abort: FATAL ((__FILE__, "analyze_code", "unexpected abort")); break;#ifdef ASM case op_asm: /* really it in unknown */ asmstat++; break;#endif /* ASM */ case op_bud: case op_brd: default: map = GET_PEEP_INFO (ip, &StaticMemory); flags = map->used | map->updated; if (flags & GROUP_1_REGISTERS) { reg += group1blocked; group1blocked = 0; group3blocked = 0; } if (flags & GROUP_3_REGISTERS) { reg += group3blocked; group1blocked = 0; group3blocked = 0; } flags = map->read; if (flags & GROUP_1_READ) { /* Delay is 1, but will allready be decremented in * this loop, so set to 2 */ group1blocked = 2; } if (flags & GROUP_3_READ) { /* Delay is 1, but will allready be decremented in * this loop, so set to 2 */ group3blocked = 2; } flags = map->modified | map->write; if (flags & GROUP_1_WRITE) { /* Delay is 2, but will allready be decremented in * this loop, so set to 3 */ group1blocked = 3; } if (flags & GROUP_3_WRITE) { /* Delay is 2, but will allready be decremented in * this loop, so set to 3 */ group3blocked = 3; } if (group1blocked > 0) { group1blocked--; } if (group3blocked > 0) { group3blocked--; } tot++; break; case op_label: case op_line: break; } } *totsize += tot; *branchconflicts += branches; *registerconflicts += reg; *asmstatements += asmstat;}/* * Returns false if the register reg1 is not used in the <ea> of ap2, otherwise * it returns true. If we aren't sure then return true anyway. */BOOL is_register_used P2 (REG, reg1, const ADDRESS *, ap2){ if (ap2 == NIL_ADDRESS) return FALSE; switch (ap2->mode) { case am_areg: case am_dreg: case am_freg: case am_ireg: case am_sreg: case am_ainc: case am_adec: case am_preinc: case am_predec: case am_ind: case am_const_ind: case am_indx: return ap2->preg == reg1; case am_indx2: case am_indxs: return ap2->sreg == reg1 || ap2->preg == reg1; case am_immed: case am_direct: case am_const_direct: case am_none: case am_line: return FALSE; default: break; } return TRUE;}/* * Checks to see if the register reg is overwritten with a new value * before the value is used (or the value is never used!). * If the value is not used again, FALSE is returned. */static BOOL is_value_used P2 (REG, reg, const CODE *, ip){ CODE *ip2, *target; BOOL result = FALSE; OPCODE op; SWITCH *sw, *table; LABEL label; unsigned i; REGBITMAP needed; REGBITMAP regbit = (1UL << (int) reg); PEEPINFO *map;#ifdef SAVE_PEEP_MEMORY PEEPINFO StaticMemory;#endif /* SAVE_PEEP_MEMORY */ if (ip == NIL_CODE) return FALSE; for (ip2 = ip->fwd; ip2 != NIL_CODE; ip2 = ip2->fwd) { switch (ip2->opcode) { case op_retsu: if ((reg == RESULT) || (reg == STACKPTR)) { /* ** Might be a return value */ return TRUE; } else { return FALSE; } case op_retiu: case op_abort: return FALSE;#ifdef ASM case op_asm: /* really it in unknown */ return TRUE;#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: op = ip2->opcode; ip2->opcode = op_abort; /* to prevent looping */ /* follow both paths of the branch */ result = is_value_used (reg, ip2) || is_value_used (reg, find_label (ip2->src1->u.offset->v.l)); ip2->opcode = op; return result; case op_bud: case op_brd: /* * brd should not be found in this stage of * codeanalysis. return TRUE if still found. */ return TRUE; case op_bu: /* * bu is used in switchtable, so we cannot say * (we had to check al paths of the switch), assume * value is used, thats save in any case * if enabled in option we analyse switches too */ if (!is_peep_phase (peep_level, PEEP_SWITCH)) { return TRUE; } /* look for the switchtable belonging to that op_bu */ table = NIL_SWITCH; for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { /* genc30 adds the labelname into the offsetfield of src1 */ if (ip2->src1->u.offset->v.l == sw->tablab) { table = sw; break; } } if (table != NIL_SWITCH) { op = ip2->opcode; ip2->opcode = op_abort; /* to prevent looping */ result = is_register_used (reg, ip2->src1); /* follow all paths of the switch */ for (i = 0; i < table->numlabs; i++) { label = table->labels[i]; target = find_label (label); if (target == NULL) { FATAL ( (__FILE__, "is_value_used", "switch_target not found")); } result |= is_value_used (reg, target); } ip2->opcode = op; return result; } else { FATAL ( (__FILE__, "is_value_used", "switchtable for bu not found")); } return TRUE; case op_br: op = ip2->opcode; ip2->opcode = op_abort; /* to prevent looping */ result = is_register_used (reg, ip2->src1) || is_value_used (reg, find_label (ip2->src1->u.offset->v.l)); ip2->opcode = op; return result;#ifndef PEEP_CALL_ALSO_VIA_TABLE case op_xcall: if (is_temporary_register (reg)) { if ((reg == REG_R0) || (reg == REG_R1)) return TRUE; /* may be used to pass parameters */ else return FALSE; } /*lint -fallthrough */ case op_callu: case op_trapu: case op_call: if (reg == STACKPTR) return TRUE; if (is_temporary_register (reg)) { return FALSE; } /*lint -fallthrough */#endif /* PEEP_CALL_ALSO_VIA_TABLE */ default: map = GET_PEEP_INFO (ip2, &StaticMemory); needed = map->read | map->modified | map->used | map->updated; /* * if register is used (read or modified) * we return TRUE (it is used :-) ) */ if (needed & regbit) { return TRUE; } /* * if register is written to * we return FALSE ( Contents are obviously not used) */ if (map->write & regbit) { return FALSE; } break; case op_label: case op_line: break; } } return FALSE;}/* * Checks to see if a remap of registers is possible in a forward direction * e.g. if register 'search' may be replaced with 'replace' in the * following instruction sequence. * * This is not possible if: * * 'search' is STACKPTR. * * 'search' is RESULT and sequence ends with return. * * An asm-statement is in the sequence. * * 'replace' is used or modified. * * 'replace' is overwritten and more replacements follow in * this sequence. * * 'replace' is not an address register and 'search' 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 return is found or 'search' is overwritten. */static BOOL is_remap_possible_fwd P3 (REG, search_reg, REG, replace,
const CODE *, ip){ CODE *ip2; BOOL replacement_forbidden = FALSE; 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->fwd; ip2 != NIL_CODE; ip2 = ip2->fwd) { switch (ip2->opcode) { case op_retsu: /* We are at the end of the block, if search_reg is sp * or RESULT we cannot replace registers */ if ((search_reg == RESULT) || (search_reg == STACKPTR)) { /* ** Might be a return value */ return FALSE; } else { return TRUE; } case op_retiu: case op_abort: return FALSE;#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:#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; } return TRUE; }#endif return FALSE; case op_bu:#if 1 if (is_peep_phase (peep_level, PEEP_VERY_HARD_REMAP)) { /* use ip2->back, then is_value_used will analyze the switch for us */ result = is_value_used (search_reg, ip2->back); result = result || is_value_used (replace, ip2->back); if (result == TRUE) { return FALSE; } return TRUE; }#endif return FALSE; case op_bud: case op_brd: /* We wont follow branches, too difficult */ return FALSE;#ifdef PEEP_CALL_ALSO_VIA_TABLE case op_xcall: if ((search_reg == REG_R0) || (search_reg == REG_R1)) { /* * Registers are used to pass parameters,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?