📄 m88k.h
字号:
target_flags |= MASK_USE_DIV; \ target_flags &= ~MASK_CHECK_ZERO_DIV; \ } \ \ m88k_cpu = (TARGET_88000 ? PROCESSOR_M88000 \ : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88110)); \ \ if (TARGET_BIG_PIC) \ flag_pic = 2; \ \ if ((target_flags & MASK_EITHER_LARGE_SHIFT) == MASK_EITHER_LARGE_SHIFT) \ error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");\ \ if (TARGET_SVR4) \ { \ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) \ reg_names[i]--; \ m88k_pound_sign = "#"; \ } \ else \ { \ target_flags |= MASK_SVR3; \ target_flags &= ~MASK_SVR4; \ } \ \ if (m88k_short_data) \ { \ char *p = m88k_short_data; \ while (*p) \ if (*p >= '0' && *p <= '9') \ p++; \ else \ { \ error ("Invalid option `-mshort-data-%s'", m88k_short_data); \ break; \ } \ m88k_gp_threshold = atoi (m88k_short_data); \ if (m88k_gp_threshold > 0x7fffffff) \ error ("-mshort-data-%s is too large ", m88k_short_data); \ if (flag_pic) \ error ("-mshort-data-%s and PIC are incompatible", m88k_short_data); \ } \ if (TARGET_OMIT_LEAF_FRAME_POINTER) /* keep nonleaf frame pointers */ \ flag_omit_frame_pointer = 1; \ } while (0)/*** Storage Layout ***//* Sizes in bits of the various types. */#define CHAR_TYPE_SIZE 8#define SHORT_TYPE_SIZE 16#define INT_TYPE_SIZE 32#define LONG_TYPE_SIZE 32#define LONG_LONG_TYPE_SIZE 64#define FLOAT_TYPE_SIZE 32#define DOUBLE_TYPE_SIZE 64#define LONG_DOUBLE_TYPE_SIZE 64/* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. Somewhat arbitrary. It matches the bit field patterns. */#define BITS_BIG_ENDIAN 1/* Define this if most significant byte of a word is the lowest numbered. That is true on the m88000. */#define BYTES_BIG_ENDIAN 1/* Define this if most significant word of a multiword number is the lowest numbered. For the m88000 we can decide arbitrarily since there are no machine instructions for them. */#define WORDS_BIG_ENDIAN 1/* Number of bits in an addressable storage unit */#define BITS_PER_UNIT 8/* Width in bits of a "word", which is the contents of a machine register. Note that this is not necessarily the width of data type `int'; if using 16-bit ints on a 68000, this would still be 32. But on a machine with 16-bit registers, this would be 16. */#define BITS_PER_WORD 32/* Width of a word, in units (bytes). */#define UNITS_PER_WORD 4/* Width in bits of a pointer. See also the macro `Pmode' defined below. */#define POINTER_SIZE 32/* Allocation boundary (in *bits*) for storing arguments in argument list. */#define PARM_BOUNDARY 32/* Largest alignment for stack parameters (if greater than PARM_BOUNDARY). */#define MAX_PARM_BOUNDARY 64/* Boundary (in *bits*) on which stack pointer should be aligned. */#define STACK_BOUNDARY 128/* Allocation boundary (in *bits*) for the code of a function. On the m88100, it is desirable to align to a cache line. However, SVR3 targets only provided 8 byte alignment. The m88110 cache is small, so align to an 8 byte boundary. Pack code tightly when compiling crtstuff.c. */#define FUNCTION_BOUNDARY (flag_inhibit_size_directive ? 32 : \ (TARGET_88100 && TARGET_SVR4 ? 128 : 64))/* No data type wants to be aligned rounder than this. */#define BIGGEST_ALIGNMENT 64/* The best alignment to use in cases where we have a choice. */#define FASTEST_ALIGNMENT (TARGET_88100 ? 32 : 64)/* Make strings 4/8 byte aligned so strcpy from constants will be faster. */#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ ((TREE_CODE (EXP) == STRING_CST \ && (ALIGN) < FASTEST_ALIGNMENT) \ ? FASTEST_ALIGNMENT : (ALIGN))/* Make arrays of chars 4/8 byte aligned for the same reasons. */#define DATA_ALIGNMENT(TYPE, ALIGN) \ (TREE_CODE (TYPE) == ARRAY_TYPE \ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))/* Alignment of field after `int : 0' in a structure. Ignored with PCC_BITFIELD_TYPE_MATTERS. *//* #define EMPTY_FIELD_BOUNDARY 8 *//* Every structure's size must be a multiple of this. */#define STRUCTURE_SIZE_BOUNDARY 8/* Set this nonzero if move instructions will actually fail to work when given unaligned data. */#define STRICT_ALIGNMENT 1/* A bitfield declared as `int' forces `int' alignment for the struct. */#define PCC_BITFIELD_TYPE_MATTERS 1/* Maximum size (in bits) to use for the largest integral type that replaces a BLKmode type. *//* #define MAX_FIXED_MODE_SIZE 0 *//* Check a `double' value for validity for a particular machine mode. This is defined to avoid crashes outputting certain constants. Since we output the number in hex, the assembler won't choke on it. *//* #define CHECK_FLOAT_VALUE(MODE,VALUE) *//* A code distinguishing the floating point format of the target machine. *//* #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT *//*** Register Usage ***//* Number of actual hardware registers. The hardware registers are assigned numbers for the compiler from 0 to just below FIRST_PSEUDO_REGISTER. All registers that the compiler knows about must be given numbers, even those that are not normally considered general registers. The m88100 has a General Register File (GRF) of 32 32-bit registers. The m88110 adds an Extended Register File (XRF) of 32 80-bit registers. */#define FIRST_PSEUDO_REGISTER 64#define FIRST_EXTENDED_REGISTER 32/* General notes on extended registers, their use and misuse. Possible good uses: spill area instead of memory. -waste if only used once floating point calculations -probably a waste unless we have run out of general purpose registers freeing up general purpose registers -e.g. may be able to have more loop invariants if floating point is moved into extended registers. I've noticed wasteful moves into and out of extended registers; e.g. a load into x21, then inside a loop a move into r24, then r24 used as input to an fadd. Why not just load into r24 to begin with? Maybe the new cse.c will address this. This wastes a move, but the load,store and move could have been saved had extended registers been used throughout. E.g. in the code following code, if z and xz are placed in extended registers, there is no need to save preserve registers. long c=1,d=1,e=1,f=1,g=1,h=1,i=1,j=1,k; double z=0,xz=4.5; foo(a,b) long a,b; { while (a < b) { k = b + c + d + e + f + g + h + a + i + j++; z += xz; a++; } printf("k= %d; z=%f;\n", k, z); } I've found that it is possible to change the constraints (putting * before the 'r' constraints int the fadd.ddd instruction) and get the entire addition and store to go into extended registers. However, this also forces simple addition and return of floating point arguments to a function into extended registers. Not the correct solution. Found the following note in local-alloc.c which may explain why I can't get both registers to be in extended registers since two are allocated in local-alloc and one in global-alloc. Doesn't explain (I don't believe) why an extended register is used instead of just using the preserve register. from local-alloc.c: We have provision to exempt registers, even when they are contained within the block, that can be tied to others that are not contained in it. This is so that global_alloc could process them both and tie them then. But this is currently disabled since tying in global_alloc is not yet implemented. The explanation of why the preserved register is not used is as follows, I believe. The registers are being allocated in order. Tying is not done so efficiently, so when it comes time to do the first allocation, there are no registers left to use without spilling except extended registers. Then when the next pseudo register needs a hard reg, there are still no registers to be had for free, but this one must be a GRF reg instead of an extended reg, so a preserve register is spilled. Thus the move from extended to GRF is necessitated. I do not believe this can be 'fixed' through the files in config/m88k. gcc seems to sometimes make worse use of register allocation -- not counting moves -- whenever extended registers are present. For example in the whetstone, the simple for loop (slightly modified) for(i = 1; i <= n1; i++) { x1 = (x1 + x2 + x3 - x4) * t; x2 = (x1 + x2 - x3 + x4) * t; x3 = (x1 - x2 + x3 + x4) * t; x4 = (x1 + x2 + x3 + x4) * t; } in general loads the high bits of the addresses of x2-x4 and i into registers outside the loop. Whenever extended registers are used, it loads all of these inside the loop. My conjecture is that since the 88110 has so many registers, and gcc makes no distinction at this point -- just that they are not fixed, that in loop.c it believes it can expect a number of registers to be available. Then it allocates 'too many' in local-alloc which causes problems later. 'Too many' are allocated because a large portion of the registers are extended registers and cannot be used for certain purposes ( e.g. hold the address of a variable). When this loop is compiled on its own, the problem does not occur. I don't know the solution yet, though it is probably in the base sources. Possibly a different way to calculate "threshold". *//* 1 for registers that have pervasive standard uses and are not available for the register allocator. Registers r14-r25 and x22-x29 are expected to be preserved across function calls. On the 88000, the standard uses of the General Register File (GRF) are: Reg 0 = Pseudo argument pointer (hardware fixed to 0). Reg 1 = Subroutine return pointer (hardware). Reg 2-9 = Parameter registers (OCS). Reg 10 = OCS reserved temporary. Reg 11 = Static link if needed [OCS reserved temporary]. Reg 12 = Address of structure return (OCS). Reg 13 = OCS reserved temporary. Reg 14-25 = Preserved register set. Reg 26-29 = Reserved by OCS and ABI. Reg 30 = Frame pointer (Common use). Reg 31 = Stack pointer. The following follows the current 88open UCS specification for the Extended Register File (XRF): Reg 32 = x0 Always equal to zero Reg 33-53 = x1-x21 Temporary registers (Caller Save) Reg 54-61 = x22-x29 Preserver registers (Callee Save) Reg 62-63 = x30-x31 Reserved for future ABI use. Note: The current 88110 extended register mapping is subject to change. The bias towards caller-save registers is based on the presumption that memory traffic can potentially be reduced by allowing the "caller" to save only that part of the register which is actually being used. (i.e. don't do a st.x if a st.d is sufficient). Also, in scientific code (a.k.a. Fortran), the large number of variables defined in common blocks may require that almost all registers be saved across calls anyway. */#define FIXED_REGISTERS \ {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}/* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any registers that can be used without being saved. The latter must include the registers where values are returned and the register where structure-value addresses are passed. Aside from that, you can include as many other registers as you like. */#define CALL_USED_REGISTERS \ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}/* Macro to conditionally modify fixed_regs/call_used_regs. */#define CONDITIONAL_REGISTER_USAGE \ { \ if (! TARGET_88110) \ { \ register int i; \ for (i = FIRST_EXTENDED_REGISTER; i < FIRST_PSEUDO_REGISTER; i++) \ { \ fixed_regs[i] = 1; \ call_used_regs[i] = 1; \ } \ } \ if (flag_pic) \ { \ /* Current hack to deal with -fpic -O2 problems. */ \ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -