diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a39ec7eaf109..4c150cc4c347 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2006-12-12 Sa Liu + Ben Elliston + + * config/spu/spu.opt (mfixed-range): New option. + * config/spu/spu.h (spu_fixed_range_string): Declare. + * config/spu/spu.c (spu_override_options): Handle -mfixed-range. + (fix_range): New function. + * doc/invoke.texi (SPU Options): Document -mfixed-range. + * testsuite/gcc.target/spu/fixed-range.c: New. + * testsuite/gcc.target/spu/fixed-range-bad.c: Ditto. + 2006-12-11 H.J. Lu PR middle-end/17982 diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index 70f09c5d9187..52c8e9ce9cb0 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -128,6 +128,7 @@ static unsigned char spu_rtx_costs (rtx x, int code, int outer_code, static unsigned char spu_function_ok_for_sibcall (tree decl, tree exp); static void spu_init_libfuncs (void); static bool spu_return_in_memory (tree type, tree fntype); +static void fix_range (const char *); extern const char *reg_names[]; rtx spu_compare_op0, spu_compare_op1; @@ -264,6 +265,9 @@ spu_override_options (void) if (align_functions < 8) align_functions = 8; + + if (spu_fixed_range_string) + fix_range (spu_fixed_range_string); } /* Handle an attribute requiring a FUNCTION_DECL; arguments as in @@ -3574,6 +3578,68 @@ mem_is_padded_component_ref (rtx x) return 0; } +/* Parse the -mfixed-range= option string. */ +static void +fix_range (const char *const_str) +{ + int i, first, last; + char *str, *dash, *comma; + + /* str must be of the form REG1'-'REG2{,REG1'-'REG} where REG1 and + REG2 are either register names or register numbers. The effect + of this option is to mark the registers in the range from REG1 to + REG2 as ``fixed'' so they won't be used by the compiler. */ + + i = strlen (const_str); + str = (char *) alloca (i + 1); + memcpy (str, const_str, i + 1); + + while (1) + { + dash = strchr (str, '-'); + if (!dash) + { + warning (0, "value of -mfixed-range must have form REG1-REG2"); + return; + } + *dash = '\0'; + comma = strchr (dash + 1, ','); + if (comma) + *comma = '\0'; + + first = decode_reg_name (str); + if (first < 0) + { + warning (0, "unknown register name: %s", str); + return; + } + + last = decode_reg_name (dash + 1); + if (last < 0) + { + warning (0, "unknown register name: %s", dash + 1); + return; + } + + *dash = '-'; + + if (first > last) + { + warning (0, "%s-%s is an empty range", str, dash + 1); + return; + } + + for (i = first; i <= last; ++i) + fixed_regs[i] = call_used_regs[i] = 1; + + if (!comma) + break; + + *comma = ','; + str = comma + 1; + } +} + int spu_valid_move (rtx * ops) { diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h index b56ff1486e6c..923ca75ac741 100644 --- a/gcc/config/spu/spu.h +++ b/gcc/config/spu/spu.h @@ -24,6 +24,7 @@ #define OVERRIDE_OPTIONS spu_override_options() extern int target_flags; +extern const char *spu_fixed_range_string; /* Default target_flags if no switches specified. */ #ifndef TARGET_DEFAULT diff --git a/gcc/config/spu/spu.opt b/gcc/config/spu/spu.opt index 5df242ebe9e6..6c3ab59b63d3 100644 --- a/gcc/config/spu/spu.opt +++ b/gcc/config/spu/spu.opt @@ -52,3 +52,6 @@ mlarge-mem Target Report RejectNegative Mask(LARGE_MEM) Generate code for 32 bit addressing +mfixed-range= +Target RejectNegative Joined Var(spu_fixed_range_string) +Specify range of registers to make fixed diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b7eab9e964f6..2d28e8509e1e 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -733,7 +733,8 @@ See RS/6000 and PowerPC Options. @gccoptlist{-mwarn-reloc -merror-reloc @gol -msafe-dma -munsafe-dma @gol -mbranch-hints @gol --msmall-mem -mlarge-mem -mstdmain} +-msmall-mem -mlarge-mem -mstdmain @gol +-mfixed-range=@var{register-range}} @emph{System V Options} @gccoptlist{-Qy -Qn -YP,@var{paths} -Ym,@var{dir}} @@ -12909,6 +12910,14 @@ With @option{-mstdmain}, GCC will link your program against startup code that assumes a C99-style interface to @code{main}, including a local copy of @code{argv} strings. +@item -mfixed-range=@var{register-range} +@opindex mfixed-range +Generate code treating the given register range as fixed registers. +A fixed register is one that the register allocator can not use. This is +useful when compiling kernel code. A register range is specified as +two registers separated by a dash. Multiple register ranges can be +specified separated by a comma. + @end table @node System V Options diff --git a/gcc/testsuite/gcc.target/spu/fixed-range-bad.c b/gcc/testsuite/gcc.target/spu/fixed-range-bad.c new file mode 100644 index 000000000000..eeef122cbffc --- /dev/null +++ b/gcc/testsuite/gcc.target/spu/fixed-range-bad.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-mfixed-range=1-x" } */ +/* { dg-error "unknown register name" "" { target spu-*-* } 0 } */ + +int i; diff --git a/gcc/testsuite/gcc.target/spu/fixed-range.c b/gcc/testsuite/gcc.target/spu/fixed-range.c new file mode 100644 index 000000000000..8dcb7fe4c251 --- /dev/null +++ b/gcc/testsuite/gcc.target/spu/fixed-range.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-mfixed-range=1-20" } */ +/* { dg-final { scan-assembler "lqd.*21" } } */ + +int foo (int i) +{ + return i; +}