📄 cris.h
字号:
|| (BASE_P (XEXP (XEXP (X, 0), 0)) \ && BIAP_INDEX_P (XEXP (XEXP (X, 0), 1))) \ /* Same, but with swapped arguments. */ \ || (BASE_P (XEXP (XEXP (X, 0), 1)) \ && BIAP_INDEX_P (XEXP (XEXP (X, 0), 0)))))) \ )#define EXTRA_CONSTRAINT_S(X) \ (flag_pic && CONSTANT_P (X) && cris_gotless_symbol (X))#define EXTRA_CONSTRAINT_U(X) \ (flag_pic && CONSTANT_P (X) && cris_got_symbol (X))/* Node: Frame Layout */#define STACK_GROWS_DOWNWARD#define FRAME_GROWS_DOWNWARD/* It seems to be indicated in the code (at least 2.1) that this is better a constant, and best 0. */#define STARTING_FRAME_OFFSET 0#define FIRST_PARM_OFFSET(FNDECL) 0#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \ cris_return_addr_rtx (COUNT, FRAMEADDR)#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, CRIS_SRP_REGNUM)/* FIXME: Any __builtin_eh_return callers must not return anything and there must not be collisions with incoming parameters. Luckily the number of __builtin_eh_return callers is limited. For now return parameter registers in reverse order and hope for the best. */#define EH_RETURN_DATA_REGNO(N) \ (IN_RANGE ((N), 0, 3) ? (CRIS_FIRST_ARG_REG + 3 - (N)) : INVALID_REGNUM)/* Store the stack adjustment in the structure-return-address register. */#define CRIS_STACKADJ_REG CRIS_STRUCT_VALUE_REGNUM#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, CRIS_STACKADJ_REG)#define EH_RETURN_HANDLER_RTX \ cris_return_addr_rtx (0, NULL)#define INIT_EXPANDERS cris_init_expanders ()/* FIXME: Move this to right node (it's not documented properly yet). */#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (CRIS_SRP_REGNUM)/* FIXME: Move this to right node (it's not documented properly yet). FIXME: Check what alignment we can assume regarding TARGET_STACK_ALIGN and TARGET_ALIGN_BY_32. */#define DWARF_CIE_DATA_ALIGNMENT -1/* If we would ever need an exact mapping between canonical register number and dwarf frame register, we would either need to include all registers in the gcc description (with some marked fixed of course), or an inverse mapping from dwarf register to gcc register. There is one need in dwarf2out.c:expand_builtin_init_dwarf_reg_sizes. Right now, I don't see that we need exact correspondence between DWARF *frame* registers and DBX_REGISTER_NUMBER, so map them onto GCC registers. */#define DWARF_FRAME_REGNUM(REG) (REG)/* Node: Stack Checking *//* (no definitions) FIXME: Check. *//* Node: Frame Registers */#define STACK_POINTER_REGNUM 14/* Register used for frame pointer. This is also the last of the saved registers, when a frame pointer is not used. */#define FRAME_POINTER_REGNUM 8/* Faked register, is always eliminated. We need it to eliminate allocating stack slots for the return address and the frame pointer. */#define ARG_POINTER_REGNUM 17#define STATIC_CHAIN_REGNUM 7/* Node: Elimination *//* Really only needed if the stack frame has variable length (alloca or variable sized local arguments (GNU C extension). */#define FRAME_POINTER_REQUIRED 0#define ELIMINABLE_REGS \ {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}/* We need not worry about when the frame-pointer is required for other reasons. */#define CAN_ELIMINATE(FROM, TO) 1#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ (OFFSET) = cris_initial_elimination_offset (FROM, TO)/* Node: Stack Arguments *//* Since many parameters take up one register each in any case, defining TARGET_PROMOTE_PROTOTYPES that always returns true would seem like a good idea, but measurements indicate that a combination using PROMOTE_MODE is better. */#define ACCUMULATE_OUTGOING_ARGS 1#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0/* Node: Register Arguments *//* The void_type_node is sent as a "closing" call. */#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ ((CUM).regs < CRIS_MAX_ARGS_IN_REGS \ ? gen_rtx_REG (MODE, (CRIS_FIRST_ARG_REG) + (CUM).regs) \ : NULL_RTX)/* The differences between this and the previous, is that this one checks that an argument is named, since incoming stdarg/varargs arguments are pushed onto the stack, and we don't have to check against the "closing" void_type_node TYPE parameter. */#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ ((NAMED) && (CUM).regs < CRIS_MAX_ARGS_IN_REGS \ ? gen_rtx_REG (MODE, CRIS_FIRST_ARG_REG + (CUM).regs) \ : NULL_RTX)/* Contrary to what you'd believe, defining FUNCTION_ARG_CALLEE_COPIES seems like a (small total) loss, at least for gcc-2.7.2 compiling and running gcc-2.1 (small win in size, small loss running -- 100.1%), and similarly for size for products (.1 .. .3% bloat, sometimes win). Due to the empirical likeliness of making slower code, it is not defined. *//* This no longer *needs* to be a structure; but keeping it as such should not hurt (and hacking the ABI is simpler). */#define CUMULATIVE_ARGS struct cum_argsstruct cum_args {int regs;};/* The regs member is an integer, the number of arguments got into registers so far. */#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \ ((CUM).regs = 0)#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ ((CUM).regs += (3 + CRIS_FUNCTION_ARG_SIZE (MODE, TYPE)) / 4)#define FUNCTION_ARG_REGNO_P(REGNO) \ ((REGNO) >= CRIS_FIRST_ARG_REG \ && (REGNO) < CRIS_FIRST_ARG_REG + (CRIS_MAX_ARGS_IN_REGS))/* Node: Scalar Return *//* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the time being. */#define FUNCTION_VALUE(VALTYPE, FUNC) \ gen_rtx_REG (TYPE_MODE (VALTYPE), CRIS_FIRST_ARG_REG)#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, CRIS_FIRST_ARG_REG)#define FUNCTION_VALUE_REGNO_P(N) ((N) == CRIS_FIRST_ARG_REG)/* Node: Aggregate Return */#if 0/* FIXME: Let's try this some time, so we return structures in registers. We would cast the result of int_size_in_bytes to unsigned, so we will get a huge number for "structures" of variable size (-1). */#define RETURN_IN_MEMORY(TYPE) \ ((unsigned) int_size_in_bytes (TYPE) > CRIS_MAX_ARGS_IN_REGS * UNITS_PER_WORD)#endif#define CRIS_STRUCT_VALUE_REGNUM ((CRIS_FIRST_ARG_REG) - 1)/* Node: Caller Saves *//* (no definitions) *//* Node: Function entry *//* See cris.c for TARGET_ASM_FUNCTION_PROLOGUE and TARGET_ASM_FUNCTION_EPILOGUE. *//* If the epilogue uses the "ret" insn, we need to fill the delay slot. */#define DELAY_SLOTS_FOR_EPILOGUE cris_delay_slots_for_epilogue ()#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) \ cris_eligible_for_epilogue_delay (INSN)/* Node: Profiling */#define FUNCTION_PROFILER(FILE, LABELNO) \ error ("no FUNCTION_PROFILER for CRIS")/* FIXME: Some of the undefined macros might be mandatory. If so, fix documentation. *//* 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 *//* 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 \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -