peep68k.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,521 行 · 第 1/4 页
C
2,521 行
SWITCH *sw;
if (ip == NIL_CODE)
return FALSE;
if (ip2 == NIL_CODE)
return FALSE;
for (ip2 = ip2->back; ip2 != NIL_CODE; ip2 = ip2->back) { switch (ip2->opcode) { case op_label: label = ip2->oper1->u.offset->v.l; /* first check code before the label */ if (!was_move_redundant (ip, ip2, memory)) { return FALSE; } /* ... and then check all branches to this label */ for (ip2 = peep_head; ip2 != NIL_CODE; ip2 = ip2->fwd) { switch (ip2->opcode) { case op_beq: case op_bne: case op_bgt: case op_bge: case op_blt: case op_ble: case op_bls: case op_blo: case op_bhi: case op_bhs: case op_bra: if (is_label_used (ip2->oper1, label)) { OPCODE op = ip2->opcode; ip2->opcode = op_nop; if (!was_move_redundant (ip, ip2, memory)) { ip2->opcode = op; return FALSE; } ip2->opcode = op; } break; default: break; } } /* but if it is via a jump table we cannot determine it */ for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { LABEL lab; for (lab = (LABEL) 0; lab < sw->numlabs; lab++) { if (sw->labels[lab] == label) { return FALSE; } } } return TRUE; case op_rts: case op_rte: case op_jmp: case op_bra: /* should have at least hit a label before here! */ case op_nop: return TRUE; case op_jsr: case op_bsr: return FALSE;#ifdef ASM case op_asm: return FALSE;#endif /* ASM */ case op_line: break; default: if (is_same_instruction (ip, ip2)) { return TRUE; } altered = is_altered (ip2->opcode); overwritten = is_overwrite (ip2->opcode); if (ip2->oper2) { /* two operand instruction */ if (is_equal_address (ip->oper1, ip2->oper2)) { if (overwritten && (ip->length <= ip2->length) && is_equal_address (ip->oper2, ip2->oper1)) return TRUE; if (altered) { return FALSE; } } if (altered) { if (is_address_used (ip2->oper2, ip->oper1)) { return FALSE; } if (is_address_used (ip2->oper2, ip->oper2)) { return FALSE; } } if (is_address_changed (ip->oper1, ip2->oper2) || is_address_changed (ip->oper2, ip2->oper2)) { return FALSE; } switch (ip2->oper2->mode) { case am_dreg: case am_areg: case am_freg: case am_mreg: case am_direct: case am_immed: if (altered && (is_equal_address (ip->oper2, ip2->oper2) || is_equal_address (ip->oper1, ip2->oper2))) { return FALSE; } break; case am_ainc: case am_adec: if (is_equal_address (ip->oper2, ip2->oper2)) { return FALSE; } /*lint -fallthrough */ case am_ind: case am_indx: if (altered && memory) { return FALSE; } break; default: break; } } if (ip2->oper1) { if (is_address_changed (ip->oper1, ip2->oper1) || is_address_changed (ip->oper2, ip2->oper1)) { return FALSE; } switch (ip2->oper1->mode) { case am_dreg: case am_areg: case am_freg: case am_mreg: case am_direct: case am_immed: if (ip2->oper2 != NIL_ADDRESS) { break; } /* one operand instruction */ if (altered && (is_equal_address (ip->oper2, ip2->oper1) || is_equal_address (ip->oper1, ip2->oper1))) return FALSE; break; case am_ainc: case am_adec: if (is_equal_address (ip->oper2, ip2->oper1)) { return FALSE; } /*lint -fallthrough */ case am_ind: case am_indx: if (ip2->oper2 != NIL_ADDRESS) { break; } /* one operand instruction */ if (altered && memory) { return FALSE; } break; default: break; } } break; } } return FALSE;}/* * Determine whether a move is redundant ... this is done by looking forward * along the code list (following all branches) to determine * whether the destination is required before being overwritten. */static BOOL is_move_redundant P3 (CODE *, ip, CODE *, ip2, BOOL, memory){ (void) ip; /* KEE COMPILEr HAPPY UNTIL CODE READY */ (void) ip2; (void) memory;#if 0 /* currently not fully working */ BOOL result, altered, overwritten; OPCODE op; for (ip2 = ip2->fwd; ip2 != NIL_CODE; ip2 = ip2->fwd) { switch (ip2->opcode) { case op_rts: case op_rte: case op_jmp: return FALSE; case op_nop: return TRUE; case op_bra: ip2->opcode = op_nop; /* to prevent looping */ result = is_move_redundant (ip, find_label (ip2->oper1->u.offset->v.l), memory); ip2->opcode = op_bra; return result; case op_beq: case op_bne: case op_bgt: case op_bge: case op_blt: case op_ble: case op_bls: case op_blo: case op_bhi: case op_bhs: op = ip2->opcode; ip2->opcode = op_nop; /* to prevent looping */ result = is_move_redundant (ip, ip2, memory) && is_move_redundant (ip, find_label (ip2->oper1->u.offset->v.l), memory); ip2->opcode = op; return result; case op_jsr: case op_bsr: return FALSE;#ifdef ASM case op_asm: return FALSE;#endif /* ASM */ case op_line: break; default: if (is_same_instruction (ip, ip2)) { return TRUE; } altered = is_altered (ip2->opcode); overwritten = is_overwrite (ip2->opcode); if (ip2->oper2) { /* two operand instruction */ if (is_address_used (ip->oper2, ip2->oper1)) { return FALSE; } if (overwritten && (ip->length <= ip2->length) && is_equal_address (ip->oper2, ip2->oper2)) { return TRUE; } if (is_address_used (ip->oper2, ip2->oper2)) { return FALSE; } break; } else if (ip2->oper1) { /* one operand instruction */ if (overwritten && (ip->length <= ip2->length) && is_equal_address (ip->oper2, ip2->oper1)) { return TRUE; } if (is_address_used (ip->oper2, ip2->oper1)) { return FALSE; } } break; } }#endif return FALSE;}/* * Look forward from the instruction 'ip' and see if the flags are * used before being reset. */static BOOL is_flag_used P1 (CODE *, ip){ BOOL result; if (ip == NIL_CODE) { return FALSE; } for (ip = ip->fwd; ip; ip = ip->fwd) { switch (ip->opcode) { case op_bra: ip->opcode = op_nop; /* to prevent looping */ result = is_flag_used (find_label (ip->oper1->u.offset->v.l)); ip->opcode = op_bra; return result; case op_jsr: case op_bsr: case op_jmp: case op_rts: case op_rte: case op_nop: return FALSE; default: if (is_use_flags (ip->opcode)) { return TRUE; } if (is_noset_flags (ip->opcode)) { if (ip->oper2) { if (ip->oper2->mode == am_areg) { break; } } else if (ip->oper1) { if (ip->oper1->mode == am_areg) { break; } } } if (is_set_flags (ip->opcode)) { return FALSE; } break; } } return FALSE;}/* insert an instruction after the specified position in the code list */static void insert_code P5 (CODE *, target, OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ CODE *p; p = code (op, len, ap1, ap2); p->fwd = target->fwd; p->back = target; target->fwd = p->fwd->back = p;}/* ensure we have a label to branch to (create if needed) */static void check_label P2 (const CODE *, ip, CODE *, target){ if (target->fwd->opcode == op_label) { ip->oper1->u.offset->v.l = target->fwd->oper1->u.offset->v.l; } else { insert_code (target, op_label, IL0, mk_label (nextlabel), NIL_ADDRESS); ip->oper1->u.offset->v.l = nextlabel++; }}static CODE *code P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ CODE *ip; ip = (CODE *) xalloc (sizeof (CODE)); ip->opcode = op; ip->length = len; ip->oper1 = ap1; ip->oper2 = ap2;#ifdef PEEPFLOW ip->regmap = 0;#endif /* PEEPFLOW */ return ip;}/* * generate a code sequence into the peep list. */void g_code P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ add_peep (code (op, len, ap1, ap2));}#ifdef FLOAT_IEEE/* * generate a floating point code sequence into the peep list. */void g_fcode P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ if (ap1 != NIL_ADDRESS && ap1->mode == am_freg && (ap2 == NIL_ADDRESS || ap2->mode == am_freg)) { len = IL12; } add_peep (code (op, (ILEN) (len + 1), ap1, ap2));}#endif /* FLOAT_IEEE *//* * add the instruction pointed to by new to the peep list. */static void add_peep P1 (CODE *, ip){ static CODE *peep_tail; if (peep_head == NIL_CODE) { peep_head = peep_tail = ip; ip->fwd = NIL_CODE; ip->back = NIL_CODE; } else { ip->fwd = NIL_CODE; ip->back = peep_tail; peep_tail->fwd = ip; peep_tail = ip; }}/* * output all code and labels in the peep list. */void flush_peep P1 (unsigned, level){ register CODE *ip; SWITCH *sw; EXPR *ep2; LABEL i; opt3 (level); /* do the peephole optimizations */ for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { if (ip->opcode == op_label) { put_label (ip->oper1->u.offset->v.l); } else { put_code (ip); } } peep_head = NIL_CODE; for (sw = swtables; sw; sw = sw->next) { put_kseg (alignment_of_type (tp_pointer)); put_label (sw->tablab); ep2 = mk_lcon (UNDEF_LABEL);#ifdef RELOC_BUG /* generate the switch jump table as a series of 4-byte addresses */ for (i = 0; i < sw->numlabs; i++) { ep2->v.l = sw->labels[i]; put_pointer (ep2); }#else /* generate the switch jump table as a series of 2-byte offsets * This limits the amount of code that can be generated in a * function to less then 32K. I believe that this is a reasonable * restriction. */ { EXPR *ep, *ep1; ep1 = mk_lcon (sw->beglab); ep = mk_node (en_sub, ep2, ep1, tp_void); for (i = (LABEL) 0; i < sw->numlabs; i++) { ep2->v.l = sw->labels[i]; put_short (ep); } }#endif /* RELOC_BUG */ } swtables = NIL_SWITCH;}/* * delete an instruction referenced by ip */static void peep_delete P1 (const CODE *, ip){ if (ip == NIL_CODE) { FATAL ((__FILE__, "peep_delete", ""));
/* NOTREACHED */ } if (ip->back == NIL_CODE) { peep_head = ip->fwd; if (ip->fwd) { ip->fwd->back = NIL_CODE; } next_ip = ip->fwd; } else { if ((ip->back->fwd = ip->fwd) != NIL_CODE) { ip->fwd->back = ip->back; } next_ip = ip->back; } changes++;}/* * changes LEA <ea>,An => PEA <ea> * PEA (An) * The value of An is not needed (An is scratch register) * CAVEAT code generator modifier! */static void peep_pea P1 (const CODE *, ip){ CODE *prev; if (ip->oper1->mode != am_ind) { return; } if ((prev = ip->back) == NIL_CODE) { return; } if (prev->opcode == op_lea && prev->oper2->preg == ip->oper1->preg && is_temporary_address_register (ip->oper1->preg)) { prev->opcode = op_pea; prev->oper2 = NIL_ADDRESS; peep_delete (ip); }}/* * peephole optimization for LEA instructions. */static void peep_lea P1 (CODE *, ip){ CODE *next; if (ip->oper1->mode == am_ind && ip->oper1->preg == ip->oper2->preg) { /* * LEA (An), An deleted */ peep_delete (ip); return; } if ((next = ip->fwd) == NIL_CODE) { return; } if (next->opcode == op_movea && is_equal_address (ip->oper2, next->oper1) && next->oper2->mode == am_areg && is_temporary_register (next->oper1->preg)) { /* * LEA <ea>, An => LEA <ea>, Am * MOVEA.L An, Am */ ip->oper2 = next->oper2; peep_delete (ip->fwd); } if (ip->oper2->preg == STACKPTR && is_dest_overwritten (ip->oper2, ip)) { peep_delete (ip); return; }}/* * peephole optimization for MOVE instructions. */static void peep_move P1 (CODE *, ip){ CODE *ip2; EXPR *ep; /* * move.w An,An changes the contents of An through sign extension */ if (is_equal_address (ip->oper1, ip->oper2) && (ip->oper1->mode != am_areg || ip->length != IL2)) { peep_delete (ip); return; } switch (ip->oper1->mode) { case am_immed: ep = ip->oper1->u.offset; if (ip->length == IL4) { /* * changes MOVE #n, -(A7) => PEA n * * unless n == 0 */ if (ip->oper2->mode == am_adec && ip->oper2->preg == STACKPTR && (ep->nodetype != en_icon || ep->v.i != 0L)) { ip->opcode = op_pea; ip->oper2 = NIL_ADDRESS; ip->oper1 = copy_addr (ip->oper1, am_direct); ip->length = IL0; changes++; return; } /* * changes MOVE #n, An => LEA n, An */ if (ip->oper2->mode == am_areg) { ip->opcode = op_lea; ip->oper1 = copy_addr (ip->oper1, am_direct); ip->length = IL0; changes++; return; } } if (is_icon (ep)) { /* * Replace move immediate An for the following cases * MOVE #0, An * MOVE #shortval, An * by the sequences * SUB.L An,An * and MOVE.W #shortval, An */ if (ip->oper2->mode == am_areg) { if (ep->v.i == 0L) { ip->length = IL4; ip->opcode = op_sub; ip->oper1 = ip->oper2; changes++; } else if ((IVAL) -32768L <= ep->v.i && ep->v.i <= (IVAL) 32767L) { ip->length = IL2; } return; } /* * Replace moving small constants into a data register by * MOVEQ #value,Dn */ if (ip->oper2->mode == am_dreg) { if ((IVAL) -128 <= ep->v.i && ep->v.i <= (IVAL) 127) { ip->opcode = op_moveq; ip->length = IL0; changes++; return; } } /* * Replace the sequence * MOVE.W #X, -(An) * MOVE.W #Y, -(An) * by the sequence * MOVE.L #(X<<16|Y), -(An) */ ip2 = ip->fwd; if (ip->length == IL2 && ip->oper2->mode == am_adec && ip2->length == IL2 && ip2->opcode == op_move && ip2->oper1->mode == am_immed && is_icon (ip2->oper1->u.offset) && ip2->oper2->mode == am_adec && ip2->oper2->preg == ip->oper2->preg) { ip->length = IL4; ep->v.u = (ep->v.u & (UVAL) 0xffffL) |
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?