📄 c4x.c
字号:
/* If there is a label at the end of the loop we must insert a NOP. */ do { insn = previous_insn (insn); } while (GET_CODE (insn) == NOTE || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER); if (GET_CODE (insn) == CODE_LABEL) return 1; for (i = 0; i < 4; i++) { /* Search back for prev non-note and non-label insn. */ while (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER) { if (insn == start_label) return i == 0; insn = previous_insn (insn); }; /* If we have a jump instruction we should insert a NOP. If we hit repeat block top we should only insert a NOP if the loop is empty. */ if (GET_CODE (insn) == JUMP_INSN) return 1; insn = previous_insn (insn); } return 0;}voidc4x_rptb_insert (insn) rtx insn;{ rtx end_label; rtx start_label; rtx count_reg; /* If the count register has not been allocated to RC, say if there is a movstr pattern in the loop, then do not insert a RPTB instruction. Instead we emit a decrement and branch at the end of the loop. */ count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0); if (REGNO (count_reg) != RC_REGNO) return; /* Extract the start label from the jump pattern (rptb_end). */ start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0); /* We'll have to update the basic blocks. */ end_label = gen_label_rtx (); emit_label_after (end_label, insn); for (; insn; insn = PREV_INSN (insn)) if (insn == start_label) break; if (! insn) fatal_insn ("c4x_rptb_insert: Cannot find start label", start_label); /* We'll have to update the basic blocks. */ emit_insn_before (gen_rptb_top (start_label, end_label), insn);}/* This function is a C4x special called immediately before delayed branch scheduling. We fix up RTPB style loops that didn't get RC allocated as the loop counter. */voidc4x_process_after_reload (first) rtx first;{ rtx insn; for (insn = first; insn; insn = NEXT_INSN (insn)) { /* Look for insn. */ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') { int insn_code_number; insn_code_number = recog_memoized (insn); if (insn_code_number < 0) continue; /* Insert the RTX for RPTB at the top of the loop and a label at the end of the loop. */ if (insn_code_number == CODE_FOR_rptb_end) c4x_rptb_insert(insn); /* We split all insns here if they have a # for the output template. */ if (1) { const char *template; template = insn_template[insn_code_number]; if (template && template[0] == '#' && template[1] == '\0') { rtx new = try_split (PATTERN(insn), insn, 0); /* If we didn't split the insn, go away. */ if (new == insn && PATTERN (new) == PATTERN(insn)) fatal_insn ("Couldn't split pattern", insn); PUT_CODE (insn, NOTE); NOTE_SOURCE_FILE (insn) = 0; NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; insn = new; } } } }}static intc4x_a_register (op) rtx op;{ return REG_P (op) && IS_ADDR_OR_PSEUDO_REGNO (op);}static intc4x_x_register (op) rtx op;{ return REG_P (op) && IS_INDEX_OR_PSEUDO_REGNO (op);}static intc4x_immed_int_constant (op) rtx op;{ if (GET_CODE (op) != CONST_INT) return 0; return GET_MODE (op) == VOIDmode || GET_MODE_CLASS (op) == MODE_INT || GET_MODE_CLASS (op) == MODE_PARTIAL_INT;}static intc4x_immed_float_constant (op) rtx op;{ if (GET_CODE (op) != CONST_DOUBLE) return 0; if (GET_CODE (XEXP (op, 0)) == MEM) return 0; return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode;}intc4x_H_constant (op) rtx op;{ return c4x_immed_float_constant (op) && c4x_immed_float_p (op);}intc4x_I_constant (op) rtx op;{ return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op));}intc4x_J_constant (op) rtx op;{ if (TARGET_C3X) return 0; return c4x_immed_int_constant (op) && IS_INT8_CONST (INTVAL (op));}static intc4x_K_constant (op) rtx op;{ if (TARGET_C3X || ! c4x_immed_int_constant (op)) return 0; return IS_INT5_CONST (INTVAL (op));}intc4x_L_constant (op) rtx op;{ return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op));}static intc4x_N_constant (op) rtx op;{ return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));}static intc4x_O_constant (op) rtx op;{ return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));}/* The constraints do not have to check the register class, except when needed to discriminate between the constraints. The operand has been checked by the predicates to be valid. *//* ARx + 9-bit signed const or IRn *ARx, *+ARx(n), *-ARx(n), *+ARx(IRn), *-Arx(IRn) for -256 < n < 256 We don't include the pre/post inc/dec forms here since they are handled by the <> constraints. */intc4x_Q_constraint (op) rtx op;{ enum machine_mode mode = GET_MODE (op); if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); switch (GET_CODE (op)) { case REG: return 1; case PLUS: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); if (! REG_P (op0)) return 0; if (REG_P (op1)) return 1; if (GET_CODE (op1) != CONST_INT) return 0; /* HImode and HFmode must be offsettable. */ if (mode == HImode || mode == HFmode) return IS_DISP8_OFF_CONST (INTVAL (op1)); return IS_DISP8_CONST (INTVAL (op1)); } break; default: break; } return 0;}/* ARx + 5-bit unsigned const *ARx, *+ARx(n) for n < 32 */intc4x_R_constraint (op) rtx op;{ enum machine_mode mode = GET_MODE (op); if (TARGET_C3X) return 0; if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); switch (GET_CODE (op)) { case REG: return 1; case PLUS: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); if (! REG_P (op0)) return 0; if (GET_CODE (op1) != CONST_INT) return 0; /* HImode and HFmode must be offsettable. */ if (mode == HImode || mode == HFmode) return IS_UINT5_CONST (INTVAL (op1) + 1); return IS_UINT5_CONST (INTVAL (op1)); } break; default: break; } return 0;}static intc4x_R_indirect (op) rtx op;{ enum machine_mode mode = GET_MODE (op); if (TARGET_C3X || GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); switch (GET_CODE (op)) { case REG: return IS_ADDR_OR_PSEUDO_REGNO (op); case PLUS: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); /* HImode and HFmode must be offsettable. */ if (mode == HImode || mode == HFmode) return IS_ADDR_OR_PSEUDO_REGNO (op0) && GET_CODE (op1) == CONST_INT && IS_UINT5_CONST (INTVAL (op1) + 1); return REG_P (op0) && IS_ADDR_OR_PSEUDO_REGNO (op0) && GET_CODE (op1) == CONST_INT && IS_UINT5_CONST (INTVAL (op1)); } break; default: break; } return 0;}/* ARx + 1-bit unsigned const or IRn *ARx, *+ARx(1), *-ARx(1), *+ARx(IRn), *-Arx(IRn) We don't include the pre/post inc/dec forms here since they are handled by the <> constraints. */intc4x_S_constraint (op) rtx op;{ enum machine_mode mode = GET_MODE (op); if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); switch (GET_CODE (op)) { case REG: return 1; case PRE_MODIFY: case POST_MODIFY: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS) || (op0 != XEXP (op1, 0))) return 0; op0 = XEXP (op1, 0); op1 = XEXP (op1, 1); return REG_P (op0) && REG_P (op1); /* pre or post_modify with a displacement of 0 or 1 should not be generated. */ } break; case PLUS: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); if (!REG_P (op0)) return 0; if (REG_P (op1)) return 1; if (GET_CODE (op1) != CONST_INT) return 0; /* HImode and HFmode must be offsettable. */ if (mode == HImode || mode == HFmode) return IS_DISP1_OFF_CONST (INTVAL (op1)); return IS_DISP1_CONST (INTVAL (op1)); } break; default: break; } return 0;}static intc4x_S_indirect (op) rtx op;{ enum machine_mode mode = GET_MODE (op); if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); switch (GET_CODE (op)) { case PRE_DEC: case POST_DEC: if (mode != QImode && mode != QFmode) return 0; case PRE_INC: case POST_INC: op = XEXP (op, 0); case REG: return IS_ADDR_OR_PSEUDO_REGNO (op); case PRE_MODIFY: case POST_MODIFY: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); if (mode != QImode && mode != QFmode) return 0; if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS) || (op0 != XEXP (op1, 0))) return 0; op0 = XEXP (op1, 0); op1 = XEXP (op1, 1); return REG_P (op0) && IS_ADDR_OR_PSEUDO_REGNO (op0) && REG_P (op1) && IS_INDEX_OR_PSEUDO_REGNO (op1); /* pre or post_modify with a displacement of 0 or 1 should not be generated. */ } case PLUS: { rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); if (REG_P (op0)) { /* HImode and HFmode must be offsettable. */ if (mode == HImode || mode == HFmode) return IS_ADDR_OR_PSEUDO_REGNO (op0) && GET_CODE (op1) == CONST_INT && IS_DISP1_OFF_CONST (INTVAL (op1)); if (REG_P (op1)) return (IS_INDEX_OR_PSEUDO_REGNO (op1) && IS_ADDR_OR_PSEUDO_REGNO (op0)) || (IS_ADDR_OR_PSEUDO_REGNO (op1) && IS_INDEX_OR_PSEUDO_REGNO (op0)); return IS_ADDR_OR_PSEUDO_REGNO (op0) && GET_CODE (op1) == CONST_INT && IS_DISP1_CONST (INTVAL (op1)); } } break; default: break; } return 0;}/* Direct memory operand. */intc4x_T_constraint (op) rtx op;{ if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); if (GET_CODE (op) != LO_SUM) { /* Allow call operands. */ return GET_CODE (op) == SYMBOL_REF && GET_MODE (op) == Pmode && SYMBOL_REF_FLAG (op); } /* HImode and HFmode are not offsettable. */ if (GET_MODE (op) == HImode || GE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -