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.

From-SVN: r49536
This commit is contained in:
Hans-Peter Nilsson 2002-02-06 05:13:12 +00:00 committed by Hans-Peter Nilsson
parent 282cb01bc2
commit a824924d41
6 changed files with 196 additions and 58 deletions

View File

@ -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.

View File

@ -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 (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";
}
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.
value >>= 16;
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
{
/* 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++)
{
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;
}
}
}

View File

@ -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 \
}

View File

@ -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

View File

@ -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

View File

@ -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