diff options
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/config/mmix/mmix.c | 165 | ||||
-rw-r--r-- | gcc/config/mmix/mmix.h | 31 | ||||
-rw-r--r-- | gcc/config/mmix/mmix.md | 5 | ||||
-rw-r--r-- | gcc/config/mmix/t-mmix | 3 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 16 |
6 files changed, 195 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a4eeafd88c..bdaa34aa2f9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2002-02-06 Hans-Peter Nilsson <hp@bitrange.com> + + Implement using "base addresses" in insn operands as default. + * config/mmix/mmix.c (mmix_conditional_register_usage): if + -mabi=gnu, modify fixed_regs to fit the GNU ABI. + (mmix_extra_constraint): Use 'R' to indicate that GETA should be + used to read the rtx value. + (mmix_target_asm_function_epilogue): Fix spacing. + (mmix_constant_address_p): Handle TARGET_BASE_ADDRESSES. + (mmix_legitimate_address): Ditto. + (mmix_encode_section_info): Set SYMBOL_REF_FLAG on rtx:es that + should be loaded with a GETA insn. Don't allocate needless extra + char for nul termination and fix misleading comment. + (mmix_print_operand_address): Handle constants if + TARGET_BASE_ADDRESSES. + (mmix_output_register_setting): Use base addressing if + TARGET_BASE_ADDRESSES and the number of insns is 3. + * config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): New. + * config/mmix/mmix.md ("movdi"): Change the alternative with GETA + to use R as constraint, add LDA to match s. + * config/mmix/mmix.h (TARGET_BASE_ADDRESSES): New. + (TARGET_DEFAULT): Add TARGET_MASK_BASE_ADDRESSES. + (TARGET_SWITCHES): Add -mbase-addresses, -mno-base-addresses. + (FIXED_REGISTERS): Make registers $231..$246 fixed by default. + (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Move $231..$246 last, in + order with other fixed registers. + (MMIX_GNU_ABI_REG_ALLOC_ORDER): Put forward $231, in order with + other parameter/call-clobbered registers. + * doc/invoke.texi (Option Summary) <MMIX Options>: Add + -mbase-addresses, -mno-base-addresses. + (MMIX Options): Ditto. + 2002-02-05 John David Anglin <dave@hiauly1.hia.nrc.ca> * pa.h (PREDICATE_CODES): Add reg_before_reload_operand. diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index bbe8313a4b4..8192d9b6a66 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -228,6 +228,12 @@ mmix_conditional_register_usage () mmixware ABI. */ for (i = 15; i <= 30; i++) call_used_regs[i] = 0; + + /* "Unfix" the parameter registers. */ + for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM; + i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS; + i++) + fixed_regs[i] = 0; } /* Step over the ":" in special register names. */ @@ -334,14 +340,34 @@ mmix_extra_constraint (x, c, strict) ? strict_memory_address_p (Pmode, x) : memory_address_p (Pmode, x); + /* R asks whether x is to be loaded with GETA or something else. Right + now, only a SYMBOL_REF and LABEL_REF can fit for + TARGET_BASE_ADDRESSES. + + Only constant symbolic addresses apply. With TARGET_BASE_ADDRESSES, + we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG + set right now; only function addresses and code labels. If we change + to let SYMBOL_REF_FLAG be set on other symbols, we have to check + inside CONST expressions. When TARGET_BASE_ADDRESSES is not in + effect, a "raw" constant check together with mmix_constant_address_p + is all that's needed; we want all constant addresses to be loaded + with GETA then. */ + if (c == 'R') + return + GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE + && mmix_constant_address_p (x) + && (! TARGET_BASE_ADDRESSES + || (GET_CODE (x) == LABEL_REF + || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x)))); + if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode) return 0; value = mmix_intval (x); /* We used to map Q->J, R->K, S->L, T->N, U->O, but we don't have to any - more ('U' taken for address_operand). Some letters map outside of - CONST_INT, though; we still use 'S' and 'T'. */ + more ('U' taken for address_operand, 'R' similarly). Some letters map + outside of CONST_INT, though; we still use 'S' and 'T'. */ if (c == 'S') return mmix_shiftable_wyde_value (value); else if (c == 'T') @@ -1017,7 +1043,7 @@ mmix_target_asm_function_epilogue (stream, locals_size) if (frame_pointer_needed) stack_space_to_deallocate += 8; - /* Make sure we don't get an unaligned stack. */ + /* Make sure we don't get an unaligned stack. */ if ((stack_space_to_deallocate % 8) != 0) internal_error ("stack frame not a multiple of octabyte: %d", stack_space_to_deallocate); @@ -1354,7 +1380,7 @@ mmix_initialize_trampoline (trampaddr, fnaddr, static_chain) /* We must exclude constant addresses that have an increment that is not a multiple of four bytes because of restrictions of the GETA - instruction. FIXME: No, I don't think so. Just add a constraint. */ + instruction, unless TARGET_BASE_ADDRESSES. */ int mmix_constant_address_p (x) @@ -1362,13 +1388,15 @@ mmix_constant_address_p (x) { RTX_CODE code = GET_CODE (x); int addend = 0; + /* When using "base addresses", anything constant goes. */ + int constant_ok = TARGET_BASE_ADDRESSES != 0; if (code == LABEL_REF || code == SYMBOL_REF) return 1; if (code == CONSTANT_P_RTX || code == HIGH) /* FIXME: Don't know how to dissect these. Avoid them for now. */ - return 0; + return constant_ok; switch (code) { @@ -1376,12 +1404,11 @@ mmix_constant_address_p (x) case SYMBOL_REF: return 1; - case PLUS: - /* Can we get a naked PLUS? */ case CONSTANT_P_RTX: case HIGH: - /* FIXME: Don't know how to dissect these. Avoid them for now. */ - return 0; + /* FIXME: Don't know how to dissect these. Avoid them for now, + except we know they're constants. */ + return constant_ok; case CONST_INT: addend = INTVAL (x); @@ -1390,7 +1417,7 @@ mmix_constant_address_p (x) case CONST_DOUBLE: if (GET_MODE (x) != VOIDmode) /* Strange that we got here. FIXME: Check if we do. */ - return 0; + return constant_ok; addend = CONST_DOUBLE_LOW (x); break; @@ -1410,17 +1437,17 @@ mmix_constant_address_p (x) && GET_MODE (x1) == VOIDmode))) addend = mmix_intval (x1); else - return 0; + return constant_ok; } else - return 0; + return constant_ok; break; default: return 0; } - return (addend & 3) == 0; + return constant_ok || (addend & 3) == 0; } /* Return 1 if the address is OK, otherwise 0. @@ -1445,7 +1472,9 @@ mmix_legitimate_address (mode, x, strict_checking) /* We only accept: (mem reg) (mem (plus reg reg)) - (mem (plus reg 0..255)). */ + (mem (plus reg 0..255)). + unless TARGET_BASE_ADDRESSES, in which case we accept all + (mem constant_address) too. */ /* (mem reg) */ @@ -1465,21 +1494,23 @@ mmix_legitimate_address (mode, x, strict_checking) x2 = tem; } - /* (mem (plus (reg) (?))) */ + /* (mem (plus (reg?) (?))) */ if (!REG_P (x1) || !MMIX_REG_OK (x1)) - return 0; + return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x); - /* (mem (plus (reg) (reg))) */ + /* (mem (plus (reg) (reg?))) */ if (REG_P (x2) && MMIX_REG_OK (x2)) return 1; - /* (mem (plus (reg) (0..255))) */ + /* (mem (plus (reg) (0..255?))) */ if (GET_CODE (x2) == CONST_INT && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I')) return 1; + + return 0; } - return 0; + return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x); } /* LEGITIMATE_CONSTANT_P. */ @@ -1676,34 +1707,41 @@ mmix_encode_section_info (decl) { /* For non-visible declarations, add a "@" prefix, which we skip when the label is output. If the label does not have this - prefix, a ":" is output. + prefix, a ":" is output if -mtoplevel-symbols. Note that this does not work for data that is declared extern and later defined as static. If there's code in between, that code - will refer to the extern declaration. And vice versa. Until we - can get rid of mmixal, we have to assume that code is - well-behaved. */ + will refer to the extern declaration, and vice versa. This just + means that when -mtoplevel-symbols is in use, we can just handle + well-behaved ISO-compliant code. */ const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0); int len = strlen (str); char *newstr; - /* Doing as rs6000 seems safe; always use ggc. Except don't copy - the suspected off-by-one bug. - FIXME: Is it still there? yes 2001-08-23 - Why is the return type of ggc_alloc_string const? */ - newstr = (char *) ggc_alloc_string ("", len + 2); + /* Why is the return type of ggc_alloc_string const? */ + newstr = (char *) ggc_alloc_string ("", len + 1); strcpy (newstr + 1, str); *newstr = '@'; XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr; } - /* FIXME: Later on, add SYMBOL_REF_FLAG for things that we can reach - from here via GETA, to check in LEGITIMATE_CONSTANT_P. Needs to have - different options for the cases where we want *all* to be assumed - reachable via GETA, or all constant symbols, or just text symbols in - this file, or perhaps just the constant pool. */ + /* Set SYMBOL_REF_FLAG for things that we want to access with GETA. We + may need different options to reach for different things with GETA. + For now, functions and things we know or have been told are constant. */ + if (TREE_CODE (decl) == FUNCTION_DECL + || TREE_CONSTANT (decl) + || (TREE_CODE (decl) == VAR_DECL + && TREE_READONLY (decl) + && !TREE_SIDE_EFFECTS (decl) + && (!DECL_INITIAL (decl) + || TREE_CONSTANT (DECL_INITIAL (decl))))) + { + rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' + ? TREE_CST_RTL (decl) : DECL_RTL (decl)); + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + } } /* STRIP_NAME_ENCODING. */ @@ -2351,6 +2389,12 @@ mmix_print_operand_address (stream, x) } } + if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x)) + { + output_addr_const (stream, x); + return; + } + fatal_insn ("MMIX Internal: This is not a recognized address", x); } @@ -2514,25 +2558,52 @@ mmix_output_register_setting (stream, regno, value, do_begin_end) static const char *const higher_parts[] = {"L", "ML", "MH", "H"}; const char *op = "SET"; const char *line_begin = ""; + int insns = 0; int i; + HOST_WIDEST_INT tmpvalue = value; - /* Output pertinent parts of the 4-wyde sequence. - Still more to do if we want this to be optimal, but hey... - Note that the zero case has been handled above. */ - for (i = 0; i < 4 && value != 0; i++) + /* Compute the number of insns needed to output this constant. */ + for (i = 0; i < 4 && tmpvalue != 0; i++) + { + if (tmpvalue & 65535) + insns++; + tmpvalue >>= 16; + } + if (TARGET_BASE_ADDRESSES && insns == 3) + { + /* The number three is based on a static observation on + ghostscript-6.52. Two and four are excluded because there + are too many such constants, and each unique constant (maybe + offset by 1..255) were used few times compared to other uses, + e.g. addresses. + + We use base-plus-offset addressing to force it into a global + register; we just use a "LDA reg,VALUE", which will cause the + assembler and linker to DTRT (for constants as well as + addresses). */ + fprintf (stream, "LDA %s,", reg_names[regno]); + mmix_output_octa (stream, value, 0); + } + else { - if (value & 65535) + /* Output pertinent parts of the 4-wyde sequence. + Still more to do if we want this to be optimal, but hey... + Note that the zero case has been handled above. */ + for (i = 0; i < 4 && value != 0; i++) { - fprintf (stream, "%s%s%s %s,#%x", line_begin, op, - higher_parts[i], reg_names[regno], - (int) (value & 65535)); - /* The first one sets the rest of the bits to 0, the next - ones add set bits. */ - op = "INC"; - line_begin = "\n\t"; - } + if (value & 65535) + { + fprintf (stream, "%s%s%s %s,#%x", line_begin, op, + higher_parts[i], reg_names[regno], + (int) (value & 65535)); + /* The first one sets the rest of the bits to 0, the next + ones add set bits. */ + op = "INC"; + line_begin = "\n\t"; + } - value >>= 16; + value >>= 16; + } } } diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index 9c1e2f13c25..74229acd6a4 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -157,6 +157,16 @@ extern int target_flags; #define TARGET_MASK_TOPLEVEL_SYMBOLS 32 #define TARGET_MASK_BRANCH_PREDICT 64 +/* We use the term "base address" since that's what Knuth uses. The base + address goes in a global register. When addressing, it's more like + "base address plus offset", with the offset being 0..255 from the base, + which itself can be a symbol plus an offset. The effect is like having + a constant pool in global registers, code offseting from those + registers (automatically causing a request for a suitable constant base + address register) without having to know the specific register or the + specific offset. */ +#define TARGET_MASK_BASE_ADDRESSES 128 + /* FIXME: Get rid of this one. */ #define TARGET_LIBFUNC (target_flags & TARGET_MASK_LIBFUNCS) #define TARGET_ABI_GNU (target_flags & TARGET_MASK_ABI_GNU) @@ -165,9 +175,10 @@ extern int target_flags; #define TARGET_KNUTH_DIVISION (target_flags & TARGET_MASK_KNUTH_DIVISION) #define TARGET_TOPLEVEL_SYMBOLS (target_flags & TARGET_MASK_TOPLEVEL_SYMBOLS) #define TARGET_BRANCH_PREDICT (target_flags & TARGET_MASK_BRANCH_PREDICT) +#define TARGET_BASE_ADDRESSES (target_flags & TARGET_MASK_BASE_ADDRESSES) #define TARGET_DEFAULT \ - (TARGET_MASK_BRANCH_PREDICT) + (TARGET_MASK_BRANCH_PREDICT | TARGET_MASK_BASE_ADDRESSES) /* FIXME: Provide a way to *load* the epsilon register. */ #define TARGET_SWITCHES \ @@ -198,6 +209,10 @@ extern int target_flags; N_("Use P-mnemonics for branches statically predicted as taken")}, \ {"no-branch-predict", -TARGET_MASK_BRANCH_PREDICT, \ N_("Don't use P-mnemonics for branches")}, \ + {"base-addresses", TARGET_MASK_BASE_ADDRESSES, \ + N_("Use addresses that allocate global registers")}, \ + {"no-base-addresses", -TARGET_MASK_BASE_ADDRESSES, \ + N_("Do not use addresses that allocate global registers")}, \ {"", TARGET_DEFAULT, ""}} /* Unfortunately, this must not reference anything in "mmix.c". */ @@ -366,8 +381,8 @@ extern int target_flags; 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, 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, 0, \ - 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 1, 1, \ 1, 1, 0, 0, 0, 1 \ } @@ -419,8 +434,6 @@ extern int target_flags; 24, 25, 26, 27, 28, 29, 30, 31, \ \ 252, 251, 250, 249, 248, 247, \ - 246, 245, 244, 243, 242, 241, 240, 239, \ - 238, 237, 236, 235, 234, 233, 232, 231, \ \ 253, \ \ @@ -451,6 +464,9 @@ extern int target_flags; 208, 209, 210, 211, 212, 213, 214, 215, \ 216, 217, 218, 219, 220, 221, 222, 223, \ 224, 225, 226, 227, 228, 229, 230, 231, \ + 232, 233, 234, 235, 236, 237, 238, 239, \ + 240, 241, 242, 243, 244, 245, 246, \ + \ 254, 255, 256, 257, 261 \ } @@ -469,7 +485,7 @@ extern int target_flags; #define MMIX_GNU_ABI_REG_ALLOC_ORDER \ { 252, 251, 250, 249, 248, 247, 246, \ 245, 244, 243, 242, 241, 240, 239, 238, \ - 237, 236, 235, 234, 233, 232, \ + 237, 236, 235, 234, 233, 232, 231, \ \ 0, 1, 2, 3, 4, 5, 6, 7, \ 8, 9, 10, 11, 12, 13, 14, 15, \ @@ -504,7 +520,8 @@ extern int target_flags; 200, 201, 202, 203, 204, 205, 206, 207, \ 208, 209, 210, 211, 212, 213, 214, 215, \ 216, 217, 218, 219, 220, 221, 222, 223, \ - 224, 225, 226, 227, 228, 229, 230, 231, \ + 224, 225, 226, 227, 228, 229, 230, \ + \ 254, 255, 256, 257, 261 \ } diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md index c8e0167c1db..da555ff2d88 100644 --- a/gcc/config/mmix/mmix.md +++ b/gcc/config/mmix/mmix.md @@ -88,8 +88,8 @@ ;; We assume all "s" are addresses. Does that hold? (define_insn "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,??r") - (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,s,n"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r") + (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,R,s,n"))] "" "@ SET %0,%1 @@ -101,6 +101,7 @@ LDO %0,%1 STOU %1,%0 GETA %0,%1 + LDA %0,%1 %r0%I1") ;; Note that we move around the float as a collection of bits; no diff --git a/gcc/config/mmix/t-mmix b/gcc/config/mmix/t-mmix index fbe1a101185..fcfe7c7229c 100644 --- a/gcc/config/mmix/t-mmix +++ b/gcc/config/mmix/t-mmix @@ -13,6 +13,9 @@ EXTRA_MULTILIB_PARTS = crti.o crtn.o crtbegin.o crtend.o MULTILIB_OPTIONS = mabi=gnu MULTILIB_DIRNAMES = gnuabi +# Don't use global registers in libraries. +MULTILIB_EXTRA_OPTS = mno-base-addresses + $(T)crti.o: $(srcdir)/config/mmix/crti.asm $(GCC_PASSES) $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mmix/crti.asm diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 51db49adb02..c5f88bed278 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -593,7 +593,8 @@ in the following sections. @gccoptlist{ -mlibfuncs -mno-libfuncs -mepsilon -mno-epsilon -mabi=gnu @gol -mabi=mmixware -mzero-extend -mknuthdiv -mtoplevel-symbols @gol --melf -mbranch-predict -mno-branch-predict} +-melf -mbranch-predict -mno-branch-predict -mbase-addresses @gol +-mno-base-addresses} @emph{IA-64 Options} @gccoptlist{ @@ -9513,6 +9514,19 @@ Generate an executable in the ELF format, rather than the default @opindex mno-branch-predict Use (do not use) the probable-branch instructions, when static branch prediction indicates a probable branch. + +@item -mbase-addresses +@itemx -mno-base-addresses +@opindex mbase-addresses +@opindex mno-base-addresses +Generate (do not generate) code that uses @emph{base addresses}. Using a +base address automatically generates a request (handled by the assembler +and the linker) for a constant to be set up in a global register. The +register is used for one or more base address requests within the range 0 +to 255 from the value held in the register. The generally leads to short +and fast code, but the number of different data items that can be +addressed is limited. This means that a program that uses lots of static +data may require @option{-mno-base-addresses}. @end table @node PDP-11 Options |