#endif
static void copy_reg_pointer (rtx, rtx);
+static void fix_range (const char *);
static int hppa_address_cost (rtx);
static bool hppa_rtx_costs (rtx, int, int, int *);
static inline rtx force_mode (enum machine_mode, rtx);
rtx hppa_compare_op0, hppa_compare_op1;
enum cmp_type hppa_branch_type;
-/* Which cpu we are scheduling for. */
-enum processor_type pa_cpu;
-
-/* String to hold which cpu we are scheduling for. */
-const char *pa_cpu_string;
-
/* Which architecture we are generating code for. */
enum architecture_type pa_arch;
/* String to hold which architecture we are generating code for. */
const char *pa_arch_string;
+/* String used with the -mfixed-range= option. */
+const char *pa_fixed_range_string;
+
+/* Which cpu we are scheduling for. */
+enum processor_type pa_cpu;
+
+/* String to hold which cpu we are scheduling for. */
+const char *pa_cpu_string;
+
/* Counts for the number of callee-saved general and floating point
registers which were saved by the current function's prologue. */
static int gr_saved, fr_saved;
struct gcc_target targetm = TARGET_INITIALIZER;
\f
+/* 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. This is
+ used, e.g., to ensure that kernel mode code doesn't use f32-f127. */
+
+ i = strlen (const_str);
+ str = (char *) alloca (i + 1);
+ memcpy (str, const_str, i + 1);
+
+ while (1)
+ {
+ dash = strchr (str, '-');
+ if (!dash)
+ {
+ warning ("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 ("unknown register name: %s", str);
+ return;
+ }
+
+ last = decode_reg_name (dash + 1);
+ if (last < 0)
+ {
+ warning ("unknown register name: %s", dash + 1);
+ return;
+ }
+
+ *dash = '-';
+
+ if (first > last)
+ {
+ warning ("%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;
+ }
+
+ /* Check if all floating point registers have been fixed. */
+ for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
+ if (!fixed_regs[i])
+ break;
+
+ if (i > FP_REG_LAST)
+ target_flags |= MASK_DISABLE_FPREGS;
+}
+
void
override_options (void)
{
warning ("unknown -mschedule= option (%s).\nValid options are 700, 7100, 7100LC, 7200, 7300, and 8000\n", pa_cpu_string);
}
- /* Set the instruction set architecture. */
+ /* Set the instruction architecture. */
if (pa_arch_string && ! strcmp (pa_arch_string, "1.0"))
{
pa_arch_string = "1.0";
warning ("unknown -march= option (%s).\nValid options are 1.0, 1.1, and 2.0\n", pa_arch_string);
}
+ if (pa_fixed_range_string)
+ fix_range (pa_fixed_range_string);
+
/* Unconditional branches in the delay slot are not compatible with dwarf2
call frame information. There is no benefit in using this optimization
on PA8000 and later processors. */
PROCESSOR_8000
};
-/* For -mschedule= option. */
-extern const char *pa_cpu_string;
-extern enum processor_type pa_cpu;
-
-#define pa_cpu_attr ((enum attr_cpu)pa_cpu)
-
/* Which architecture to generate code for. */
enum architecture_type
extern const char *pa_arch_string;
extern enum architecture_type pa_arch;
+/* For -mfixed-range= option. */
+extern const char *pa_fixed_range_string;
+
+/* For -mschedule= option. */
+extern const char *pa_cpu_string;
+extern enum processor_type pa_cpu;
+
+#define pa_cpu_attr ((enum attr_cpu)pa_cpu)
+
/* Print subsidiary information on the compiler version in use. */
#define TARGET_VERSION fputs (" (hppa)", stderr);
#define TARGET_OPTIONS \
{ \
- { "schedule=", &pa_cpu_string, \
- N_("Specify CPU for scheduling purposes"), 0}, \
{ "arch=", &pa_arch_string, \
- N_("Specify architecture for code generation. Values are 1.0, 1.1, and 2.0. 2.0 requires gas snapshot 19990413 or later."), 0}\
+ N_("Specify PA-RISC architecture for code generation. " \
+ "Values are 1.0, 1.1 and 2.0."), 0}, \
+ { "fixed-range=", &pa_fixed_range_string, \
+ N_("Specify range of registers to make fixed"), 0}, \
+ { "schedule=", &pa_cpu_string, \
+ N_("Specify CPU for scheduling purposes"), 0} \
}
/* Support for a compile-time default CPU, et cetera. The rules are:
@gccoptlist{-march=@var{architecture-type} @gol
-mbig-switch -mdisable-fpregs -mdisable-indexing @gol
-mfast-indirect-calls -mgas -mgnu-ld -mhp-ld @gol
+-mfixed-range=@var{register-range} @gol
-mjump-in-delay -mlinker-opt -mlong-calls @gol
-mlong-load-store -mno-big-switch -mno-disable-fpregs @gol
-mno-disable-indexing -mno-fast-indirect-calls -mno-gas @gol
This option will not work in the presence of shared libraries or nested
functions.
+@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.
+
@item -mlong-load-store
@opindex mlong-load-store
Generate 3-instruction load and store sequences as sometimes required by