Commit 3933e0e1 by Michael Meissner

Add -mno-toc; Support block moves if -mno-string.

From-SVN: r9763
parent 15c8ec1c
......@@ -202,6 +202,10 @@ rs6000_override_options ()
warning ("-mstring is not supported on little endian systems");
}
}
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
}
/* Create a CONST_DOUBLE like immed_double_const, except reverse the
......@@ -641,37 +645,58 @@ input_operand (op, mode)
operands[2] is the length
operands[3] is the alignment */
#define MAX_MOVE_REG 4
int
expand_block_move (operands)
rtx operands[];
{
rtx bytes_rtx = operands[2];
int constp = (GET_CODE (bytes_rtx) == CONST_INT);
int bytes = (constp ? INTVAL (bytes_rtx) : 0);
rtx align_rtx = operands[3];
int constp = (GET_CODE (bytes_rtx) == CONST_INT);
int align = XINT (align_rtx, 0);
int bytes;
int offset;
int num_reg;
int i;
rtx src_reg;
rtx dest_reg;
rtx src_addr;
rtx dest_addr;
rtx tmp_reg;
rtx stores[MAX_MOVE_REG];
int move_bytes;
/* If this is not a fixed size move, just call memcpy */
if (!constp)
return 0;
/* Anything to move? */
if (constp && bytes <= 0)
bytes = INTVAL (bytes_rtx);
if (bytes <= 0)
return 1;
/* If we don't want to use multiple string instructions, quit now and
generate the normal code. */
if (!TARGET_STRING)
/* Don't support real large moves. If string instructions are not used,
then don't generate more than 8 loads. */
if (TARGET_STRING)
{
if (bytes > 64)
return 0;
/* We don't support variable sized moves at this time or real large moves */
if (!constp || bytes > 64)
}
else if (!STRICT_ALIGNMENT)
{
if (bytes > 4*8)
return 0;
}
else if (bytes > 8*align)
return 0;
/* Move the address into scratch registers. */
dest_reg = copy_addr_to_reg (XEXP (operands[0], 0));
src_reg = copy_addr_to_reg (XEXP (operands[1], 0));
if (TARGET_STRING) /* string instructions are available */
{
for ( ; bytes > 0; bytes -= move_bytes)
{
if (bytes > 24 /* move up to 32 bytes at a time */
......@@ -764,6 +789,62 @@ expand_block_move (operands)
GEN_INT ((bytes > move_bytes) ? move_bytes : 0)));
}
}
}
else /* string instructions not available */
{
num_reg = offset = 0;
for ( ; bytes > 0; (bytes -= move_bytes), (offset += move_bytes))
{
/* Calculate the correct offset for src/dest */
if (offset == 0)
{
src_addr = src_reg;
dest_addr = dest_reg;
}
else
{
src_addr = gen_rtx (PLUS, Pmode, src_reg, GEN_INT (offset));
dest_addr = gen_rtx (PLUS, Pmode, dest_reg, GEN_INT (offset));
}
/* Generate the appropriate load and store, saving the stores for later */
if (bytes >= 4 && (align >= 4 || !STRICT_ALIGNMENT))
{
move_bytes = 4;
tmp_reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (tmp_reg, gen_rtx (MEM, SImode, src_addr)));
stores[ num_reg++ ] = gen_movsi (gen_rtx (MEM, SImode, dest_addr), tmp_reg);
}
else if (bytes >= 2 && (align >= 2 || !STRICT_ALIGNMENT))
{
move_bytes = 2;
tmp_reg = gen_reg_rtx (HImode);
emit_insn (gen_movhi (tmp_reg, gen_rtx (MEM, HImode, src_addr)));
stores[ num_reg++ ] = gen_movhi (gen_rtx (MEM, HImode, dest_addr), tmp_reg);
}
else
{
move_bytes = 1;
tmp_reg = gen_reg_rtx (QImode);
emit_insn (gen_movqi (tmp_reg, gen_rtx (MEM, QImode, src_addr)));
stores[ num_reg++ ] = gen_movqi (gen_rtx (MEM, QImode, dest_addr), tmp_reg);
}
if (num_reg >= MAX_MOVE_REG)
{
for (i = 0; i < num_reg; i++)
emit_insn (stores[i]);
num_reg = 0;
}
}
if (num_reg > 0)
{
for (i = 0; i < num_reg; i++)
emit_insn (stores[i]);
}
}
return 1;
}
......@@ -1936,6 +2017,16 @@ output_prolog (file, size)
asm_fprintf (file, "\t{cax|add} 30,0,30\n");
rs6000_pic_labelno++;
}
else if (TARGET_NO_TOC)
{
ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
asm_fprintf (file, "\t{cau|addis} 30,0,");
assemble_name (file, buf);
asm_fprintf (file, "@ha\n");
asm_fprintf (file, "\t{cal|addi} 30,30,");
assemble_name (file, buf);
asm_fprintf (file, "@l\n");
}
else
#endif /* USING_SVR4_H */
{
......
......@@ -279,16 +279,7 @@ extern char *rs6000_cpu_string;
On the RS/6000 this is used to define the target cpu type. */
#define OVERRIDE_OPTIONS \
do { \
rs6000_override_options (); \
SUBTARGET_OVERRIDE_OPTIONS; \
} while (0)
/* For OS-dependent options */
#ifndef SUBTARGET_OVERRIDE_OPTIONS
#define SUBTARGET_OVERRIDE_OPTIONS
#endif
#define OVERRIDE_OPTIONS rs6000_override_options ()
/* Show we can debug even without a frame pointer. */
#define CAN_DEBUG_WITHOUT_FP
......
......@@ -26,16 +26,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define MASK_RELOCATABLE 0x10000000 /* GOT pointers are PC relative */
#define MASK_NO_TRACEBACK 0x08000000 /* eliminate traceback words */
#define MASK_LITTLE_ENDIAN 0x04000000 /* target is little endian */
#define MASK_NO_TOC 0x02000000 /* do not use TOC for loading addresses */
#define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
#define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN)
#define TARGET_RELOCATABLE (target_flags & MASK_RELOCATABLE)
#define TARGET_NO_TRACEBACK (target_flags & MASK_NO_TRACEBACK)
#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
#define TARGET_NO_TOC (target_flags & MASK_NO_TOC)
#define TARGET_BITFIELD_TYPE (! TARGET_NO_BITFIELD_TYPE)
#define TARGET_TRACEBACK (! TARGET_NO_TRACEBACK)
#define TARGET_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
#define TARGET_TOC (! TARGET_NO_TOC)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
......@@ -50,7 +53,39 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
{ "little-endian", MASK_LITTLE_ENDIAN }, \
{ "little", MASK_LITTLE_ENDIAN }, \
{ "big-endian", -MASK_LITTLE_ENDIAN }, \
{ "big", -MASK_LITTLE_ENDIAN },
{ "big", -MASK_LITTLE_ENDIAN }, \
{ "no-toc", MASK_NO_TOC | MASK_MINIMAL_TOC }, \
{ "toc", -MASK_NO_TOC },
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
`OVERRIDE_OPTIONS' to take account of this. This macro, if
defined, is executed once just after all the command options have
been parsed.
The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
get control. */
#define SUBTARGET_OVERRIDE_OPTIONS \
do { \
if (TARGET_RELOCATABLE && TARGET_NO_TOC) \
{ \
target_flags &= ~ MASK_NO_TOC; \
error ("-mrelocatable and -mno-toc are incompatible."); \
} \
\
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
{ \
target_flags |= MASK_MINIMAL_TOC; \
error ("-mrelocatable and -mno-minimal-toc are incompatible."); \
} \
\
if (TARGET_NO_TOC && !TARGET_MINIMAL_TOC) \
{ \
target_flags |= MASK_MINIMAL_TOC; \
error ("-mno-toc and -mno-minimal-toc are incompatible."); \
} \
} while (0)
#include "rs6000/powerpc.h"
......@@ -152,12 +187,12 @@ toc_section () \
{ \
if (! toc_initialized) \
{ \
if (!TARGET_RELOCATABLE) \
if (!TARGET_RELOCATABLE && !TARGET_NO_TOC) \
fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \
\
if (TARGET_MINIMAL_TOC) \
{ \
if (!TARGET_RELOCATABLE) \
if (!TARGET_RELOCATABLE && !TARGET_NO_TOC) \
{ \
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LCTOC", 0); \
fprintf (asm_out_file, "\t.tc "); \
......
......@@ -16,9 +16,11 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
# Build libgcc.a with different options.
MULTILIB_OPTIONS = msoft-float \
mno-toc \
mlittle/mbig
MULTILIB_DIRNAMES = soft-float \
no-toc \
little-endian big-endian
MULTILIB_MATCHES = mlittle=mlittle-endian \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment