📄 cris.c
字号:
cris_cfun_uses_pic_table (){ return current_function_uses_pic_offset_table;}/* Given an rtx, return the text string corresponding to the CODE of X. Intended for use in the assembly language output section of a define_insn. */const char *cris_op_str (x) rtx x;{ cris_output_insn_is_bound = 0; switch (GET_CODE (x)) { case PLUS: return "add"; break; case MINUS: return "sub"; break; case MULT: return "mul"; break; case DIV: return "div"; break; case AND: return "and"; break; case IOR: return "or"; break; case XOR: return "xor"; break; case NOT: return "not"; break; case ASHIFT: return "lsl"; break; case LSHIFTRT: return "lsr"; break; case ASHIFTRT: return "asr"; break; case UMIN: /* Used to control the sign/zero-extend character for the 'e' modifier. BOUND has none. */ cris_output_insn_is_bound = 1; return "bound"; break; default: return "Unknown operator"; break; }}/* Emit an error message when we're in an asm, and a fatal error for "normal" insns. Formatted output isn't easily implemented, since we use output_operand_lossage to output the actual message and handle the categorization of the error. */static voidcris_operand_lossage (msgid, op) const char *msgid; rtx op;{ debug_rtx (op); output_operand_lossage ("%s", msgid);}/* Print an index part of an address to file. */static voidcris_print_index (index, file) rtx index; FILE * file;{ rtx inner = XEXP (index, 0); /* Make the index "additive" unless we'll output a negative number, in which case the sign character is free (as in free beer). */ if (GET_CODE (index) != CONST_INT || INTVAL (index) >= 0) putc ('+', file); if (REG_P (index)) fprintf (file, "$%s.b", reg_names[REGNO (index)]); else if (CONSTANT_P (index)) cris_output_addr_const (file, index); else if (GET_CODE (index) == MULT) { fprintf (file, "$%s.", reg_names[REGNO (XEXP (index, 0))]); putc (INTVAL (XEXP (index, 1)) == 2 ? 'w' : 'd', file); } else if (GET_CODE (index) == SIGN_EXTEND && GET_CODE (inner) == MEM) { rtx inner_inner = XEXP (inner, 0); if (GET_CODE (inner_inner) == POST_INC) { fprintf (file, "[$%s+].", reg_names[REGNO (XEXP (inner_inner, 0))]); putc (GET_MODE (inner) == HImode ? 'w' : 'b', file); } else { fprintf (file, "[$%s].", reg_names[REGNO (inner_inner)]); putc (GET_MODE (inner) == HImode ? 'w' : 'b', file); } } else if (GET_CODE (index) == MEM) { if (GET_CODE (inner) == POST_INC) fprintf (file, "[$%s+].d", reg_names[REGNO (XEXP (inner, 0))]); else fprintf (file, "[$%s].d", reg_names[REGNO (inner)]); } else cris_operand_lossage ("unexpected index-type in cris_print_index", index);}/* Print a base rtx of an address to file. */static voidcris_print_base (base, file) rtx base; FILE *file;{ if (REG_P (base)) fprintf (file, "$%s", reg_names[REGNO (base)]); else if (GET_CODE (base) == POST_INC) fprintf (file, "$%s+", reg_names[REGNO (XEXP (base, 0))]); else cris_operand_lossage ("unexpected base-type in cris_print_base", base);}/* Usable as a guard in expressions. */intcris_fatal (arg) char *arg;{ internal_error (arg); /* We'll never get here; this is just to appease compilers. */ return 0;}/* Textual function prologue. */static voidcris_target_asm_function_prologue (file, size) FILE *file; HOST_WIDE_INT size;{ int regno; /* Shorten the used name for readability. */ int cfoa_size = current_function_outgoing_args_size; int last_movem_reg = -1; int doing_dwarf = dwarf2out_do_frame (); int framesize; int faked_args_size = 0; int cfa_write_offset = 0; char *cfa_label = NULL; int return_address_on_stack = regs_ever_live[CRIS_SRP_REGNUM] || cfun->machine->needs_return_address_on_stack != 0; /* Don't do anything if no prologues or epilogues are wanted. */ if (!TARGET_PROLOGUE_EPILOGUE) return; if (size < 0) abort (); /* Align the size to what's best for the CPU model. */ if (TARGET_STACK_ALIGN) size = TARGET_ALIGN_BY_32 ? (size + 3) & ~3 : (size + 1) & ~1; if (current_function_pretend_args_size) { int pretend = current_function_pretend_args_size; for (regno = CRIS_FIRST_ARG_REG + CRIS_MAX_ARGS_IN_REGS - 1; pretend > 0; regno--, pretend -= 4) { fprintf (file, "\tpush $%s\n", reg_names[regno]); faked_args_size += 4; } } framesize = faked_args_size; if (doing_dwarf) { /* FIXME: Slightly redundant calculation, as we do the same in pieces below. This offset must be the total adjustment of the stack-pointer. We can then def_cfa call at the end of this function with the current implementation of execute_cfa_insn, but that wouldn't really be clean. */ int cfa_offset = faked_args_size + (return_address_on_stack ? 4 : 0) + (frame_pointer_needed ? 4 : 0); int cfa_reg; if (frame_pointer_needed) cfa_reg = FRAME_POINTER_REGNUM; else { cfa_reg = STACK_POINTER_REGNUM; cfa_offset += cris_initial_frame_pointer_offset (); } cfa_label = dwarf2out_cfi_label (); dwarf2out_def_cfa (cfa_label, cfa_reg, cfa_offset); cfa_write_offset = - faked_args_size - 4; } /* Save SRP if not a leaf function. */ if (return_address_on_stack) { fprintf (file, "\tPush $srp\n"); framesize += 4; if (doing_dwarf) { dwarf2out_return_save (cfa_label, cfa_write_offset); cfa_write_offset -= 4; } } /* Set up frame pointer if needed. */ if (frame_pointer_needed) { fprintf (file, "\tpush $%s\n\tmove.d $sp,$%s\n", reg_names[FRAME_POINTER_REGNUM], reg_names[FRAME_POINTER_REGNUM]); framesize += 4; if (doing_dwarf) { dwarf2out_reg_save (cfa_label, FRAME_POINTER_REGNUM, cfa_write_offset); cfa_write_offset -= 4; } } /* Local vars are located above saved regs. */ cfa_write_offset -= size; /* Get a contiguous sequence of registers, starting with r0, that need to be saved. */ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) { if ((((regs_ever_live[regno] && !call_used_regs[regno]) || (regno == (int) PIC_OFFSET_TABLE_REGNUM && (current_function_uses_pic_offset_table /* It is saved anyway, if there would be a gap. */ || (flag_pic && regs_ever_live[regno + 1] && !call_used_regs[regno + 1])))) && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed) && regno != CRIS_SRP_REGNUM) || (current_function_calls_eh_return && (regno == EH_RETURN_DATA_REGNO (0) || regno == EH_RETURN_DATA_REGNO (1) || regno == EH_RETURN_DATA_REGNO (2) || regno == EH_RETURN_DATA_REGNO (3)))) { /* Check if movem may be used for registers so far. */ if (regno == last_movem_reg + 1) /* Yes, update next expected register. */ last_movem_reg++; else { /* We cannot use movem for all registers. We have to flush any movem:ed registers we got so far. */ if (last_movem_reg != -1) { /* It is a win to use a side-effect assignment for 64 <= size <= 128. But side-effect on movem was not usable for CRIS v0..3. Also only do it if side-effects insns are allowed. */ if ((last_movem_reg + 1) * 4 + size >= 64 && (last_movem_reg + 1) * 4 + size <= 128 && cris_cpu_version >= CRIS_CPU_SVINTO && TARGET_SIDE_EFFECT_PREFIXES) fprintf (file, "\tmovem $%s,[$sp=$sp-%d]\n", reg_names[last_movem_reg], (last_movem_reg + 1) * 4 + size); else { /* Avoid printing multiple subsequent sub:s for sp. */ fprintf (file, "\tsub%s %d,$sp\n", ADDITIVE_SIZE_MODIFIER ((last_movem_reg + 1) * 4 + size), (last_movem_reg + 1) * 4 + size); fprintf (file, "\tmovem $%s,[$sp]\n", reg_names[last_movem_reg]); } framesize += (last_movem_reg + 1) * 4 + size; if (TARGET_PDEBUG) fprintf (file, "; frame %d, #regs %d, bytes %d args %d\n", size, last_movem_reg + 1, (last_movem_reg + 1) * 4, current_function_args_size); last_movem_reg = -1; size = 0; } else if (size > 0) { /* Local vars on stack, but there are no movem:s. Just allocate space. */ fprintf (file, "\tSub%s %d,$sp\n", ADDITIVE_SIZE_MODIFIER (size), size); framesize += size; size = 0; } fprintf (file, "\tPush $%s\n", reg_names[regno]); framesize += 4; } if (doing_dwarf) { /* Registers are stored lowest numbered at highest address, which matches the loop order; we just need to update the write-offset. */ dwarf2out_reg_save (cfa_label, regno, cfa_write_offset); cfa_write_offset -= 4; } } } /* Check after, if we can movem all registers. This is the normal case. */ if (last_movem_reg != -1) { /* Side-effect assignment on movem was not supported for CRIS v0..3, and don't do it if we're asked not to. The movem is already accounted for, for unwind. */ if ((last_movem_reg + 1) * 4 + size >= 64 && (last_movem_reg + 1) * 4 + size <= 128 && cris_cpu_version >= CRIS_CPU_SVINTO && TARGET_SIDE_EFFECT_PREFIXES) fprintf (file, "\tmovem $%s,[$sp=$sp-%d]\n", reg_names[last_movem_reg], (last_movem_reg+1) * 4 + size); else { /* Avoid printing multiple subsequent sub:s for sp. FIXME: Clean up the conditional expression. */ fprintf (file, "\tsub%s %d,$sp\n", ADDITIVE_SIZE_MODIFIER ((last_movem_reg + 1) * 4 + size), (last_movem_reg + 1) * 4 + size); /* To be compatible with v0..v3 means we do not use an assignment addressing mode with movem. We normally don't need that anyway. It would only be slightly more efficient for 64..128 bytes frame size. */ fprintf (file, "\tmovem $%s,[$sp]\n", reg_names[last_movem_reg]); } framesize += (last_movem_reg + 1) * 4 + size; if (TARGET_PDEBUG) fprintf (file, "; frame %d, #regs %d, bytes %d args %d\n", size, last_movem_reg + 1, (last_movem_reg + 1) * 4, current_function_args_size); /* We have to put outgoing argument space after regs. */ if (cfoa_size) { /* This does not need to be accounted for, for unwind. */ fprintf (file, "\tSub%s %d,$sp\n", ADDITIVE_SIZE_MODIFIER (cfoa_size), cfoa_size); framesize += cfoa_size; } } else if ((size + cfoa_size) > 0) { /* This does not need to be accounted for, for unwind. */ /* Local vars on stack, and we could not use movem. Add a sub here. */ fprintf (file, "\tSub%s %d,$sp\n", ADDITIVE_SIZE_MODIFIER (size + cfoa_size), cfoa_size + size); framesize += size + cfoa_size; } /* Set up the PIC register. */ if (current_function_uses_pic_offset_table) fprintf (file, "\tmove.d $pc,$%s\n\tsub.d .:GOTOFF,$%s\n", reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[PIC_OFFSET_TABLE_REGNUM]); if (TARGET_PDEBUG) fprintf (file, "; parm #%d @ %d; frame %d, FP-SP is %d; leaf: %s%s; fp %s, outg: %d arg %d\n", CRIS_MAX_ARGS_IN_REGS + 1, FIRST_PARM_OFFSET (0), get_frame_size (), cris_initial_frame_pointer_offset (), leaf_function_p () ? "yes" : "no", return_address_on_stack ? "no" :"yes", frame_pointer_needed ? "yes" : "no", cfoa_size, current_function_args_size); if (cris_max_stackframe && framesize > cris_max_stackframe) warning ("stackframe too big: %d bytes", framesize);}/* Return nonzero if there are regs mentioned in the insn that are not all in the call_used regs. This is part of the decision whether an insn can be put in the epilogue. */static intsaved_regs_mentioned (x) rtx x;{ int i; const char *fmt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -