📄 cris.h
字号:
#define SETUP_INCOMING_VARARGS(ARGSSF, MODE, TYPE, PRETEND, SECOND) \ do \ { \ if ((ARGSSF).regs < (CRIS_MAX_ARGS_IN_REGS)) \ (PRETEND) = ((CRIS_MAX_ARGS_IN_REGS) - (ARGSSF).regs) * 4; \ if (TARGET_PDEBUG) \ { \ fprintf (asm_out_file, \ "\n; VA:: ANSI: %d args before, anon @ #%d, %dtime\n", \ (ARGSSF).regs, PRETEND, SECOND); \ } \ } \ while (0)/* FIXME: This and other EXPAND_BUILTIN_VA_... target macros are not documented, although used by several targets. */#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \ cris_expand_builtin_va_arg (VALIST, TYPE)/* Node: Trampolines *//* This looks too complicated, and it is. I assigned r7 to be the static chain register, but it is call-saved, so we have to save it, and come back to restore it after the call, so we have to save srp... Anyway, trampolines are rare enough that we can cope with this somewhat lack of elegance. (Do not be tempted to "straighten up" whitespace in the asms; the assembler #NO_APP state mandates strict spacing). */#define TRAMPOLINE_TEMPLATE(FILE) \ do \ { \ fprintf (FILE, "\tmove.d $%s,[$pc+20]\n", \ reg_names[STATIC_CHAIN_REGNUM]); \ fprintf (FILE, "\tmove $srp,[$pc+22]\n"); \ fprintf (FILE, "\tmove.d 0,$%s\n", \ reg_names[STATIC_CHAIN_REGNUM]); \ fprintf (FILE, "\tjsr 0\n"); \ fprintf (FILE, "\tmove.d 0,$%s\n", \ reg_names[STATIC_CHAIN_REGNUM]); \ fprintf (FILE, "\tjump 0\n"); \ } \ while (0)#define TRAMPOLINE_SIZE 32/* CRIS wants instructions on word-boundary. Note that due to a bug (reported) in 2.7.2 and earlier, this is actually treated as alignment in _bytes_, not _bits_. (Obviously this is not fatal, only a slight waste of stack space). */#define TRAMPOLINE_ALIGNMENT 16#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ do \ { \ emit_move_insn (gen_rtx (MEM, SImode, \ plus_constant (TRAMP, 10)), \ CXT); \ emit_move_insn (gen_rtx (MEM, SImode, \ plus_constant (TRAMP, 16)), \ FNADDR); \ } \ while (0)/* Note that there is no need to do anything with the cache for sake of a trampoline. *//* Node: Library Calls */#define MULSI3_LIBCALL "__Mul"#define DIVSI3_LIBCALL "__Div"#define UDIVSI3_LIBCALL "__Udiv"#define MODSI3_LIBCALL "__Mod"#define UMODSI3_LIBCALL "__Umod"/* If you change this, you have to check whatever libraries and systems that use it. */#define TARGET_EDOM 33/* Node: Addressing Modes */#define HAVE_POST_INCREMENT 1#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)#define MAX_REGS_PER_ADDRESS 2/* There are helper macros defined here which are used only in GO_IF_LEGITIMATE_ADDRESS. Note that you *have to* reject invalid addressing modes for mode MODE, even if it is legal for normal addressing modes. You cannot rely on the constraints to do this work. They can only be used to doublecheck your intentions. One example is that you HAVE TO reject (mem:DI (plus:SI (reg:SI x) (reg:SI y))) because for some reason this cannot be reloaded. (Which of course you can argue that gcc should have done.) FIXME: Strange. Check. *//* No symbol can be used as an index (or more correct, as a base) together with a register with PIC; the PIC register must be there. */#define CONSTANT_INDEX_P(X) \ (CONSTANT_P (X) && !(flag_pic && cris_symbol (X)))/* True if X is a valid base register. */#define BASE_P(X) \ (REG_P (X) && REG_OK_FOR_BASE_P (X))/* True if X is a valid base register with or without autoincrement. */#define BASE_OR_AUTOINCR_P(X) \ (BASE_P (X) || (GET_CODE (X) == POST_INC && BASE_P (XEXP (X, 0))))/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */#define BDAP_INDEX_P(X) \ ((GET_CODE (X) == MEM && GET_MODE (X) == SImode \ && BASE_OR_AUTOINCR_P (XEXP (X, 0))) \ || (GET_CODE (X) == SIGN_EXTEND \ && GET_CODE (XEXP (X, 0)) == MEM \ && (GET_MODE (XEXP (X, 0)) == HImode \ || GET_MODE (XEXP (X, 0)) == QImode) \ && BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0))))/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */#define BIAP_INDEX_P(X) \ ((BASE_P (X) && REG_OK_FOR_INDEX_P (X)) \ || (GET_CODE (X) == MULT \ && BASE_P (XEXP (X, 0)) \ && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \ && GET_CODE (XEXP (X, 1)) == CONST_INT \ && (INTVAL (XEXP (X, 1)) == 2 \ || INTVAL (XEXP (X, 1)) == 4)))/* True if X is an address that doesn't need a prefix i.e. [Rs] or [Rs+]. */#define SIMPLE_ADDRESS_P(X) \ (BASE_P (X) \ || (GET_CODE (X) == POST_INC \ && BASE_P (XEXP (X, 0))))/* A PIC operand looks like a normal symbol here. At output we dress it in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local symbol) so we exclude all addressing modes where we can't replace a plain "symbol" with that. A global PIC symbol does not fit anywhere here (but is thankfully a general_operand in itself). A local PIC symbol is valid for the plain "symbol + offset" case. */#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ { \ rtx x1, x2; \ if (SIMPLE_ADDRESS_P (X)) \ goto ADDR; \ if (CONSTANT_P (X) \ && (! flag_pic \ || cris_gotless_symbol (X) \ || ! cris_symbol (X))) \ goto ADDR; \ /* Indexed? */ \ if (GET_CODE (X) == PLUS) \ { \ x1 = XEXP (X, 0); \ x2 = XEXP (X, 1); \ /* BDAP o, Rd. */ \ if ((BASE_P (x1) && CONSTANT_INDEX_P (x2)) \ || (BASE_P (x2) && CONSTANT_INDEX_P (x1)) \ /* BDAP Rs[+], Rd. */ \ || (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ && ((BASE_P (x1) && BDAP_INDEX_P (x2)) \ || (BASE_P (x2) && BDAP_INDEX_P (x1)) \ /* BIAP.m Rs, Rd */ \ || (BASE_P (x1) && BIAP_INDEX_P (x2)) \ || (BASE_P (x2) && BIAP_INDEX_P (x1))))) \ goto ADDR; \ } \ else if (GET_CODE (X) == MEM) \ { \ /* DIP (Rs). Reject [[reg+]] and [[reg]] for \ DImode (long long). */ \ if (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ && (BASE_P (XEXP (X, 0)) \ || BASE_OR_AUTOINCR_P (XEXP (X, 0)))) \ goto ADDR; \ } \ }#ifndef REG_OK_STRICT /* Nonzero if X is a hard reg that can be used as a base reg or if it is a pseudo reg. */# define REG_OK_FOR_BASE_P(X) \ (REGNO (X) <= CRIS_LAST_GENERAL_REGISTER \ || REGNO (X) == ARG_POINTER_REGNUM \ || REGNO (X) >= FIRST_PSEUDO_REGISTER)#else /* Nonzero if X is a hard reg that can be used as a base reg. */# define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))#endif#ifndef REG_OK_STRICT /* Nonzero if X is a hard reg that can be used as an index or if it is a pseudo reg. */# define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)#else /* Nonzero if X is a hard reg that can be used as an index. */# define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))#endif/* For now, don't do anything. GCC does a good job most often. Maybe we could do something about gcc:s misbehavior when it recalculates frame offsets for local variables, from fp+offs to sp+offs. The resulting address expression gets screwed up sometimes, but I'm not sure that it may be fixed here, since it is already split up in several instructions (Is this still true?). FIXME: Check and adjust for gcc-2.9x. */#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) {}/* Kludge to solve Axis-990219: Work around imperfection in reload_load_address1: (plus (sign_extend (mem:qi (reg))) (reg)) should be reloaded as (plus (reg) (reg)), not (plus (sign_extend (reg)) (reg)). There are no checks that reload_load_address_1 "reloads" addresses correctly, so invalidness is not caught or corrected. When the right thing happens in reload, the kludge can be removed; still not as of 2003-02-27. */#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \ do \ { \ if (GET_CODE (X) == PLUS \ && REG_P (XEXP (X, 1)) \ && GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \ && GET_CODE (XEXP (XEXP (X, 0), 0)) == MEM \ && (GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode \ || GET_MODE (XEXP (XEXP (X, 0), 0)) == QImode) \ && (REG_P (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ || (GET_CODE (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ == POST_INC \ && REG_P (XEXP (XEXP (XEXP (XEXP (X, 0), 0), 0), \ 0))))) \ { \ int something_reloaded = 0; \ \ if (REGNO (XEXP (X, 1)) >= FIRST_PSEUDO_REGISTER) \ { \ /* Second reg is pseudo, reload it. */ \ push_reload (XEXP (X, 1), NULL_RTX, &XEXP (X, 1), \ NULL, \ GENERAL_REGS, GET_MODE (X), VOIDmode, 0, 0, \ OPNUM, TYPE); \ something_reloaded = 1; \ } \ \ if (REG_P (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ && (REGNO (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ >= FIRST_PSEUDO_REGISTER)) \ { \ /* First one is a pseudo - reload that. */ \ push_reload (XEXP (XEXP (XEXP (X, 0), 0), 0), NULL_RTX, \ &XEXP (XEXP (XEXP (X, 0), 0), 0), NULL, \ GENERAL_REGS, \ GET_MODE (X), VOIDmode, 0, 0, OPNUM, TYPE); \ something_reloaded = 1; \ } \ \ if (! something_reloaded \ || (GET_CODE (XEXP (XEXP (X, 0), 0)) == POST_INC \ && (REGNO (XEXP (XEXP (XEXP (X, 0), 0), 0)) \ >= FIRST_PSEUDO_REGISTER))) \ /* Reload the sign_extend. Happens if neither reg is a \ pseudo, or the first one was inside post_increment. */ \ push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \ GENERAL_REGS, GET_MODE (X), VOIDmode, 0, 0, \ OPNUM, TYPE); \ goto WIN; \ } \ } \ while (0)/* In CRIS, only the postincrement address mode depends thus, since the increment depends on the size of the operand. */#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ do \ { \ if (GET_CODE (ADDR) == POST_INC) \ goto LABEL; \ } \ while (0)#define LEGITIMATE_CONSTANT_P(X) 1/* Node: Condition Code */#define NOTICE_UPDATE_CC(EXP, INSN) cris_notice_update_cc (EXP, INSN)/* FIXME: Maybe define CANONICALIZE_COMPARISON later, when playing with optimizations. It is needed; currently we do this with instruction patterns and NOTICE_UPDATE_CC. *//* Node: Costs */#define CONST_COSTS(RTX, CODE, OUTER_CODE) \ case CONST_INT: \ if (INTVAL (RTX) == 0) \ return 0; \ if (INTVAL (RTX) < 32 && INTVAL (RTX) >= -32) \ return 1; \ /* Eight or 16 bits are a word and cycle more expensive. */ \ if (INTVAL (RTX) <= 32767 && INTVAL (RTX) >= -32768) \ return 2; \ /* A 32 bit constant (or very seldom, unsigned 16 bits) costs \ another word. FIXME: This isn't linear to 16 bits. */ \ return 4; \ case LABEL_REF: \ return 6; \ case CONST: \ case SYMBOL_REF: \ /* For PIC, we need a prefix (if it isn't already there), \ and the PIC register. For a global PIC symbol, we also need a \ read of the GOT. */ \ return \ flag_pic ? (cris_got_symbol (RTX) ? (2 + 4 + 6) : (2 + 6)) : 6; \ case CONST_DOUBLE: \ if (RTX != CONST0_RTX (GET_MODE (RTX) == VOIDmode ? DImode \ : GET_MODE (RTX))) \ return 12; \ /* Make 0.0 cheap, else test-insns will not be used. */ \ return 0;#define RTX_COSTS(X, CODE, OUTER_CODE) \ case MULT: \ /* Identify values that are no powers of two. Powers of 2 are \ taken care of already and those values should not be \ changed. */ \ if (GET_CODE (XEXP (X, 1)) != CONST_INT \ || exact_log2 (INTVAL (XEXP (X, 1)) < 0)) \ { \ /* If we have a multiply insn, then the cost is between \ 1 and 2 "fast" instructions. */ \ if (TARGET_HAS_MUL_INSNS) \ return COSTS_N_INSNS (1) + COSTS_N_INSNS (1) /2; \ \ /* Estimate as 4 + 4 * #ofbits. */ \ return COSTS_N_INSNS (132); \ } \ break; \ case UDIV: \ case MOD: \ case UMOD: \ case DIV: \ if (GET_CODE (XEXP (X, 1)) != CONST_INT \ || exact_log2 (INTVAL (XEXP (X, 1)) < 0)) \ /* Estimate this as 4 + 8 * #of bits. */ \ return COSTS_N_INSNS (260); \ \ case AND: \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -