📄 bfin.c
字号:
case LTU: fprintf (file, "l"); break; case GEU: fprintf (file, "ge"); break; case LEU: fprintf (file, "le"); break; default: output_operand_lossage ("invalid %%j value"); } break; case 'J': /* reverse logic */ switch (GET_CODE(x)) { case EQ: fprintf (file, "ne"); break; case NE: fprintf (file, "e"); break; case GT: fprintf (file, "le"); break; case LT: fprintf (file, "ge"); break; case GE: fprintf (file, "l"); break; case LE: fprintf (file, "g"); break; case GTU: fprintf (file, "le"); break; case LTU: fprintf (file, "ge"); break; case GEU: fprintf (file, "l"); break; case LEU: fprintf (file, "g"); break; default: output_operand_lossage ("invalid %%J value"); } break; default: switch (GET_CODE (x)) { case REG: if (code == 'h') { gcc_assert (REGNO (x) < 32); fprintf (file, "%s", short_reg_names[REGNO (x)]); /*fprintf (file, "\n%d\n ", REGNO (x));*/ break; } else if (code == 'd') { gcc_assert (REGNO (x) < 32); fprintf (file, "%s", high_reg_names[REGNO (x)]); break; } else if (code == 'w') { gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1); fprintf (file, "%s.w", reg_names[REGNO (x)]); } else if (code == 'x') { gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1); fprintf (file, "%s.x", reg_names[REGNO (x)]); } else if (code == 'D') { fprintf (file, "%s", dregs_pair_names[REGNO (x)]); } else if (code == 'H') { gcc_assert (mode == DImode || mode == DFmode); gcc_assert (REG_P (x)); fprintf (file, "%s", reg_names[REGNO (x) + 1]); } else if (code == 'T') { if (REGNO (x) > 7) abort (); fprintf (file, "%s", byte_reg_names[REGNO (x)]); } else fprintf (file, "%s", reg_names[REGNO (x)]); break; case MEM: fputc ('[', file); x = XEXP (x,0); print_address_operand (file, x); fputc (']', file); break; case CONST_INT: /* Moves to half registers with d or h modifiers always use unsigned constants. */ if (code == 'd') x = GEN_INT ((INTVAL (x) >> 16) & 0xffff); else if (code == 'h') x = GEN_INT (INTVAL (x) & 0xffff); else if (code == 'X') x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x))); else if (code == 'Y') x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x))); else if (code == 'Z') /* Used for LINK insns. */ x = GEN_INT (-8 - INTVAL (x)); /* fall through */ case SYMBOL_REF: output_addr_const (file, x); if (code == 'G' && flag_pic) fprintf (file, "@GOT"); break; case CONST_DOUBLE: output_operand_lossage ("invalid const_double operand"); break; case UNSPEC: if (XINT (x, 1) == UNSPEC_MOVE_PIC) { output_addr_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@GOT"); } else if (XINT (x, 1) == UNSPEC_LIBRARY_OFFSET) fprintf (file, "_current_shared_library_p5_offset_"); else abort (); break; default: output_addr_const (file, x); } }}/* Argument support functions. *//* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. VDSP C Compiler manual, our ABI says that first 3 words of arguments will use R0, R1 and R2.*/voidinit_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype ATTRIBUTE_UNUSED, rtx libname ATTRIBUTE_UNUSED){ static CUMULATIVE_ARGS zero_cum; *cum = zero_cum; /* Set up the number of registers to use for passing arguments. */ cum->nregs = max_arg_registers; cum->arg_regs = arg_regs; return;}/* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. (TYPE is null for libcalls where that information may not be available.) */voidfunction_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED){ int count, bytes, words; bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; cum->words += words; cum->nregs -= words; if (cum->nregs <= 0) { cum->nregs = 0; cum->arg_regs = NULL; } else { for (count = 1; count <= words; count++) cum->arg_regs++; } return;}/* Define where to put the arguments to a function. Value is zero to push the argument on the stack, or a hard register in which to store the argument. MODE is the argument's machine mode. TYPE is the data type of the argument (as a tree). This is null for libcalls where that information may not be available. CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called. NAMED is nonzero if this argument is a named parameter (otherwise it is an extra parameter matching an ellipsis). */struct rtx_def *function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED){ int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); if (bytes == -1) return NULL_RTX; if (cum->nregs) return gen_rtx_REG (mode, *(cum->arg_regs)); return NULL_RTX;}/* For an arg passed partly in registers and partly in memory, this is the number of bytes passed in registers. For args passed entirely in registers or entirely in memory, zero. Refer VDSP C Compiler manual, our ABI. First 3 words are in registers. So, if a an argument is larger than the registers available, it will span the register and stack. */static intbfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED){ int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); int bytes_left = cum->nregs * UNITS_PER_WORD; if (bytes == -1) return 0; if (bytes_left == 0) return 0; if (bytes > bytes_left) return bytes_left; return 0;}/* Variable sized types are passed by reference. */static boolbfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, tree type, bool named ATTRIBUTE_UNUSED){ return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;}/* Decide whether a type should be returned in memory (true) or in a register (false). This is called by the macro RETURN_IN_MEMORY. */intbfin_return_in_memory (tree type){ int size; enum machine_mode mode = TYPE_MODE (type); if (mode == BLKmode) return 1; size = int_size_in_bytes (type); if (VECTOR_MODE_P (mode) || mode == TImode) { /* User-created vectors small enough to fit in REG. */ if (size < 8) return 0; if (size == 8 || size == 16) return 1; } if (size > 12) return 1; return 0;}/* Register in which address to store a structure value is passed to a function. */static rtxbfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED){ return gen_rtx_REG (Pmode, REG_P0);}/* Return true when register may be used to pass function parameters. */bool function_arg_regno_p (int n){ int i; for (i = 0; arg_regs[i] != -1; i++) if (n == arg_regs[i]) return true; return false;}/* Returns 1 if OP contains a symbol reference */intsymbolic_reference_mentioned_p (rtx op){ register const char *fmt; register int i; if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) return 1; fmt = GET_RTX_FORMAT (GET_CODE (op)); for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) { if (fmt[i] == 'E') { register int j; for (j = XVECLEN (op, i) - 1; j >= 0; j--) if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) return 1; } else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) return 1; } return 0;}/* Decide whether we can make a sibling call to a function. DECL is the declaration of the function being targeted by the call and EXP is the CALL_EXPR representing the call. */static boolbfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, tree exp ATTRIBUTE_UNUSED){ return true;}/* Emit RTL insns to initialize the variable parts of a trampoline at TRAMP. FNADDR is an RTX for the address of the function's pure code. CXT is an RTX for the static chain value for the function. */voidinitialize_trampoline (tramp, fnaddr, cxt) rtx tramp, fnaddr, cxt;{ rtx t1 = copy_to_reg (fnaddr); rtx t2 = copy_to_reg (cxt); rtx addr; addr = memory_address (Pmode, plus_constant (tramp, 2)); emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1)); emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16))); addr = memory_address (Pmode, plus_constant (tramp, 6)); emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1)); addr = memory_address (Pmode, plus_constant (tramp, 10)); emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2)); emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16))); addr = memory_address (Pmode, plus_constant (tramp, 14)); emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));}/* Legitimize PIC addresses. If the address is already position-independent, we return ORIG. Newly generated position-independent addresses go into a reg. This is REG if nonzero, otherwise we allocate register(s) as necessary. */rtxlegitimize_pic_address (rtx orig, rtx reg){ rtx addr = orig; rtx new = orig; if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) { if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr)) reg = new = orig; else { if (reg == 0) { if (no_new_pseudos) abort (); reg = gen_reg_rtx (Pmode); } if (flag_pic == 2) { emit_insn (gen_movsi_high_pic (reg, addr)); emit_insn (gen_movsi_low_pic (reg, reg, addr)); emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx)); new = gen_rtx_MEM (Pmode, reg); } else { rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_MOVE_PIC); new = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp)); } emit_move_insn (reg, new); } current_function_uses_pic_offset_table = 1; return reg; } else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) { rtx base; if (GET_CODE (addr) == CONST) { addr = XEXP (addr, 0); if (GET_CODE (addr) != PLUS) abort (); } if (XEXP (addr, 0) == pic_offset_table_rtx) return orig; if (reg == 0) { if (no_new_pseudos) abort (); reg = gen_reg_rtx (Pmode); } base = legitimize_pic_address (XEXP (addr, 0), reg); addr = legitimize_pic_address (XEXP (addr, 1), base == reg ? NULL_RTX : reg); if (GET_CODE (addr) == CONST_INT) { if (! reload_in_progress && ! reload_completed) addr = force_reg (Pmode, addr); else /* If we reach here, then something is seriously wrong. */ abort (); } if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1))) { base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0)); addr = XEXP (addr, 1); } return gen_rtx_PLUS (Pmode, base, addr); } return new;}/* Emit insns to move operands[1] into operands[0]. */voidemit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED){ rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) operands[1] = force_reg (SImode, operands[1]); else operands[1] = legitimize_pic_address (operands[1], temp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -