📄 c4x.c
字号:
fprintf (file, "%s\t@", TARGET_C3X ? "ldp" : "ldpk"); output_address (XEXP (op, 0)); fprintf (file, "\n\t"); } return; case 'O': /* Offset address. */ if (code == MEM && c4x_autoinc_operand (op, Pmode)) break; else if (code == MEM) output_address (XEXP (adjust_address (op, VOIDmode, 1), 0)); else if (code == REG) fprintf (file, "%s", reg_names[REGNO (op) + 1]); else fatal_insn ("c4x_print_operand: %%O inconsistency", op); return; case 'C': /* Call. */ break; case 'U': /* Call/callu. */ if (code != SYMBOL_REF) fprintf (file, "u"); return; default: break; } switch (code) { case REG: if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT && ! TARGET_TI) fprintf (file, "%s", float_reg_names[REGNO (op)]); else fprintf (file, "%s", reg_names[REGNO (op)]); break; case MEM: output_address (XEXP (op, 0)); break; case CONST_DOUBLE: { char str[64]; real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (op), sizeof (str), 0, 1); fprintf (file, "%s", str); } break; case CONST_INT: fprintf (file, "%d", INTVAL (op)); break; case NE: fprintf (file, "ne"); break; case EQ: fprintf (file, "eq"); break; case GE: fprintf (file, "ge"); break; case GT: fprintf (file, "gt"); break; case LE: fprintf (file, "le"); break; case LT: fprintf (file, "lt"); break; case GEU: fprintf (file, "hs"); break; case GTU: fprintf (file, "hi"); break; case LEU: fprintf (file, "ls"); break; case LTU: fprintf (file, "lo"); break; case SYMBOL_REF: output_addr_const (file, op); break; case CONST: output_addr_const (file, XEXP (op, 0)); break; case CODE_LABEL: break; default: fatal_insn ("c4x_print_operand: Bad operand case", op); break; }}voidc4x_print_operand_address (file, addr) FILE *file; rtx addr;{ switch (GET_CODE (addr)) { case REG: fprintf (file, "*%s", reg_names[REGNO (addr)]); break; case PRE_DEC: fprintf (file, "*--%s", reg_names[REGNO (XEXP (addr, 0))]); break; case POST_INC: fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]); break; case POST_MODIFY: { rtx op0 = XEXP (XEXP (addr, 1), 0); rtx op1 = XEXP (XEXP (addr, 1), 1); if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1)) fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)], reg_names[REGNO (op1)]); else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0) fprintf (file, "*%s++(%d)", reg_names[REGNO (op0)], INTVAL (op1)); else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0) fprintf (file, "*%s--(%d)", reg_names[REGNO (op0)], -INTVAL (op1)); else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1)) fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)], reg_names[REGNO (op1)]); else fatal_insn ("c4x_print_operand_address: Bad post_modify", addr); } break; case PRE_MODIFY: { rtx op0 = XEXP (XEXP (addr, 1), 0); rtx op1 = XEXP (XEXP (addr, 1), 1); if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1)) fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)], reg_names[REGNO (op1)]); else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0) fprintf (file, "*++%s(%d)", reg_names[REGNO (op0)], INTVAL (op1)); else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0) fprintf (file, "*--%s(%d)", reg_names[REGNO (op0)], -INTVAL (op1)); else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1)) fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)], reg_names[REGNO (op1)]); else fatal_insn ("c4x_print_operand_address: Bad pre_modify", addr); } break; case PRE_INC: fprintf (file, "*++%s", reg_names[REGNO (XEXP (addr, 0))]); break; case POST_DEC: fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]); break; case PLUS: /* Indirect with displacement. */ { rtx op0 = XEXP (addr, 0); rtx op1 = XEXP (addr, 1); if (REG_P (op0)) { if (REG_P (op1)) { if (IS_INDEX_REG (op0)) { fprintf (file, "*+%s(%s)", reg_names[REGNO (op1)], reg_names[REGNO (op0)]); /* Index + base. */ } else { fprintf (file, "*+%s(%s)", reg_names[REGNO (op0)], reg_names[REGNO (op1)]); /* Base + index. */ } } else if (INTVAL (op1) < 0) { fprintf (file, "*-%s(%d)", reg_names[REGNO (op0)], -INTVAL (op1)); /* Base - displacement. */ } else { fprintf (file, "*+%s(%d)", reg_names[REGNO (op0)], INTVAL (op1)); /* Base + displacement. */ } } else fatal_insn ("c4x_print_operand_address: Bad operand case", addr); } break; case LO_SUM: { rtx op0 = XEXP (addr, 0); rtx op1 = XEXP (addr, 1); if (REG_P (op0) && REGNO (op0) == DP_REGNO) c4x_print_operand_address (file, op1); else fatal_insn ("c4x_print_operand_address: Bad operand case", addr); } break; case CONST: case SYMBOL_REF: case LABEL_REF: fprintf (file, "@"); output_addr_const (file, addr); break; /* We shouldn't access CONST_INT addresses. */ case CONST_INT: default: fatal_insn ("c4x_print_operand_address: Bad operand case", addr); break; }}/* Return nonzero if the floating point operand will fit in the immediate field. */static intc4x_immed_float_p (op) rtx op;{ long convval[2]; int exponent; REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, op); if (GET_MODE (op) == HFmode) REAL_VALUE_TO_TARGET_DOUBLE (r, convval); else { REAL_VALUE_TO_TARGET_SINGLE (r, convval[0]); convval[1] = 0; } /* Sign extend exponent. */ exponent = (((convval[0] >> 24) & 0xff) ^ 0x80) - 0x80; if (exponent == -128) return 1; /* 0.0 */ if ((convval[0] & 0x00000fff) != 0 || convval[1] != 0) return 0; /* Precision doesn't fit. */ return (exponent <= 7) /* Positive exp. */ && (exponent >= -7); /* Negative exp. */}/* The last instruction in a repeat block cannot be a Bcond, DBcound, CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS. None of the last four instructions from the bottom of the block can be a BcondD, BRD, DBcondD, RPTBD, LAJ, LAJcond, LATcond, BcondAF, BcondAT or RETIcondD. This routine scans the four previous insns for a jump insn, and if one is found, returns 1 so that we bung in a nop instruction. This simple minded strategy will add a nop, when it may not be required. Say when there is a JUMP_INSN near the end of the block that doesn't get converted into a delayed branch. Note that we cannot have a call insn, since we don't generate repeat loops with calls in them (although I suppose we could, but there's no benefit.) !!! FIXME. The rptb_top insn may be sucked into a SEQUENCE. */intc4x_rptb_nop_p (insn) rtx insn;{ rtx start_label; int i; /* Extract the start label from the jump pattern (rptb_end). */ start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0); /* 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;}/* The C4x looping instruction needs to be emitted at the top of the loop. Emitting the true RTL for a looping instruction at the top of the loop can cause problems with flow analysis. So instead, a dummy doloop insn is emitted at the end of the loop. This routine checks for the presence of this doloop insn and then searches back to the top of the loop, where it inserts the true looping insn (provided there are no instructions in the loop which would cause problems). Any additional labels can be emitted at this point. In addition, if the desired loop count register was not allocated, this routine does nothing. Before we can create a repeat block looping instruction we have to verify that there are no jumps outside the loop and no jumps outside the loop go into this loop. This can happen in the basic blocks reorder pass. The C4x cpu can not handle this. */static intc4x_label_ref_used_p (x, code_label) rtx x, code_label;{ enum rtx_code code; int i, j; const char *fmt; if (x == 0) return 0; code = GET_CODE (x); if (code == LABEL_REF) return INSN_UID (XEXP (x,0)) == INSN_UID (code_label); fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') { if (c4x_label_ref_used_p (XEXP (x, i), code_label)) return 1; } else if (fmt[i] == 'E') for (j = XVECLEN (x, i) - 1; j >= 0; j--) if (c4x_label_ref_used_p (XVECEXP (x, i, j), code_label)) return 1; } return 0;}static intc4x_rptb_valid_p (insn, start_label) rtx insn, start_label;{ rtx end = insn; rtx start; rtx tmp; /* Find the start label. */ for (; insn; insn = PREV_INSN (insn)) if (insn == start_label) break; /* Note found then we can not use a rptb or rpts. The label was probably moved by the basic block reorder pass. */ if (! insn) return 0; start = insn; /* If any jump jumps inside this block then we must fail. */ for (insn = PREV_INSN (start); insn; insn = PREV_INSN (insn)) { if (GET_CODE (insn) == CODE_LABEL) { for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp)) if (GET_CODE (tmp) == JUMP_INSN && c4x_label_ref_used_p (tmp, insn)) return 0; } } for (insn = NEXT_INSN (end); insn; insn = NEXT_INSN (insn)) { if (GET_CODE (insn) == CODE_LABEL) { for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp)) if (GET_CODE (tmp) == JUMP_INSN && c4x_label_ref_used_p (tmp, insn)) return 0; } } /* If any jump jumps outside this block then we must fail. */ for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn)) { if (GET_CODE (insn) == CODE_LABEL) { for (tmp = NEXT_INSN (end); tmp; tmp = NEXT_INSN(tmp)) if (GET_CODE (tmp) == JUMP_INSN && c4x_label_ref_used_p (tmp, insn)) return 0; for (tmp = PREV_INSN (start); tmp; tmp = PREV_INSN(tmp)) if (GET_CODE (tmp) == JUMP_INSN && c4x_label_ref_used_p (tmp, insn)) return 0; } } /* All checks OK. */ return 1;}voidc4x_rptb_insert (insn) rtx insn;{ rtx end_label; rtx start_label; rtx new_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -