📄 m88k.h
字号:
of `FUNCTION_ARG' and other related values. It suffices to count the number of words of argument so far. */#define CUMULATIVE_ARGS int/* 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. */#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0)/* A C statement (sans semicolon) to update the summarizer variable CUM to advance past an argument in the argument list. The values MODE, TYPE and NAMED describe that argument. Once this is done, the variable CUM is suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. (TYPE is null for libcalls where that information may not be available.) */#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ do { \ enum machine_mode __mode = (TYPE) ? TYPE_MODE (TYPE) : (MODE); \ if ((CUM & 1) \ && (__mode == DImode || __mode == DFmode \ || ((TYPE) && TYPE_ALIGN (TYPE) > BITS_PER_WORD))) \ CUM++; \ CUM += (((__mode != BLKmode) \ ? GET_MODE_SIZE (MODE) : int_size_in_bytes (TYPE)) \ + 3) / 4; \ } while (0)/* True if N is a possible register number for function argument passing. On the m88000, these are registers 2 through 9. */#define FUNCTION_ARG_REGNO_P(N) ((N) <= 9 && (N) >= 2)/* A C expression which determines whether, and in which direction, to pad out an argument with extra space. The value should be of type `enum direction': either `upward' to pad above the argument, `downward' to pad below, or `none' to inhibit padding. This macro does not control the *amount* of padding; that is always just enough to reach the next multiple of `FUNCTION_ARG_BOUNDARY'. */#define FUNCTION_ARG_PADDING(MODE, TYPE) \ ((MODE) == BLKmode \ || ((TYPE) && (TREE_CODE (TYPE) == RECORD_TYPE \ || TREE_CODE (TYPE) == UNION_TYPE)) \ ? upward : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY ? downward : none)/* If defined, a C expression that gives the alignment boundary, in bits, of an argument with the specified mode and type. If it is not defined, `PARM_BOUNDARY' is used for all arguments. */#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ (((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ ? PARM_BOUNDARY : 2 * PARM_BOUNDARY)/* Generate necessary RTL for __builtin_saveregs(). ARGLIST is the argument list; see expr.c. */#define EXPAND_BUILTIN_SAVEREGS() m88k_builtin_saveregs ()/* Define the `__builtin_va_list' type for the ABI. */#define BUILD_VA_LIST_TYPE(VALIST) \ (VALIST) = m88k_build_va_list ()/* Implement `va_start' for varargs and stdarg. */#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ m88k_va_start (valist, nextarg)/* Implement `va_arg'. */#define EXPAND_BUILTIN_VA_ARG(valist, type) \ m88k_va_arg (valist, type)/* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. Redefined in sysv3.h, sysv4.h and dgux.h. */#define FUNCTION_PROFILER(FILE, LABELNO) \ output_function_profiler (FILE, LABELNO, "mcount", 1)/* Maximum length in instructions of the code output by FUNCTION_PROFILER. */#define FUNCTION_PROFILER_LENGTH (5+3+1+5)/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in functions that have frame pointers. No definition is equivalent to always zero. */#define EXIT_IGNORE_STACK (1)/* Value should be nonzero if functions must have frame pointers. Zero means the frame pointer need not be set up (and parms may be accessed via the stack pointer) in functions that seem suitable. This is computed in `reload', in reload1.c. */#define FRAME_POINTER_REQUIRED \((TARGET_OMIT_LEAF_FRAME_POINTER && !leaf_function_p ()) \ || (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION))/* Definitions for register eliminations. We have two registers that can be eliminated on the m88k. First, the frame pointer register can often be eliminated in favor of the stack pointer register. Secondly, the argument pointer register can always be eliminated; it is replaced with either the stack or frame pointer. *//* This is an array of structures. Each structure initializes one pair of eliminable registers. The "from" register number is given first, followed by "to". Eliminations of the same "from" register are listed in order of preference. */#define ELIMINABLE_REGS \{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}/* Given FROM and TO register numbers, say whether this elimination is allowed. */#define CAN_ELIMINATE(FROM, TO) \ (!((FROM) == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))/* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \{ m88k_layout_frame (); \ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ (OFFSET) = m88k_fp_offset; \ else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ (OFFSET) = m88k_stack_size - m88k_fp_offset; \ else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ (OFFSET) = m88k_stack_size; \ else \ abort (); \}/*** Trampolines for Nested Functions ***//* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. This block is placed on the stack and filled in. It is aligned 0 mod 128 and those portions that are executed are constant. This should work for instruction caches that have cache lines up to the aligned amount (128 is arbitrary), provided no other code producer is attempting to play the same game. This of course is in violation of any number of 88open standards. */#define TRAMPOLINE_TEMPLATE(FILE) \{ \ char buf[256]; \ static int labelno = 0; \ labelno++; \ ASM_GENERATE_INTERNAL_LABEL (buf, "LTRMP", labelno); \ /* Save the return address (r1) in the static chain reg (r11). */ \ fprintf (FILE, "\tor\t %s,%s,0\n", reg_names[11], reg_names[1]); \ /* Locate this block; transfer to the next instruction. */ \ fprintf (FILE, "\tbsr\t %s\n", &buf[1]); \ ASM_OUTPUT_INTERNAL_LABEL (FILE, "LTRMP", labelno); \ /* Save r10; use it as the relative pointer; restore r1. */ \ fprintf (FILE, "\tst\t %s,%s,24\n", reg_names[10], reg_names[1]); \ fprintf (FILE, "\tor\t %s,%s,0\n", reg_names[10], reg_names[1]); \ fprintf (FILE, "\tor\t %s,%s,0\n", reg_names[1], reg_names[11]); \ /* Load the function's address and go there. */ \ fprintf (FILE, "\tld\t %s,%s,32\n", reg_names[11], reg_names[10]); \ fprintf (FILE, "\tjmp.n\t %s\n", reg_names[11]); \ /* Restore r10 and load the static chain register. */ \ fprintf (FILE, "\tld.d\t %s,%s,24\n", reg_names[10], reg_names[10]); \ /* Storage: r10 save area, static chain, function address. */ \ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \}/* Length in units of the trampoline for entering a nested function. This is really two components. The first 32 bytes are fixed and must be copied; the last 12 bytes are just storage that's filled in later. So for allocation purposes, it's 32+12 bytes, but for initialization purposes, it's 32 bytes. */#define TRAMPOLINE_SIZE (32+12)/* Alignment required for a trampoline. 128 is used to find the beginning of a line in the instruction cache and to allow for instruction cache lines of up to 128 bytes. */#define TRAMPOLINE_ALIGNMENT 128/* Emit RTL insns to initialize the variable parts of a trampoline. 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. */#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \{ \ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 40)), FNADDR); \ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 36)), CXT); \}/*** Library Subroutine Names ***//* Define this macro if GNU CC should generate calls to the System V (and ANSI C) library functions `memcpy' and `memset' rather than the BSD functions `bcopy' and `bzero'. */#define TARGET_MEM_FUNCTIONS/*** Addressing Modes ***/#define SELECT_CC_MODE(OP,X,Y) CCmode/* #define HAVE_POST_INCREMENT 0 *//* #define HAVE_POST_DECREMENT 0 *//* #define HAVE_PRE_DECREMENT 0 *//* #define HAVE_PRE_INCREMENT 0 *//* Recognize any constant value that is a valid address. When PIC, we do not accept an address that would require a scratch reg to load into a register. */#define CONSTANT_ADDRESS_P(X) \ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ || (GET_CODE (X) == CONST \ && ! (flag_pic && pic_address_needs_scratch (X))))/* Maximum number of registers that can appear in a valid memory address. */#define MAX_REGS_PER_ADDRESS 2/* The condition for memory shift insns. */#define SCALED_ADDRESS_P(ADDR) \ (GET_CODE (ADDR) == PLUS \ && (GET_CODE (XEXP (ADDR, 0)) == MULT \ || GET_CODE (XEXP (ADDR, 1)) == MULT))/* Can the reference to X be made short? */#define SHORT_ADDRESS_P(X,TEMP) \ ((TEMP) = (GET_CODE (X) == CONST ? get_related_value (X) : X), \ ((TEMP) && GET_CODE (TEMP) == SYMBOL_REF && SYMBOL_REF_FLAG (TEMP)))/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a valid memory address for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. On the m88000, a legitimate address has the form REG, REG+REG, REG+SMALLINT, REG+(REG*modesize) (REG[REG]), or SMALLINT. The register elimination process should deal with the argument pointer and frame pointer changing to REG+SMALLINT. */#define LEGITIMATE_INDEX_P(X, MODE) \ ((GET_CODE (X) == CONST_INT \ && SMALL_INT (X)) \ || (REG_P (X) \ && REG_OK_FOR_INDEX_P (X)) \ || (GET_CODE (X) == MULT \ && REG_P (XEXP (X, 0)) \ && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \ && GET_CODE (XEXP (X, 1)) == CONST_INT \ && INTVAL (XEXP (X, 1)) == GET_MODE_SIZE (MODE)))#define RTX_OK_FOR_BASE_P(X) \ ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ || (GET_CODE (X) == SUBREG \ && GET_CODE (SUBREG_REG (X)) == REG \ && REG_OK_FOR_BASE_P (SUBREG_REG (X))))#define RTX_OK_FOR_INDEX_P(X) \ ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ || (GET_CODE (X) == SUBREG \ && GET_CODE (SUBREG_REG (X)) == REG \ && REG_OK_FOR_INDEX_P (SUBREG_REG (X))))#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \{ \ register rtx _x; \ if (REG_P (X)) \ { \ if (REG_OK_FOR_BASE_P (X)) \ goto ADDR; \ } \ else if (GET_CODE (X) == PLUS) \ { \ register rtx _x0 = XEXP (X, 0); \ register rtx _x1 = XEXP (X, 1); \ if ((flag_pic \ && _x0 == pic_offset_table_rtx \ && (flag_pic == 2 \ ? RTX_OK_FOR_BASE_P (_x1) \ : (GET_CODE (_x1) == SYMBOL_REF \ || GET_CODE (_x1) == LABEL_REF))) \ || (REG_P (_x0) \ && (REG_OK_FOR_BASE_P (_x0) \ && LEGITIMATE_INDEX_P (_x1, MODE))) \ || (REG_P (_x1) \ && (REG_OK_FOR_BASE_P (_x1) \ && LEGITIMATE_INDEX_P (_x0, MODE)))) \ goto ADDR; \ } \ else if (GET_CODE (X) == LO_SUM) \ { \ register rtx _x0 = XEXP (X, 0); \ register rtx _x1 = XEXP (X, 1); \ if (((REG_P (_x0) \ && REG_OK_FOR_BASE_P (_x0)) \ || (GET_CODE (_x0) == SUBREG \ && REG_P (SUBREG_REG (_x0)) \ && REG_OK_FOR_BASE_P (SUBREG_REG (_x0)))) \ && CONSTANT_P (_x1)) \ goto ADDR; \ } \ else if (GET_CODE (X) == CONST_INT \ && SMALL_INT (X)) \ goto ADDR; \ else if (SHORT_ADDRESS_P (X, _x)) \ goto ADDR; \}/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. We have two alternate definitions for each of them. The usual definition accepts all pseudo regs; the other rejects them unless they have been allocated suitable hard regs. The symbol REG_OK_STRICT causes the latter definition to be used. Most source files want to accept pseudo regs in the hope that they will get allocated to the class that the insn wants them to be in. Source files for reload pass need to be strict. After reload, it makes no difference, since pseudo regs have been eliminated by then. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -