📄 c4x.c
字号:
return 1; case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC: return 1; /* These shouldn't be directly generated. */ case SYMBOL_REF: case LABEL_REF: case CONST: return 10; case LO_SUM: { rtx op1 = XEXP (addr, 1); if (GET_CODE (op1) == LABEL_REF || GET_CODE (op1) == SYMBOL_REF) return TARGET_SMALL ? 3 : 4; if (GET_CODE (op1) == CONST) { rtx offset = const0_rtx; op1 = eliminate_constant_term (op1, &offset); /* ??? These costs need rethinking... */ if (GET_CODE (op1) == LABEL_REF) return 3; if (GET_CODE (op1) != SYMBOL_REF) return 4; if (INTVAL (offset) == 0) return 3; return 4; } fatal_insn ("c4x_address_cost: Invalid addressing mode", addr); } break; case PLUS: { register rtx op0 = XEXP (addr, 0); register rtx op1 = XEXP (addr, 1); if (GET_CODE (op0) != REG) break; switch (GET_CODE (op1)) { default: break; case REG: /* This cost for REG+REG must be greater than the cost for REG if we want autoincrement addressing modes. */ return 2; case CONST_INT: if (IS_DISP1_CONST (INTVAL (op1))) return 1; if (! TARGET_C3X && IS_UINT5_CONST (INTVAL (op1))) return 2; return 3; } } default: } return 4;}rtxc4x_gen_compare_reg (code, x, y) enum rtx_code code; rtx x, y;{ enum machine_mode mode = SELECT_CC_MODE (code, x, y); rtx cc_reg; if (mode == CC_NOOVmode && (code == LE || code == GE || code == LT || code == GT)) return NULL_RTX; cc_reg = gen_rtx_REG (mode, ST_REGNO); emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y))); return cc_reg;}char *c4x_output_cbranch (form, seq) char *form; rtx seq;{ int delayed = 0; int annultrue = 0; int annulfalse = 0; rtx delay; char *cp; static char str[100]; if (final_sequence) { delay = XVECEXP (final_sequence, 0, 1); delayed = ! INSN_ANNULLED_BRANCH_P (seq); annultrue = INSN_ANNULLED_BRANCH_P (seq) && ! INSN_FROM_TARGET_P (delay); annulfalse = INSN_ANNULLED_BRANCH_P (seq) && INSN_FROM_TARGET_P (delay); } strcpy (str, form); cp = &str [strlen (str)]; if (delayed) { *cp++ = '%'; *cp++ = '#'; } if (annultrue) { *cp++ = 'a'; *cp++ = 't'; } if (annulfalse) { *cp++ = 'a'; *cp++ = 'f'; } *cp++ = '\t'; *cp++ = '%'; *cp++ = 'l'; *cp++ = '1'; *cp = 0; return str;}voidc4x_print_operand (file, op, letter) FILE *file; /* file to write to */ rtx op; /* operand to print */ int letter; /* %<letter> or 0 */{ rtx op1; enum rtx_code code; switch (letter) { case '#': /* delayed */ if (final_sequence) asm_fprintf (file, "d"); return; } code = GET_CODE (op); switch (letter) { case 'A': /* direct address */ if (code == CONST_INT || code == SYMBOL_REF) asm_fprintf (file, "@"); break; case 'H': /* sethi */ output_addr_const (file, op); return; case 'I': /* reversed condition */ code = reverse_condition (code); break; case 'L': /* log 2 of constant */ if (code != CONST_INT) fatal_insn ("c4x_print_operand: %%L inconsistency", op); fprintf (file, "%d", exact_log2 (INTVAL (op))); return; case 'N': /* ones complement of small constant */ if (code != CONST_INT) fatal_insn ("c4x_print_operand: %%N inconsistency", op); fprintf (file, "%d", ~INTVAL (op)); return; case 'K': /* generate ldp(k) if direct address */ if (! TARGET_SMALL && code == MEM && GET_CODE (XEXP (op, 0)) == LO_SUM && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG && REGNO (XEXP (XEXP (op, 0), 0)) == DP_REGNO) { op1 = XEXP (XEXP (op, 0), 1); if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF) { asm_fprintf (file, "\t%s\t", TARGET_C3X ? "ldp" : "ldpk"); output_address (XEXP (adj_offsettable_operand (op, 1), 0)); asm_fprintf (file, "\n"); } } return; case 'M': /* generate ldp(k) if direct address */ if (! TARGET_SMALL /* only used in asm statements */ && code == MEM && (GET_CODE (XEXP (op, 0)) == CONST || GET_CODE (XEXP (op, 0)) == SYMBOL_REF)) { asm_fprintf (file, "%s\t", TARGET_C3X ? "ldp" : "ldpk"); output_address (XEXP (op, 0)); asm_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 (adj_offsettable_operand (op, 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) asm_fprintf (file, "u"); return; default: break; } switch (code) { case REG: if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT) 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[30]; REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_TO_DECIMAL (r, "%20f", str); fprintf (file, "%s", str); } break; case CONST_INT: fprintf (file, "%d", INTVAL (op)); break; case NE: asm_fprintf (file, "ne"); break; case EQ: asm_fprintf (file, "eq"); break; case GE: asm_fprintf (file, "ge"); break; case GT: asm_fprintf (file, "gt"); break; case LE: asm_fprintf (file, "le"); break; case LT: asm_fprintf (file, "lt"); break; case GEU: asm_fprintf (file, "hs"); break; case GTU: asm_fprintf (file, "hi"); break; case LEU: asm_fprintf (file, "ls"); break; case LTU: asm_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_REGNO (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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -