* Makefile.in (final.o): Depend on target.h.
* final.c: Include target.h.
(default_function_pro_epilogue): New.
(final_start_function): Use target structure for function prologues.
(final_end_function): Use target structure for function epilogues.
* fold-const.c (real_hex_to_f): Constify s and p.
* output.h (default_function_pro_epilogue): New.
* real.h (real_hex_to_f): Update prototype.
* target-def.h (TARGET_ASM_FUNCTION_PROLOGUE,
TARGET_ASM_FUNCTION_EPILOGUE, TARGET_ASM_OUT): New.
(TARGET_INITIALIZER): Update.
* target.h (gcc_target): Add struct asm_out.
* doc/tm.texi: Update.
config:
Update each arch to use TARGET_ASM_FUNCTION_PROLOGUE and
TARGET_ASM_FUNCTION_EPILOGUE. Move macro code to functions
in cpu/cpu.c, or rename old functions consistently. Take
a HOST_WIDE INT not an int as the SIZE parameter. Remove now
redundant macros and prototypes. Make new functions static.
* 1750a/1750a.c: Similarly.
* 1750a/1750a.h: Similarly.
* a29k/a29k-protos.h: Similarly.
* a29k/a29k.c: Similarly.
* a29k/a29k.h: Similarly.
* arc/arc-protos.h: Similarly.
* arc/arc.c: Similarly.
* arc/arc.h: Similarly.
* arm/arm-protos.h: Similarly.
* arm/arm.c: Similarly.
* arm/arm.h: Similarly.
* avr/avr-protos.h: Similarly.
* avr/avr.c: Similarly.
* avr/avr.h: Similarly.
* clipper/clipper-protos.h: Similarly.
* clipper/clipper.c: Similarly.
* clipper/clipper.h: Similarly.
* convex/convex.c: Similarly.
* convex/convex.h: Similarly.
* d30v/d30v-protos.h: Similarly.
* d30v/d30v.c: Similarly.
* d30v/d30v.h: Similarly.
* d30v/d30v.md: Similarly.
* dsp16xx/dsp16xx-protos.h: Similarly.
* dsp16xx/dsp16xx.c: Similarly.
* dsp16xx/dsp16xx.h: Similarly.
* elxsi/elxsi.c: Similarly.
* elxsi/elxsi.h: Similarly.
* fr30/fr30.c: Similarly.
* fr30/fr30.md: Similarly.
* h8300/h8300-protos.h: Similarly.
* h8300/h8300.c: Similarly.
* h8300/h8300.h: Similarly.
* i370/i370-protos.h: Similarly.
* i370/i370.c: Similarly.
* i370/i370.h: Similarly.
* i386/i386.c: Similarly.
* i386/osf1elf.h: Similarly.
* i386/osfrose.h: Similarly.
* i860/i860-protos.h: Similarly.
* i860/i860.c: Similarly.
* i860/i860.h: Similarly.
* i960/i960-protos.h: Similarly.
* i960/i960.c: Similarly.
* i960/i960.h: Similarly.
* ia64/ia64-protos.h: Similarly.
* ia64/ia64.c: Similarly.
* ia64/ia64.h: Similarly.
* m32r/m32r-protos.h: Similarly.
* m32r/m32r.c: Similarly.
* m32r/m32r.h: Similarly.
* m68hc11/m68hc11-protos.h: Similarly.
* m68hc11/m68hc11.c: Similarly.
* m68hc11/m68hc11.h: Similarly.
* m68k/crds.h: Similarly.
* m68k/dpx2.h: Similarly.
* m68k/m68k-protos.h: Similarly.
* m68k/m68k.c: Similarly.
* m68k/m68k.h: Similarly.
* m68k/news.h: Similarly.
* m88k/m88k-protos.h: Similarly.
* m88k/m88k.c: Similarly.
* m88k/m88k.h: Similarly.
* mips/mips-protos.h: Similarly.
* mips/mips.c: Similarly.
* mips/mips.h: Similarly.
* ns32k/merlin.h: Similarly.
* ns32k/ns32k.c: Similarly.
* ns32k/ns32k.h: Similarly.
* ns32k/tek6000.h: Similarly.
* pa/pa-protos.h: Similarly.
* pa/pa.c: Similarly.
* pa/pa.h: Similarly.
* pdp11/2bsd.h: Similarly.
* pdp11/pdp11-protos.h: Similarly.
* pdp11/pdp11.c: Similarly.
* pdp11/pdp11.h: Similarly.
* romp/romp-protos.h: Similarly.
* romp/romp.c: Similarly.
* romp/romp.h: Similarly.
* rs6000/rs6000-protos.h: Similarly.
* rs6000/rs6000.c: Similarly.
* rs6000/rs6000.h: Similarly.
* rs6000/sysv4.h: Similarly.
* sh/sh-protos.h: Similarly.
* sh/sh.c: Similarly.
* sh/sh.h: Similarly.
* sparc/sparc-protos.h: Similarly.
* sparc/sparc.c: Similarly.
* sparc/sparc.h: Similarly.
* vax/vax.c: Similarly.
* vax/vax.h: Similarly.
* vax/vms.h: Similarly.
* we32k/we32k.c: Similarly.
* we32k/we32k.h: Similarly.
From-SVN: r43817
$(REGS_H) $(RECOG_H) conditions.h insn-config.h $(INSN_ATTR_H) function.h \
real.h output.h hard-reg-set.h except.h \
xcoffout.h toplev.h reload.h dwarfout.h dwarf2out.h sdbout.h \
- dbxout.h $(BASIC_BLOCK_H) $(TM_P_H)
+ dbxout.h $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H)
recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) function.h $(BASIC_BLOCK_H) \
$(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h $(INSN_ATTR_H) \
real.h toplev.h output.h reload.h $(TM_P_H)
-/* config.in. Generated automatically from configure.in by autoheader. */
+/* config.in. Generated automatically from configure.in by autoheader 2.13. */
/* Define to empty if the keyword does not work. */
#undef const
#include "real.h"
#include "regs.h"
#include "output.h"
+#include "flags.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
{"Init", "Normal", "Konst", "Static"};
static int which_bit PARAMS ((int));
+static void output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+static void
+output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ if (flag_verbose_asm)
+ {
+ int regno, regs_used = 0;
+
+ fprintf (file, "\t; registers used: ");
+ for (regno = 0; regno < 14; regno++)
+ if (regs_ever_live[regno])
+ {
+ fprintf (file, " %s", reg_names[regno]);
+ regs_used++;
+ }
+
+ if (regs_used == 0)
+ fprintf (file, "(none)");
+ }
+
+ if (size > 0)
+ {
+ fprintf (file, "\n\t%s\tr15,%d",
+ (size <= 16 ? "sisp" : "sim"), size);
+ if (flag_verbose_asm)
+ fprintf (file, " ; reserve local-variable space");
+ }
+
+ if (frame_pointer_needed)
+ {
+ fprintf(file, "\n\tpshm\tr14,r14");
+ if (flag_verbose_asm)
+ fprintf (file, " ; push old frame");
+ fprintf (file, "\n\tlr\tr14,r15");
+ if (flag_verbose_asm)
+ fprintf (file, " ; set new frame");
+ }
+
+ fprintf (file, "\n");
+ program_counter = 0;
+ jmplbl_ndx = -1;
+}
+
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ if (frame_pointer_needed)
+ {
+ fprintf (file, "\tlr\tr15,r14");
+ if (flag_verbose_asm)
+ fprintf (file, " ; set stack ptr to frame ptr");
+ fprintf (file, "\n\tpopm\tr14,r14");
+ if (flag_verbose_asm)
+ fprintf (file, " ; restore previous frame ptr");
+ fprintf (file, "\n");
+ }
+
+ if (size > 0)
+ {
+ fprintf (file, "\t%s\tr15,%d",
+ (size <= 16 ? "aisp" : "aim"), size);
+ if (flag_verbose_asm)
+ fprintf (file, " ; free up local-var space");
+ fprintf (file, "\n");
+ }
+
+ fprintf (file, "\turs\tr15\n\n");
+}
+
void
notice_update_cc (exp)
rtx exp;
#define DEFAULT_CALLER_SAVES
-
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) { \
- if (flag_verbose_asm) \
- { \
- int regno, regs_used = 0; \
- fprintf (FILE, "\t; registers used: "); \
- for (regno = 0; regno < 14; regno++) \
- if (regs_ever_live[regno]) \
- { \
- fprintf (FILE, " %s", reg_names[regno]); \
- regs_used++; \
- } \
- if (regs_used == 0) \
- fprintf (FILE, "(none)"); \
- } \
- if (SIZE > 0) \
- { \
- fprintf (FILE, "\n\t%s\tr15,%d", \
- (SIZE <= 16 ? "sisp" : "sim"), SIZE); \
- if (flag_verbose_asm) \
- fprintf (FILE, " ; reserve local-variable space"); \
- } \
- if (frame_pointer_needed) \
- { \
- fprintf(FILE, "\n\tpshm\tr14,r14"); \
- if (flag_verbose_asm) \
- fprintf (FILE, " ; push old frame"); \
- fprintf (FILE, "\n\tlr\tr14,r15"); \
- if (flag_verbose_asm) \
- fprintf (FILE, " ; set new frame"); \
- } \
- fprintf (FILE, "\n"); \
- program_counter = 0; \
- jmplbl_ndx = -1; \
-}
-
/************* 1750: PROFILER HANDLING NOT YET DONE !!!!!!! *************/
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 0
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) { \
- if (frame_pointer_needed) \
- { \
- fprintf (FILE, "\tlr\tr15,r14"); \
- if (flag_verbose_asm) \
- fprintf (FILE, " ; set stack ptr to frame ptr"); \
- fprintf (FILE, "\n\tpopm\tr14,r14"); \
- if (flag_verbose_asm) \
- fprintf (FILE, " ; restore previous frame ptr"); \
- fprintf (FILE, "\n"); \
- } \
- if (SIZE > 0) \
- { \
- fprintf (FILE, "\t%s\tr15,%d", \
- (SIZE <= 16 ? "aisp" : "aim"), SIZE); \
- if (flag_verbose_asm) \
- fprintf (FILE, " ; free up local-var space"); \
- fprintf (FILE, "\n"); \
- } \
- fprintf (FILE, "\turs\tr15\n\n"); \
-}
-
/* If the memory address ADDR is relative to the frame pointer,
correct it to be relative to the stack pointer instead.
This is for when we don't use a frame pointer.
extern int null_epilogue PARAMS ((void));
extern void print_operand PARAMS ((FILE *, rtx, int));
extern void a29k_compute_reg_names PARAMS ((void));
-extern void output_prolog PARAMS ((FILE *, int));
-extern void output_epilog PARAMS ((FILE *, int));
#endif /* RTX_CODE */
static void a29k_set_memflags_1 PARAMS ((rtx, int, int, int, int));
static void compute_regstack_size PARAMS ((void));
static void check_epilogue_internal_label PARAMS ((FILE *));
+static void output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
#define min(A,B) ((A) < (B) ? (A) : (B))
int a29k_compare_fp_p;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Output function prolog code to file FILE. Memory stack size is SIZE. */
-void
-output_prolog (file, size)
+static void
+output_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int i;
int arg_count = 0;
stack size. The register stack size is in the variable
A29K_REGSTACK_SIZE. */
-void
-output_epilog (file, size)
+static void
+output_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
rtx insn;
int locals_unavailable = 0; /* True until after first insn
a29k_function_name = NAME; \
a29k_compute_reg_names ();
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
-
/* Define the number of delay slots needed for the function epilogue.
On the 29k, we need a slot except when we have a register stack adjustment,
extern unsigned int arc_compute_frame_size PARAMS ((int));
extern void arc_save_restore PARAMS ((FILE *, const char *, unsigned int,
unsigned int, const char *));
-extern void arc_output_function_prologue PARAMS ((FILE *, int));
-extern void arc_output_function_epilogue PARAMS ((FILE *, int));
extern int arc_delay_slots_for_epilogue PARAMS ((void));
extern void arc_finalize_pic PARAMS ((void));
extern void arc_ccfsm_at_label PARAMS ((const char *, int));
static void arc_init_reg_tables PARAMS ((void));
static int get_arc_condition_code PARAMS ((rtx));
static int arc_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
+static void arc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void arc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE arc_valid_decl_attribute
\f
/* Set up the stack and frame pointer (if desired) for the function. */
-void
+static void
arc_output_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
const char *sp_str = reg_names[STACK_POINTER_REGNUM];
const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
/* Do any necessary cleanup after a function to restore stack, frame,
and regs. */
-void
+static void
arc_output_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
rtx epilogue_delay = current_function_epilogue_delay_list;
int noepilogue = FALSE;
is passed to a function, or 0 to use `invisible' first argument. */
#define STRUCT_VALUE 0
\f
-/* Function entry and exit. */
-
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-arc_output_function_prologue (FILE, SIZE)
-
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
functions that have frame pointers.
No definition is equivalent to always zero. */
#define EXIT_IGNORE_STACK 0
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-arc_output_function_epilogue (FILE, SIZE)
-
/* Epilogue delay slots. */
#define DELAY_SLOTS_FOR_EPILOGUE arc_delay_slots_for_epilogue ()
extern void arm_finalize_pic PARAMS ((int));
extern int arm_volatile_func PARAMS ((void));
extern const char * arm_output_epilogue PARAMS ((int));
-extern void output_func_epilogue PARAMS ((int));
extern void arm_expand_prologue PARAMS ((void));
/* Used in arm.md, but defined in output.c. */
extern void assemble_align PARAMS ((int));
extern void output_ascii_pseudo_op PARAMS ((FILE *, const unsigned char *, int));
extern const char * output_return_instruction PARAMS ((rtx, int, int));
extern void arm_poke_function_name PARAMS ((FILE *, char *));
-extern void output_arm_prologue PARAMS ((FILE *, int));
extern void arm_print_operand PARAMS ((FILE *, rtx, int));
extern void arm_print_operand_address PARAMS ((FILE *, rtx));
extern void arm_final_prescan_insn PARAMS ((rtx));
extern int is_called_in_ARM_mode PARAMS ((tree));
#endif
extern int thumb_shiftable_const PARAMS ((unsigned HOST_WIDE_INT));
-extern void output_thumb_prologue PARAMS ((FILE *));
#ifdef RTX_CODE
extern void thumb_final_prescan_insn PARAMS ((rtx));
extern const char * thumb_load_double_from_address
tree, tree));
static int arm_valid_decl_attribute_p PARAMS ((tree, tree,
tree, tree));
+static void arm_output_function_epilogue PARAMS ((FILE *,
+ HOST_WIDE_INT));
+static void arm_output_function_prologue PARAMS ((FILE *,
+ HOST_WIDE_INT));
+static void thumb_output_function_prologue PARAMS ((FILE *,
+ HOST_WIDE_INT));
static int arm_comp_type_attributes PARAMS ((tree, tree));
static void arm_set_default_type_attributes PARAMS ((tree));
#undef Hint
# define TARGET_VALID_DECL_ATTRIBUTE arm_valid_decl_attribute_p
#endif
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
+
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
+
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
/* Place some comments into the assembler stream
describing the current function. */
-void
-output_arm_prologue (f, frame_size)
+static void
+arm_output_function_prologue (f, frame_size)
FILE * f;
- int frame_size;
+ HOST_WIDE_INT frame_size;
{
unsigned long func_type;
+
+ if (!TARGET_ARM)
+ {
+ thumb_output_function_prologue (f, frame_size);
+ return;
+ }
/* Sanity check. */
if (arm_ccfsm_state || arm_target_insn)
return "";
}
-void
-output_func_epilogue (frame_size)
- int frame_size;
+static void
+arm_output_function_epilogue (file, frame_size)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT frame_size;
{
if (TARGET_THUMB)
{
emit_insn (gen_blockage ());
}
-void
-output_thumb_prologue (f)
+static void
+thumb_output_function_prologue (f, size)
FILE * f;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
int live_regs_mask = 0;
int high_regs_pushed = 0;
(PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \
}
-/* Generate assembly output for the start of a function. */
-#define FUNCTION_PROLOGUE(STREAM, SIZE) \
- do \
- { \
- if (TARGET_ARM) \
- output_arm_prologue (STREAM, SIZE); \
- else \
- output_thumb_prologue (STREAM); \
- } \
- while (0)
-
/* If your target environment doesn't prefix user functions with an
underscore, you may wish to re-define this to prevent any conflicts.
e.g. AOF may prefix mcount with an underscore. */
frame. */
#define EXIT_IGNORE_STACK 1
-/* Generate the assembly code for function exit. */
-#define FUNCTION_EPILOGUE(STREAM, SIZE) \
- output_func_epilogue (SIZE)
-
#define EPILOGUE_USES(REGNO) (reload_completed && (REGNO) == LR_REGNUM)
/* Determine if the epilogue should be output as RTL.
extern void asm_globalize_label PARAMS ((FILE *file, const char *name));
extern void order_regs_for_local_alloc PARAMS ((void));
extern int initial_elimination_offset PARAMS ((int from, int to));
-extern void function_prologue PARAMS ((FILE *file, int size));
-extern void function_epilogue PARAMS ((FILE *file, int size));
extern void progmem_section PARAMS ((void));
extern int mask_one_bit_p PARAMS ((HOST_WIDE_INT mask));
extern void gas_output_limited_string PARAMS ((FILE *file, const char *str));
void debug_hard_reg_set PARAMS ((HARD_REG_SET set));
static int avr_valid_type_attribute PARAMS ((tree, tree, tree, tree));
static int avr_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
+static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Allocate registers from r25 to r8 for parameters for function calls */
#define FIRST_CUM_REG 26
int avr_case_values_threshold = 30000;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE avr_valid_decl_attribute
/* Output function prologue */
-void
-function_prologue (file, size)
+static void
+avr_output_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int reg;
int interrupt_func_p;
/* Output function epilogue */
-void
-function_epilogue (file, size)
+static void
+avr_output_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int reg;
int interrupt_func_p;
the frame pointer. A definition of 0 means that the address is
passed as an "invisible" first argument. */
-#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue (FILE, SIZE)
-/* A C compound statement that outputs the assembler code for entry
- to a function. The prologue is responsible for setting up the
- stack frame, initializing the frame pointer register, saving
- registers that must be saved, and allocating SIZE additional bytes
- of storage for the local variables. SIZE is an integer. FILE is
- a stdio stream to which the assembler code should be output.
-
- The label for the beginning of the function need not be output by
- this macro. That has already been done when the macro is run.
-
- To determine which registers to save, the macro can refer to the
- array `regs_ever_live': element R is nonzero if hard register R is
- used anywhere within the function. This implies the function
- prologue should save register R, provided it is not one of the
- call-used registers. (`FUNCTION_EPILOGUE' must likewise use
- `regs_ever_live'.)
-
- On machines that have "register windows", the function entry code
- does not save on the stack the registers that are in the windows,
- even if they are supposed to be preserved by function calls;
- instead it takes appropriate steps to "push" the register stack,
- if any non-call-used registers are used in the function.
-
- On machines where functions may or may not have frame-pointers, the
- function entry code must vary accordingly; it must set up the frame
- pointer if one is wanted, and not otherwise. To determine whether
- a frame pointer is in wanted, the macro can refer to the variable
- `frame_pointer_needed'. The variable's value will be 1 at run
- time in a function that needs a frame pointer. *Note
- Elimination::.
-
- The function entry code is responsible for allocating any stack
- space required for the function. This stack space consists of the
- regions listed below. In most cases, these regions are allocated
- in the order listed, with the last listed region closest to the
- top of the stack (the lowest address if `STACK_GROWS_DOWNWARD' is
- defined, and the highest address if it is not defined). You can
- use a different order for a machine if doing so is more convenient
- or required for compatibility reasons. Except in cases where
- required by standard or by a debugger, there is no reason why the
- stack layout used by GCC need agree with that used by other
- compilers for a machine.
-
- * A region of `current_function_pretend_args_size' bytes of
- uninitialized space just underneath the first argument
- arriving on the stack. (This may not be at the very start of
- the allocated stack region if the calling sequence has pushed
- anything else since pushing the stack arguments. But
- usually, on such machines, nothing else has been pushed yet,
- because the function prologue itself does all the pushing.)
- This region is used on machines where an argument may be
- passed partly in registers and partly in memory, and, in some
- cases to support the features in `varargs.h' and `stdargs.h'.
-
- * An area of memory used to save certain registers used by the
- function. The size of this area, which may also include
- space for such things as the return address and pointers to
- previous stack frames, is machine-specific and usually
- depends on which registers have been used in the function.
- Machines with register windows often do not require a save
- area.
-
- * A region of at least SIZE bytes, possibly rounded up to an
- allocation boundary, to contain the local variables of the
- function. On some machines, this region and the save area
- may occur in the opposite order, with the save area closer to
- the top of the stack.
-
- * Optionally, when `ACCUMULATE_OUTGOING_ARGS' is defined, a
- region of `current_function_outgoing_args_size' bytes to be
- used for outgoing argument lists of the function. *Note
- Stack Arguments::.
-
- Normally, it is necessary for the macros `FUNCTION_PROLOGUE' and
- `FUNCTION_EPILOGE' to treat leaf functions specially. The C
- variable `leaf_function' is nonzero for such a function. */
-
#define EPILOGUE_USES(REGNO) 0
/* Define this macro as a C expression that is nonzero for registers
are used by the epilogue or the `return' pattern. The stack and
frame pointer registers are already be assumed to be used as
needed. */
-#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue (FILE, SIZE)
-/* A C compound statement that outputs the assembler code for exit
- from a function. The epilogue is responsible for restoring the
- saved registers and stack pointer to their values when the
- function was called, and returning control to the caller. This
- macro takes the same arguments as the macro `FUNCTION_PROLOGUE',
- and the registers to restore are determined from `regs_ever_live'
- and `CALL_USED_REGISTERS' in the same way.
-
- On some machines, there is a single instruction that does all the
- work of returning from the function. On these machines, give that
- instruction the name `return' and do not define the macro
- `FUNCTION_EPILOGUE' at all.
-
- Do not define a pattern named `return' if you want the
- `FUNCTION_EPILOGUE' to be used. If you want the target switches
- to control whether return instructions or epilogues are used,
- define a `return' pattern with a validity condition that tests the
- target switches appropriately. If the `return' pattern's validity
- condition is false, epilogues will be used.
-
- On machines where functions may or may not have frame-pointers, the
- function exit code must vary accordingly. Sometimes the code for
- these two cases is completely different. To determine whether a
- frame pointer is wanted, the macro can refer to the variable
- `frame_pointer_needed'. The variable's value will be 1 when
- compiling a function that needs a frame pointer.
-
- Normally, `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' must treat
- leaf functions specially. The C variable `leaf_function' is
- nonzero for such a function. *Note Leaf Functions::.
-
- On some machines, some functions pop their arguments on exit while
- others leave that for the caller to do. For example, the 68020
- when given `-mrtd' pops arguments in functions that take a fixed
- number of arguments.
-
- Your definition of the macro `RETURN_POPS_ARGS' decides which
- functions pop their own arguments. `FUNCTION_EPILOGUE' needs to
- know what was decided. The variable that is called
- `current_function_pops_args' is the number of bytes of its
- arguments that a function should pop. *Note Scalar Return::. */
-
#define STRICT_ARGUMENT_NAMING 1
/* Define this macro if the location where a function argument is
passed depends on whether or not it is a named argument.
extern struct rtx_def *clipper_builtin_saveregs PARAMS ((void));
extern int clipper_frame_size PARAMS ((int));
-extern void output_function_prologue PARAMS ((FILE *, int));
-extern void output_function_epilogue PARAMS ((FILE *, int));
#ifdef TREE_CODE
extern tree clipper_build_va_list PARAMS ((void));
#endif /* TREE_CODE */
#include "output.h"
#include "insn-attr.h"
#include "tree.h"
+#include "expr.h"
#include "c-tree.h"
#include "function.h"
-#include "expr.h"
#include "flags.h"
#include "recog.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+static void clipper_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void clipper_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+
extern char regs_ever_live[];
extern int frame_pointer_needed;
static int frame_size;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE clipper_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE clipper_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
can run with misaligned stack -> subq $4,sp / add $4,sp on entry and exit
can be omitted. */
-void
-output_function_prologue (file, lsize)
+static void
+clipper_output_function_prologue (file, lsize)
FILE *file;
- int lsize; /* size for locals */
+ HOST_WIDE_INT lsize; /* size for locals */
{
int i, offset;
int size;
}
}
-void
-output_function_epilogue (file, size)
+static void
+clipper_output_function_epilogue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
int i, offset;
#define EXPAND_BUILTIN_SAVEREGS() clipper_builtin_saveregs ()
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_function_prologue (FILE,SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_function_epilogue(FILE,SIZE)
-
/* Store in the variable DEPTH the initial difference between the
frame pointer reg contents and the stack pointer reg contents,
as of the start of the function body. This depends on the layout
static rtx convert_arg_pushes ();
#endif
static void expand_movstr_call PARAMS ((rtx *));
+static void convex_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void convex_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE convex_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE convex_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+static void
+convex_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ size = ((size) + 7) & -8;
+ if (size)
+ fprintf (file, "\tsub.w #%d,sp\n", size);
+}
+
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+convex_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ /* Follow function with a zero to stop c34 icache prefetching. */
+ fprintf (file, "\tds.h 0\n");
+}
+
/* Here from OVERRIDE_OPTIONS at startup. Initialize constant tables. */
void
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
((MODE) == VOIDmode ? GEN_INT ((CUM)) : 0)
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ \
- int size = ((SIZE) + 7) & -8; \
- if (size != 0) \
- fprintf (FILE, "\tsub.w #%d,sp\n", size); \
-}
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ \
- /* Follow function with a zero to stop c34 icache prefetching. */ \
- fprintf (FILE, "\tds.h 0\n"); \
-}
-
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts. */
#endif /* RTX_CODE */
#endif /* TREE_CODE */
-extern void d30v_function_prologue PARAMS ((FILE *, int));
extern void d30v_expand_prologue PARAMS ((void));
-extern void d30v_function_epilogue PARAMS ((FILE *, int));
extern void d30v_expand_epilogue PARAMS ((void));
extern void d30v_function_profiler PARAMS ((FILE *, int));
#ifdef RTX_CODE
static void d30v_init_machine_status PARAMS ((struct function *));
static void d30v_mark_machine_status PARAMS ((struct function *));
static void d30v_free_machine_status PARAMS ((struct function *));
+static void d30v_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void d30v_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Define the information needed to generate branch and scc insns. This is
stored from the compare operation. */
enum reg_class reg_class_from_letter[256];
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE d30v_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE d30v_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
return ptr_rtx;
}
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
-/* A C compound statement that outputs the assembler code for entry to a
- function. The prologue is responsible for setting up the stack frame,
- initializing the frame pointer register, saving registers that must be
- saved, and allocating SIZE additional bytes of storage for the local
- variables. SIZE is an integer. FILE is a stdio stream to which the
- assembler code should be output.
-
- The label for the beginning of the function need not be output by this
- macro. That has already been done when the macro is run.
-
- To determine which registers to save, the macro can refer to the array
- `regs_ever_live': element R is nonzero if hard register R is used anywhere
- within the function. This implies the function prologue should save
- register R, provided it is not one of the call-used registers.
- (`FUNCTION_EPILOGUE' must likewise use `regs_ever_live'.)
-
- On machines that have "register windows", the function entry code does not
- save on the stack the registers that are in the windows, even if they are
- supposed to be preserved by function calls; instead it takes appropriate
- steps to "push" the register stack, if any non-call-used registers are used
- in the function.
-
- On machines where functions may or may not have frame-pointers, the function
- entry code must vary accordingly; it must set up the frame pointer if one is
- wanted, and not otherwise. To determine whether a frame pointer is in
- wanted, the macro can refer to the variable `frame_pointer_needed'. The
- variable's value will be 1 at run time in a function that needs a frame
- pointer. *Note Elimination::.
-
- The function entry code is responsible for allocating any stack space
- required for the function. This stack space consists of the regions listed
- below. In most cases, these regions are allocated in the order listed, with
- the last listed region closest to the top of the stack (the lowest address
- if `STACK_GROWS_DOWNWARD' is defined, and the highest address if it is not
- defined). You can use a different order for a machine if doing so is more
- convenient or required for compatibility reasons. Except in cases where
- required by standard or by a debugger, there is no reason why the stack
- layout used by GCC need agree with that used by other compilers for a
- machine.
-
- * A region of `current_function_pretend_args_size' bytes of
- uninitialized space just underneath the first argument
- arriving on the stack. (This may not be at the very start of
- the allocated stack region if the calling sequence has pushed
- anything else since pushing the stack arguments. But
- usually, on such machines, nothing else has been pushed yet,
- because the function prologue itself does all the pushing.)
- This region is used on machines where an argument may be
- passed partly in registers and partly in memory, and, in some
- cases to support the features in `varargs.h' and `stdargs.h'.
-
- * An area of memory used to save certain registers used by the
- function. The size of this area, which may also include
- space for such things as the return address and pointers to
- previous stack frames, is machine-specific and usually
- depends on which registers have been used in the function.
- Machines with register windows often do not require a save
- area.
-
- * A region of at least SIZE bytes, possibly rounded up to an
- allocation boundary, to contain the local variables of the
- function. On some machines, this region and the save area
- may occur in the opposite order, with the save area closer to
- the top of the stack.
-
- * Optionally, when `ACCUMULATE_OUTGOING_ARGS' is defined, a
- region of `current_function_outgoing_args_size' bytes to be
- used for outgoing argument lists of the function. *Note
- Stack Arguments::.
-
- Normally, it is necessary for the macros `FUNCTION_PROLOGUE' and
- `FUNCTION_EPILOGUE' to treat leaf functions specially. The C variable
- `leaf_function' is nonzero for such a function. */
-
-/* For the d30v, move all of the prologue processing into separate insns. */
-void
-d30v_function_prologue (stream, size)
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+static void
+d30v_output_function_prologue (stream, size)
FILE *stream ATTRIBUTE_UNUSED;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
+ /* For the d30v, move all of the prologue processing into separate
+ insns. */
}
\f
-/* Called after register allocation to add any instructions needed for the
- prologue. Using a prologue insn is favored compared to putting all of the
- instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
- to intermix instructions with the saves of the caller saved registers. In
- some cases, it might be necessary to emit a barrier instruction as the last
- insn to prevent such scheduling. */
+/* Called after register allocation to add any instructions needed for
+ the prologue. Using a prologue insn is favored compared to putting
+ all of the instructions in output_function_prologue (), since it
+ allows the scheduler to intermix instructions with the saves of the
+ caller saved registers. In some cases, it might be necessary to
+ emit a barrier instruction as the last insn to prevent such
+ scheduling. */
void
d30v_expand_prologue ()
}
\f
-/* A C compound statement that outputs the assembler code for exit from a
- function. The epilogue is responsible for restoring the saved registers and
- stack pointer to their values when the function was called, and returning
- control to the caller. This macro takes the same arguments as the macro
- `FUNCTION_PROLOGUE', and the registers to restore are determined from
- `regs_ever_live' and `CALL_USED_REGISTERS' in the same way.
-
- On some machines, there is a single instruction that does all the work of
- returning from the function. On these machines, give that instruction the
- name `return' and do not define the macro `FUNCTION_EPILOGUE' at all.
-
- Do not define a pattern named `return' if you want the `FUNCTION_EPILOGUE'
- to be used. If you want the target switches to control whether return
- instructions or epilogues are used, define a `return' pattern with a
- validity condition that tests the target switches appropriately. If the
- `return' pattern's validity condition is false, epilogues will be used.
-
- On machines where functions may or may not have frame-pointers, the function
- exit code must vary accordingly. Sometimes the code for these two cases is
- completely different. To determine whether a frame pointer is wanted, the
- macro can refer to the variable `frame_pointer_needed'. The variable's
- value will be 1 when compiling a function that needs a frame pointer.
-
- Normally, `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' must treat leaf
- functions specially. The C variable `leaf_function' is nonzero for such a
- function. *Note Leaf Functions::.
-
- On some machines, some functions pop their arguments on exit while others
- leave that for the caller to do. For example, the 68020 when given `-mrtd'
- pops arguments in functions that take a fixed number of arguments.
-
- Your definition of the macro `RETURN_POPS_ARGS' decides which functions pop
- their own arguments. `FUNCTION_EPILOGUE' needs to know what was decided.
- The variable that is called `current_function_pops_args' is the number of
- bytes of its arguments that a function should pop. *Note Scalar Return::. */
-
-/* For the d30v, move all processing to be as insns, but do any cleanup
- here, since it is done after handling all of the insns. */
-void
-d30v_function_epilogue (stream, size)
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+d30v_output_function_epilogue (stream, size)
FILE *stream ATTRIBUTE_UNUSED;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
+ /* For the d30v, move all processing to be as insns, but do any
+ cleanup here, since it is done after handling all of the insns. */
d30v_stack_cache = (d30v_stack_t *)0; /* reset stack cache */
}
\f
-/* Called after register allocation to add any instructions needed for the
- epilogue. Using a epilogue insn is favored compared to putting all of the
- instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
- to intermix instructions with the saves of the caller saved registers. In
- some cases, it might be necessary to emit a barrier instruction as the last
- insn to prevent such scheduling. */
+/* Called after register allocation to add any instructions needed for
+ the epilogue. Using a epilogue insn is favored compared to putting
+ all of the instructions in output_function_prologue(), since it
+ allows the scheduler to intermix instructions with the saves of the
+ caller saved registers. In some cases, it might be necessary to
+ emit a barrier instruction as the last insn to prevent such
+ scheduling. */
void
d30v_expand_epilogue ()
/* #define CALLER_SAVE_PROFITABLE(REFS, CALLS) */
\f
-/* Function Entry and Exit */
-
-/* A C compound statement that outputs the assembler code for entry to a
- function. The prologue is responsible for setting up the stack frame,
- initializing the frame pointer register, saving registers that must be
- saved, and allocating SIZE additional bytes of storage for the local
- variables. SIZE is an integer. FILE is a stdio stream to which the
- assembler code should be output.
-
- The label for the beginning of the function need not be output by this
- macro. That has already been done when the macro is run.
-
- To determine which registers to save, the macro can refer to the array
- `regs_ever_live': element R is nonzero if hard register R is used anywhere
- within the function. This implies the function prologue should save
- register R, provided it is not one of the call-used registers.
- (`FUNCTION_EPILOGUE' must likewise use `regs_ever_live'.)
-
- On machines that have "register windows", the function entry code does not
- save on the stack the registers that are in the windows, even if they are
- supposed to be preserved by function calls; instead it takes appropriate
- steps to "push" the register stack, if any non-call-used registers are used
- in the function.
-
- On machines where functions may or may not have frame-pointers, the function
- entry code must vary accordingly; it must set up the frame pointer if one is
- wanted, and not otherwise. To determine whether a frame pointer is in
- wanted, the macro can refer to the variable `frame_pointer_needed'. The
- variable's value will be 1 at run time in a function that needs a frame
- pointer. *Note Elimination::.
-
- The function entry code is responsible for allocating any stack space
- required for the function. This stack space consists of the regions listed
- below. In most cases, these regions are allocated in the order listed, with
- the last listed region closest to the top of the stack (the lowest address
- if `STACK_GROWS_DOWNWARD' is defined, and the highest address if it is not
- defined). You can use a different order for a machine if doing so is more
- convenient or required for compatibility reasons. Except in cases where
- required by standard or by a debugger, there is no reason why the stack
- layout used by GCC need agree with that used by other compilers for a
- machine.
-
- * A region of `current_function_pretend_args_size' bytes of
- uninitialized space just underneath the first argument
- arriving on the stack. (This may not be at the very start of
- the allocated stack region if the calling sequence has pushed
- anything else since pushing the stack arguments. But
- usually, on such machines, nothing else has been pushed yet,
- because the function prologue itself does all the pushing.)
- This region is used on machines where an argument may be
- passed partly in registers and partly in memory, and, in some
- cases to support the features in `varargs.h' and `stdargs.h'.
-
- * An area of memory used to save certain registers used by the
- function. The size of this area, which may also include
- space for such things as the return address and pointers to
- previous stack frames, is machine-specific and usually
- depends on which registers have been used in the function.
- Machines with register windows often do not require a save
- area.
-
- * A region of at least SIZE bytes, possibly rounded up to an
- allocation boundary, to contain the local variables of the
- function. On some machines, this region and the save area
- may occur in the opposite order, with the save area closer to
- the top of the stack.
-
- * Optionally, when `ACCUMULATE_OUTGOING_ARGS' is defined, a
- region of `current_function_outgoing_args_size' bytes to be
- used for outgoing argument lists of the function. *Note
- Stack Arguments::.
-
- Normally, it is necessary for the macros `FUNCTION_PROLOGUE' and
- `FUNCTION_EPILOGUE' to treat leaf functions specially. The C variable
- `leaf_function' is nonzero for such a function. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) d30v_function_prologue (FILE, SIZE)
-
-/* Define this macro as a C expression that is nonzero if the return
- instruction or the function epilogue ignores the value of the stack pointer;
- in other words, if it is safe to delete an instruction to adjust the stack
- pointer before a return from the function.
-
- Note that this macro's value is relevant only for functions for which frame
- pointers are maintained. It is never safe to delete a final stack
- adjustment in a function that has no frame pointer, and the compiler knows
- this regardless of `EXIT_IGNORE_STACK'. */
/* #define EXIT_IGNORE_STACK */
/* Define this macro as a C expression that is nonzero for registers
needed. */
#define EPILOGUE_USES(REGNO) ((REGNO) == GPR_LINK)
-/* A C compound statement that outputs the assembler code for exit from a
- function. The epilogue is responsible for restoring the saved registers and
- stack pointer to their values when the function was called, and returning
- control to the caller. This macro takes the same arguments as the macro
- `FUNCTION_PROLOGUE', and the registers to restore are determined from
- `regs_ever_live' and `CALL_USED_REGISTERS' in the same way.
-
- On some machines, there is a single instruction that does all the work of
- returning from the function. On these machines, give that instruction the
- name `return' and do not define the macro `FUNCTION_EPILOGUE' at all.
-
- Do not define a pattern named `return' if you want the `FUNCTION_EPILOGUE'
- to be used. If you want the target switches to control whether return
- instructions or epilogues are used, define a `return' pattern with a
- validity condition that tests the target switches appropriately. If the
- `return' pattern's validity condition is false, epilogues will be used.
-
- On machines where functions may or may not have frame-pointers, the function
- exit code must vary accordingly. Sometimes the code for these two cases is
- completely different. To determine whether a frame pointer is wanted, the
- macro can refer to the variable `frame_pointer_needed'. The variable's
- value will be 1 when compiling a function that needs a frame pointer.
-
- Normally, `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' must treat leaf
- functions specially. The C variable `leaf_function' is nonzero for such a
- function. *Note Leaf Functions::.
-
- On some machines, some functions pop their arguments on exit while others
- leave that for the caller to do. For example, the 68020 when given `-mrtd'
- pops arguments in functions that take a fixed number of arguments.
-
- Your definition of the macro `RETURN_POPS_ARGS' decides which functions pop
- their own arguments. `FUNCTION_EPILOGUE' needs to know what was decided.
- The variable that is called `current_function_pops_args' is the number of
- bytes of its arguments that a function should pop. *Note Scalar Return::. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) d30v_function_epilogue (FILE, SIZE)
-
/* Define this macro if the function epilogue contains delay slots to which
instructions from the rest of the function can be "moved". The definition
should be a C expression whose value is an integer representing the number
The insns accepted to fill the epilogue delay slots are put in an
RTL list made with `insn_list' objects, stored in the variable
`current_function_epilogue_delay_list'. The insn for the first
- delay slot comes first in the list. Your definition of the macro
- `FUNCTION_EPILOGUE' should fill the delay slots by outputting the
+ delay slot comes first in the list. Your definition of the function
+ output_function_epilogue() should fill the delay slots by outputting the
insns in this list, usually by calling `final_scan_insn'.
You need not define this macro if you did not define
the return address. Hence returning from FUNCTION will return to whoever
called the current `thunk'.
- The effect must be as if FUNCTION had been called directly with the adjusted
- first argument. This macro is responsible for emitting all of the code for
- a thunk function; `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' are not
- invoked.
+ The effect must be as if FUNCTION had been called directly with the
+ adjusted first argument. This macro is responsible for emitting
+ all of the code for a thunk function; output_function_prologue()
+ and output_function_epilogue() are not invoked.
The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been
extracted from it.) It might possibly be useful on some targets, but
code to call function `__bb_trace_ret'. The assembler code should
only be output if the global compile flag `profile_block_flag' ==
2. This macro has to be used at every place where code for
- returning from a function is generated (e.g. `FUNCTION_EPILOGUE').
- Although you have to write the definition of `FUNCTION_EPILOGUE'
+ returning from a function is generated (e.g. output_function_epilogue()).
+ Although you have to write the definition of output_function_epilogue()
as well, you have to define this macro to tell the compiler, that
the proper call to `__bb_trace_ret' is produced. */
/* #define FUNCTION_BLOCK_PROFILER_EXIT(FILE) */
the assembler code can be concatenated with the string ID, to obtain a
unique lable name.
- Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or
- `FUNCTION_EPILOGUE' must be saved in the macros `FUNCTION_BLOCK_PROFILER',
- `FUNCTION_BLOCK_PROFILER_EXIT' and `BLOCK_PROFILER' prior calling
- `__bb_init_trace_func', `__bb_trace_ret' and `__bb_trace_func' respectively. */
+ Registers or condition codes clobbered by output_function_prologue()
+ or output_function_epilogue() must be saved in the macros
+ `FUNCTION_BLOCK_PROFILER', FUNCTION_BLOCK_PROFILER_EXIT' and
+ `BLOCK_PROFILER' prior calling `__bb_init_trace_func', `__bb_trace_ret'
+ and `__bb_trace_func' respectively. */
/* #define MACHINE_STATE_SAVE(ID) */
/* A C statement or compound statement to restore all registers, including
condition codes, saved by `MACHINE_STATE_SAVE'.
- Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or
- `FUNCTION_EPILOGUE' must be restored in the macros
+ Registers or condition codes clobbered by output_function_prologue()
+ or output_function_epilogue() must be restored in the macros
`FUNCTION_BLOCK_PROFILER', `FUNCTION_BLOCK_PROFILER_EXIT' and
`BLOCK_PROFILER' after calling `__bb_init_trace_func', `__bb_trace_ret' and
`__bb_trace_func' respectively. */
stack slot. This default is right for most machines. The exceptions are
machines where it is impossible to execute instructions in the stack area.
On such machines, you may have to implement a separate stack, using this
- macro in conjunction with `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE'.
+ macro in conjunction with output_function_prologue () and
+ output_function_epilogue ().
FP points to a data structure, a `struct function', which describes the
compilation status of the immediate containing function of the function
To support optional call frame debugging information, you must also define
`INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the
prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa'
- and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you
- don't.
+ and `dwarf2out_reg_save' as appropriate from output_function_prologue() if
+ you don't.
Defined in svr4.h. */
/* #define DWARF2_DEBUGGING_INFO */
;; Called after register allocation to add any instructions needed for the
;; prologue. Using a prologue insn is favored compared to putting all of the
-;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+;; instructions in output_function_prologue (), since it allows the scheduler
;; to intermix instructions with the saves of the caller saved registers. In
;; some cases, it might be necessary to emit a barrier instruction as the last
;; insn to prevent such scheduling.
;; Called after register allocation to add any instructions needed for the
;; epilogue. Using a epilogue insn is favored compared to putting all of the
-;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+;; instructions in output_function_epilogue (), since it allows the scheduler
;; to intermix instructions with the saves of the caller saved registers. In
;; some cases, it might be necessary to emit a barrier instruction as the last
;; insn to prevent such scheduling.
extern int hard_regno_mode_ok PARAMS ((int, enum machine_mode));
extern enum reg_class dsp16xx_reg_class_from_letter PARAMS ((int));
extern int regno_reg_class PARAMS ((int));
-extern void function_prologue PARAMS ((FILE *, int));
-extern void function_epilogue PARAMS ((FILE *, int));
rtx dsp16xx_compare_op0;
rtx dsp16xx_compare_op1;
-struct rtx_def *(*dsp16xx_compare_gen)();
static const char *fp;
static const char *sp;
};
static int reg_save_size PARAMS ((void));
+static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE dsp16xx_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
return live;
}
-void
-function_prologue (file, size)
+static void
+dsp16xx_output_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int regno;
long total_size;
dsp16xx_lshrhi3_libcall = (rtx) 0;
}
-void
-function_epilogue (file, size)
+
+static void
+dsp16xx_output_function_epilogue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
int regno;
#if OLD_REGISTER_SAVE
else if (letter == 'm')
fprintf (file, "%s", himode_reg_name[REGNO (op)]);
else
- output_operand_lossgae ("Bad register extension code");
+ output_operand_lossage ("Bad register extension code");
}
else if (code == MEM)
output_address (XEXP(op,0));
else if (letter == 'h')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
else if (letter == 'U')
- fprint(f file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
else
output_addr_const (file, op);
}
#define FUNCTION_ARG_REGNO_P(N) \
((N) == REG_Y || (N) == REG_YL || (N) == REG_PROD || (N) == REG_PRODL)
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue(FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
internal_error ("Trampolines not yet implemented");
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE)
-
/* A C expression which is nonzero if a function must have and use a
frame pointer. If its value is nonzero the functions will have a
frame pointer. */
static const char *const cmp_tab[] = {
"gt", "gt", "eq", "eq", "ge", "ge", "lt", "lt", "ne", "ne",
"le", "le" };
+
+static void elxsi_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void elxsi_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE elxsi_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE elxsi_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+static void
+elxsi_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int cnt = 0;
+ extern char call_used_regs[];
+
+ /* the below two lines are a HACK, and should be deleted, but
+ for now are very much needed (1.35) */
+ if (frame_pointer_needed)
+ regs_ever_live[14] = 1, call_used_regs[14] = 0;
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ cnt += 8;
+
+ if (size + cnt)
+ fprintf (file, "\tadd.64\t.sp,=%d\n", -size - cnt);
+
+ cnt = 0;
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ fprintf (file, "\tst.64\t.r%d,[.sp]%d\n", regno, (cnt += 8) - 12);
+
+ if (frame_pointer_needed)
+ fprintf (file, "\tadd.64\t.r14,.sp,=%d\n", size + cnt);
+}
+
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+elxsi_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int cnt = 0;
+ extern char call_used_regs[];
+
+ /* this conditional is ONLY here because there is a BUG;
+ EXIT_IGNORE_STACK is ignored itself when the first part of
+ the condition is true! (at least in version 1.35) */
+ /* the 8*10 is for 64 bits of .r5 - .r14 */
+ if (current_function_calls_alloca || size >= (256 - 8 * 10))
+ {
+ /* use .r4 as a temporary! Ok for now.... */
+ fprintf (file, "\tld.64\t.r4,.r14\n");
+
+ for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ cnt += 8;
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ fprintf (file, "\tld.64\t.r%d,[.r14]%d\n", regno,
+ -((cnt -= 8) + 8) - 4 - size);
+
+ fprintf (file, "\tld.64\t.sp,.r4\n\texit\t0\n");
+ }
+ else
+ {
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ fprintf (file, "\tld.64\t.r%d,[.sp]%d\n", regno, (cnt + =8) - 12);
+
+ fprintf (file, "\texit\t%d\n", size + cnt);
+ }
+}
+
/* type is the index into the above table */
/* s is "" for signed, or "u" for unsigned */
const char *
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno; \
- register int cnt = 0; \
- extern char call_used_regs[]; \
- /* the below two lines are a HACK, and should be deleted, but \
- for now are very much needed (1.35) */ \
- if (frame_pointer_needed) \
- regs_ever_live[14]=1, call_used_regs[14]=0; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- cnt+=8; \
- if ((SIZE)+cnt) \
- fprintf (FILE, "\tadd.64\t.sp,=%d\n", -(SIZE)-cnt); \
- cnt = 0; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- fprintf (FILE, "\tst.64\t.r%d,[.sp]%d\n", regno, (cnt+=8)-12); \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tadd.64\t.r14,.sp,=%d\n", (SIZE)+cnt); \
-}
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 0
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int regno; \
- register int cnt = 0; \
- extern char call_used_regs[]; \
- /* this conditional is ONLY here because there is a BUG; \
- EXIT_IGNORE_STACK is ignored itself when the first part of \
- the condition is true! (at least in version 1.35) */ \
- /* the 8*10 is for 64 bits of .r5 - .r14 */ \
- if (current_function_calls_alloca || (SIZE)>=(256-8*10)) { \
- /* use .r4 as a temporary! Ok for now.... */ \
- fprintf (FILE, "\tld.64\t.r4,.r14\n"); \
- for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- cnt+=8; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- fprintf (FILE, "\tld.64\t.r%d,[.r14]%d\n", regno, \
- -((cnt-=8) + 8)-4-(SIZE)); \
- fprintf (FILE, "\tld.64\t.sp,.r4\n\texit\t0\n"); \
- } else { \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- fprintf (FILE, "\tld.64\t.r%d,[.sp]%d\n", regno, (cnt+=8)-12); \
- fprintf (FILE, "\texit\t%d\n", (SIZE)+cnt); \
- } }
-
/* If the memory address ADDR is relative to the frame pointer,
correct it to be relative to the stack pointer instead.
This is for when we don't use a frame pointer.
/* Called after register allocation to add any instructions needed for the
prologue. Using a prologue insn is favored compared to putting all of the
- instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+ instructions in output_function_prologue(), since it allows the scheduler
to intermix instructions with the saves of the caller saved registers. In
some cases, it might be necessary to emit a barrier instruction as the last
insn to prevent such scheduling. */
/* Called after register allocation to add any instructions needed for the
epilogue. Using a epilogue insn is favored compared to putting all of the
- instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler
+ instructions in output_function_epilogue(), since it allows the scheduler
to intermix instructions with the restores of the caller saved registers.
In some cases, it might be necessary to emit a barrier instruction as the
first insn to prevent such scheduling. */
;; Called after register allocation to add any instructions needed for the
;; prologue. Using a prologue insn is favored compared to putting all of the
-;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+;; instructions in output_function_prologue(), since it allows the scheduler
;; to intermix instructions with the saves of the caller saved registers. In
;; some cases, it might be necessary to emit a barrier instruction as the last
;; insn to prevent such scheduling.
;; Called after register allocation to add any instructions needed for the
;; epilogue. Using a epilogue insn is favored compared to putting all of the
-;; instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler
+;; instructions in output_function_epilogue(), since it allows the scheduler
;; to intermix instructions with the restores of the caller saved registers.
;; In some cases, it might be necessary to emit a barrier instruction as the
;; first insn to prevent such scheduling.
#endif /* TREE_CODE */
extern void h8300_init_once PARAMS ((void));
-extern void function_prologue PARAMS ((FILE *, int));
-extern void function_epilogue PARAMS ((FILE *, int));
extern void asm_file_start PARAMS ((FILE *));
extern void asm_file_end PARAMS ((FILE *));
extern int ok_for_bclr PARAMS ((HOST_WIDE_INT));
static void pop PARAMS ((FILE *, int));
static const char *cond_string PARAMS ((enum rtx_code));
static int h8300_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
+static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* CPU_TYPE, says what cpu we're compiling for. */
int cpu_type;
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE h8300_valid_decl_attribute
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE h8300_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Initialize various cpu specific globals at start up. */
/* Output assembly language code for the function prologue. */
-void
-function_prologue (file, size)
+static void
+h8300_output_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int fsize = round_frame_size (size);
int idx;
/* Output assembly language code for the function epilogue. */
-void
-function_epilogue (file, size)
+static void
+h8300_output_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int fsize = round_frame_size (size);
int idx;
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED)
-/* Generate assembly output for the start of a function. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- function_prologue (FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 0
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
- function_epilogue (FILE, SIZE)
-
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.
extern int mvs_need_alias PARAMS ((const char *));
extern int mvs_get_alias PARAMS ((const char *, char *));
extern int mvs_check_alias PARAMS ((const char *, char *));
-extern void i370_function_prolog PARAMS ((FILE *, int));
extern void check_label_emit PARAMS ((void));
extern void mvs_free_label_list PARAMS ((void));
static label_node_t * mvs_get_label PARAMS ((int));
static void i370_label_scan PARAMS ((void));
+static void i370_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void i370_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* ===================================================== */
/* defines and functions specific to the HLASM assembler */
};
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE i370_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE i370_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
}
}
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
#ifdef TARGET_HLASM
-void
-i370_function_prolog (f, l)
+static void
+i370_output_function_prologue (f, l)
FILE *f;
- int l;
+ HOST_WIDE_INT l;
{
#if MACROPROLOGUE == 1
fprintf (f, "* Function %s prologue\n", mvs_function_name);
also, to quite using addresses 136, 140, etc.
*/
-void
-i370_function_prolog (f, frame_size)
+static void
+i370_output_function_prologue (f, frame_size)
FILE *f;
- int frame_size;
+ HOST_WIDE_INT frame_size;
{
static int function_label_index = 1;
static int function_first = 0;
i370_label_scan ();
}
#endif /* TARGET_ELF_ABI */
+
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+i370_output_function_epilogue (file, l)
+ FILE *file;
+ HOST_WIDE_INT l ATTRIBUTE_UNUSED;
+{
+ int i;
+
+ check_label_emit ();
+ mvs_check_page (file, 14, 0);
+ fprintf (file, "* Function %s epilogue\n", mvs_function_name);
+ mvs_page_num++;
+
+#if MACROEPILOGUE == 1
+ fprintf (file, "\tEDCEPIL\n");
+#else /* MACROEPILOGUE != 1 */
+ fprintf (file, "\tL\t13,4(,13)\n");
+ fprintf (file, "\tL\t14,12(,13)\n");
+ fprintf (file, "\tLM\t2,12,28(13)\n");
+ fprintf (file, "\tBALR\t1,14\n");
+ fprintf (file, "\tDC\tA(");
+ assemble_name (file, mvs_function_name);
+ fprintf (file, ")\n" );
+#endif /* MACROEPILOGUE */
+
+ fprintf (file, "* Function %s literal pool\n", mvs_function_name);
+ fprintf (file, "\tDS\t0F\n" );
+ fprintf (file, "\tLTORG\n");
+ fprintf (file, "* Function %s page table\n", mvs_function_name);
+ fprintf (file, "\tDS\t0F\n");
+ fprintf (file, "PGT%d\tEQU\t*\n", function_base_page);
+
+ mvs_free_label_list();
+ for (i = function_base_page; i < mvs_page_num; i++)
+ fprintf (file, "\tDC\tA(PG%d)\n", i);
+}
} \
}
-/* This macro generates the assembly code for function entry.
- All of the C/370 environment is preserved. */
-#define FUNCTION_PROLOGUE(FILE, LSIZE) i370_function_prolog ((FILE), (LSIZE));
-
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
{ \
if (strlen (NAME) + 1 > mvs_function_name_length) \
fputs ("\tCSECT\n", FILE); \
}
-/* This macro generates the assembly code for function exit, on machines
- that need it. If FUNCTION_EPILOGUE is not defined then individual
- return instructions are generated for each return statement. Args are
- same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#if MACROEPILOGUE == 1
-#define FUNCTION_EPILOGUE(FILE, LSIZE) \
-{ \
- int i; \
- check_label_emit(); \
- mvs_check_page (FILE,14,0); \
- fprintf (FILE, "* Function %s epilogue\n", mvs_function_name); \
- fprintf (FILE, "\tEDCEPIL\n"); \
- mvs_page_num++; \
- fprintf (FILE, "* Function %s literal pool\n", mvs_function_name); \
- fprintf (FILE, "\tDS\t0F\n" ); \
- fprintf (FILE, "\tLTORG\n"); \
- fprintf (FILE, "* Function %s page table\n", mvs_function_name); \
- fprintf (FILE, "\tDS\t0F\n"); \
- fprintf (FILE, "PGT%d\tEQU\t*\n", function_base_page); \
- mvs_free_label_list(); \
- for ( i = function_base_page; i < mvs_page_num; i++ ) \
- fprintf (FILE, "\tDC\tA(PG%d)\n", i); \
-}
-#else /* MACROEPILOGUE != 1 */
-#define FUNCTION_EPILOGUE(FILE, LSIZE) \
-{ \
- int i; \
- check_label_emit(); \
- mvs_check_page (FILE,14,0); \
- fprintf (FILE, "* Function %s epilogue\n", mvs_function_name); \
- fprintf (FILE, "\tL\t13,4(,13)\n"); \
- fprintf (FILE, "\tL\t14,12(,13)\n"); \
- fprintf (FILE, "\tLM\t2,12,28(13)\n"); \
- fprintf (FILE, "\tBALR\t1,14\n"); \
- fprintf (FILE, "\tDC\tA("); \
- mvs_page_num++; \
- assemble_name (FILE, mvs_function_name); \
- fprintf (FILE, ")\n" ); \
- fprintf (FILE, "* Function %s literal pool\n", mvs_function_name); \
- fprintf (FILE, "\tDS\t0F\n" ); \
- fprintf (FILE, "\tLTORG\n"); \
- fprintf (FILE, "* Function %s page table\n", mvs_function_name); \
- fprintf (FILE, "\tDS\t0F\n"); \
- fprintf (FILE, "PGT%d\tEQU\t*\n", function_base_page); \
- mvs_free_label_list(); \
- for ( i = function_base_page; i < mvs_page_num; i++ ) \
- fprintf (FILE, "\tDC\tA(PG%d)\n", i); \
-}
-#endif /* MACROEPILOGUE */
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
} \
}
-/* This macro generates the assembly code for function exit, on machines
- that need it. If FUNCTION_EPILOGUE is not defined then individual
- return instructions are generated for each return statement. Args are
- same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, LSIZE) \
-{ \
- int i; \
- check_label_emit(); \
- mvs_check_page (FILE,14,0); \
- fprintf (FILE, "# Function epilogue\n"); \
- fprintf (FILE, "\tL\tsp,4(0,sp)\n"); \
- fprintf (FILE, "\tL\tlr,12(0,sp)\n"); \
- fprintf (FILE, "\tLM\t2,12,28(sp)\n"); \
- fprintf (FILE, "\tBASR\t1,lr\n"); \
- mvs_page_num++; \
- fprintf (FILE, "# Function literal pool\n"); \
- fprintf (FILE, "\t.balign\t4\n"); \
- fprintf (FILE, "\t.ltorg\n"); \
- fprintf (FILE, "# Function page table\n"); \
- fprintf (FILE, "\t.balign\t4\n"); \
- fprintf (FILE, ".LPGT%d:\n", function_base_page); \
- mvs_free_label_list(); \
- for ( i = function_base_page; i < mvs_page_num; i++ ) \
- fprintf (FILE, "\t.long\t.LPG%d\n", i); \
-}
-
-#define FUNCTION_PROLOGUE(FILE, LSIZE) i370_function_prolog ((FILE), (LSIZE));
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
/* Make it a no-op for now, so we can at least compile glibc */
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES ix86_comp_type_attributes
+#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
+ static void ix86_osf_output_function_prologue PARAMS ((FILE *,
+ HOST_WIDE_INT));
+# undef TARGET_ASM_FUNCTION_PROLOGUE
+# define TARGET_ASM_FUNCTION_PROLOGUE ix86_osf_output_function_prologue
+#endif
+
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Sometimes certain combinations of command options do not make
return 0;
}
+#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
+
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used.
+
+ We override it here to allow for the new profiling code to go before
+ the prologue and the old mcount code to go after the prologue (and
+ after %ebx has been set up for ELF shared library support). */
+
+static void
+ix86_osf_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ char *prefix = "";
+ char *lprefix = LPREFIX;
+ int labelno = profile_label_no;
+
+#ifdef OSF_OS
+
+ if (TARGET_UNDERSCORES)
+ prefix = "_";
+
+ if (profile_flag && OSF_PROFILE_BEFORE_PROLOGUE)
+ {
+ if (!flag_pic && !HALF_PIC_P ())
+ {
+ fprintf (file, "\tmovl $%sP%d,%%edx\n", lprefix, labelno);
+ fprintf (file, "\tcall *%s_mcount_ptr\n", prefix);
+ }
+
+ else if (HALF_PIC_P ())
+ {
+ rtx symref;
+
+ HALF_PIC_EXTERNAL ("_mcount_ptr");
+ symref = HALF_PIC_PTR (gen_rtx_SYMBOL_REF (Pmode,
+ "_mcount_ptr"));
+
+ fprintf (file, "\tmovl $%sP%d,%%edx\n", lprefix, labelno);
+ fprintf (file, "\tmovl %s%s,%%eax\n", prefix,
+ XSTR (symref, 0));
+ fprintf (file, "\tcall *(%%eax)\n");
+ }
+
+ else
+ {
+ static int call_no = 0;
+
+ fprintf (file, "\tcall %sPc%d\n", lprefix, call_no);
+ fprintf (file, "%sPc%d:\tpopl %%eax\n", lprefix, call_no);
+ fprintf (file, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n",
+ lprefix, call_no++);
+ fprintf (file, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n",
+ lprefix, labelno);
+ fprintf (file, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n",
+ prefix);
+ fprintf (file, "\tcall *(%%eax)\n");
+ }
+ }
+
+#else /* !OSF_OS */
+
+ if (profile_flag && OSF_PROFILE_BEFORE_PROLOGUE)
+ {
+ if (!flag_pic)
+ {
+ fprintf (file, "\tmovl $%sP%d,%%edx\n", lprefix, labelno);
+ fprintf (file, "\tcall *%s_mcount_ptr\n", prefix);
+ }
+
+ else
+ {
+ static int call_no = 0;
+
+ fprintf (file, "\tcall %sPc%d\n", lprefix, call_no);
+ fprintf (file, "%sPc%d:\tpopl %%eax\n", lprefix, call_no);
+ fprintf (file, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n",
+ lprefix, call_no++);
+ fprintf (file, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n",
+ lprefix, labelno);
+ fprintf (file, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n",
+ prefix);
+ fprintf (file, "\tcall *(%%eax)\n");
+ }
+ }
+#endif /* !OSF_OS */
+
+ function_prologue (file, size);
+}
+
+#endif /* OSF_OS || TARGET_OSF1ELF */
+
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 OSF/1)");
+#define TARGET_OSF1ELF
+
/* WORD_SWITCH_TAKES_ARG defined in svr4 is not correct. We also
need an extra -soname */
#undef WORD_SWITCH_TAKES_ARG
#else
#define OSF_PROFILE_BEFORE_PROLOGUE 0
#endif
-#undef FUNCTION_PROLOGUE
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-do \
- { \
- char *prefix = ""; \
- char *lprefix = LPREFIX; \
- int labelno = profile_label_no; \
- \
- if (profile_flag && OSF_PROFILE_BEFORE_PROLOGUE) \
- { \
- if (!flag_pic) \
- { \
- fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \
- fprintf (FILE, "\tcall *%s_mcount_ptr\n", prefix); \
- } \
- \
- else \
- { \
- static int call_no = 0; \
- \
- fprintf (FILE, "\tcall %sPc%d\n", lprefix, call_no); \
- fprintf (FILE, "%sPc%d:\tpopl %%eax\n", lprefix, call_no); \
- fprintf (FILE, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n", \
- lprefix, call_no++); \
- fprintf (FILE, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n", \
- lprefix, labelno); \
- fprintf (FILE, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n", \
- prefix); \
- fprintf (FILE, "\tcall *(%%eax)\n"); \
- } \
- } \
- \
- function_prologue (FILE, SIZE); \
- } \
-while (0)
/* A C statement or compound statement to output to FILE some assembler code to
call the profiling subroutine `mcount'. Before calling, the assembler code
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 64
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used.
-
- We override it here to allow for the new profiling code to go before
- the prologue and the old mcount code to go after the prologue (and
- after %ebx has been set up for ELF shared library support). */
-
#define OSF_PROFILE_BEFORE_PROLOGUE \
(!TARGET_MCOUNT \
&& !current_function_needs_context \
|| (!current_function_uses_pic_offset_table \
&& !current_function_uses_const_pool)))
-#undef FUNCTION_PROLOGUE
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-do \
- { \
- char *prefix = (TARGET_UNDERSCORES) ? "_" : ""; \
- char *lprefix = LPREFIX; \
- int labelno = profile_label_no; \
- \
- if (profile_flag && OSF_PROFILE_BEFORE_PROLOGUE) \
- { \
- if (!flag_pic && !HALF_PIC_P ()) \
- { \
- fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \
- fprintf (FILE, "\tcall *%s_mcount_ptr\n", prefix); \
- } \
- \
- else if (HALF_PIC_P ()) \
- { \
- rtx symref; \
- \
- HALF_PIC_EXTERNAL ("_mcount_ptr"); \
- symref = HALF_PIC_PTR (gen_rtx_SYMBOL_REF (Pmode, \
- "_mcount_ptr")); \
- \
- fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \
- fprintf (FILE, "\tmovl %s%s,%%eax\n", prefix, \
- XSTR (symref, 0)); \
- fprintf (FILE, "\tcall *(%%eax)\n"); \
- } \
- \
- else \
- { \
- static int call_no = 0; \
- \
- fprintf (FILE, "\tcall %sPc%d\n", lprefix, call_no); \
- fprintf (FILE, "%sPc%d:\tpopl %%eax\n", lprefix, call_no); \
- fprintf (FILE, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n", \
- lprefix, call_no++); \
- fprintf (FILE, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n", \
- lprefix, labelno); \
- fprintf (FILE, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n", \
- prefix); \
- fprintf (FILE, "\tcall *(%%eax)\n"); \
- } \
- } \
- \
- function_prologue (FILE, SIZE); \
- } \
-while (0)
-
/* A C statement or compound statement to output to FILE some assembler code to
call the profiling subroutine `mcount'. Before calling, the assembler code
must load the address of a counter variable into a register where `mcount'
#ifdef TREE_CODE
extern tree i860_build_va_list PARAMS ((void));
#endif /* TREE_CODE */
-
-extern void function_prologue PARAMS ((FILE *, unsigned));
-extern void function_epilogue PARAMS ((FILE *, unsigned));
static const char *load_opcode PARAMS ((enum machine_mode, const char *, rtx));
static const char *store_opcode PARAMS ((enum machine_mode, const char *, rtx));
static void output_size_for_block_move PARAMS ((rtx, rtx, rtx));
+static void i860_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void i860_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
#ifndef I860_REG_PREFIX
#define I860_REG_PREFIX ""
rtx i860_compare_op0, i860_compare_op1;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE i860_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE i860_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
}
\f
/* This function generates the assembly code for function entry.
- The macro FUNCTION_PROLOGUE in i860.h is defined to call this function.
ASM_FILE is a stdio stream to output the code to.
SIZE is an int: how many units of temporary storage to allocate.
static int must_preserve_r1;
static unsigned must_preserve_bytes;
-void
-function_prologue (asm_file, local_bytes)
+static void
+i860_output_function_prologue (asm_file, local_bytes)
register FILE *asm_file;
- register unsigned local_bytes;
+ register HOST_WIDE_INT local_bytes;
{
- register unsigned frame_lower_bytes;
- register unsigned frame_upper_bytes;
- register unsigned total_fsize;
+ register HOST_WIDE_INT frame_lower_bytes;
+ register HOST_WIDE_INT frame_upper_bytes;
+ register HOST_WIDE_INT total_fsize;
register unsigned preserved_reg_bytes = 0;
register unsigned i;
register unsigned preserved_so_far = 0;
}
\f
/* This function generates the assembly code for function exit.
- The macro FUNCTION_EPILOGUE in i860.h is defined to call this function.
ASM_FILE is a stdio stream to output the code to.
SIZE is an int: how many units of temporary storage to allocate.
unsigned int negative_frame_size; /* same as frame_lower_bytes */
} TDESC;
-void
-function_epilogue (asm_file, local_bytes)
+static void
+i860_output_function_epilogue (asm_file, local_bytes)
register FILE *asm_file;
- register unsigned local_bytes;
+ register HOST_WIDE_INT local_bytes;
{
- register unsigned frame_upper_bytes;
- register unsigned frame_lower_bytes;
- register unsigned preserved_reg_bytes = 0;
+ register HOST_WIDE_INT frame_upper_bytes;
+ register HOST_WIDE_INT frame_lower_bytes;
+ register HOST_WIDE_INT preserved_reg_bytes = 0;
register unsigned i;
register unsigned restored_so_far = 0;
register unsigned int_restored;
? PARM_BOUNDARY \
: GET_MODE_ALIGNMENT(MODE)))
-/* This macro generates the assembly code for function entry.
-
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
-*/
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue ((FILE), (SIZE))
-
/* Output a no-op just before the beginning of the function,
to ensure that there does not appear to be a delayed branch there.
Such a thing would confuse interrupt recovery. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit.
-
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning.
-*/
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue ((FILE), (SIZE))
-
/* Generate necessary RTL for __builtin_saveregs(). */
#define EXPAND_BUILTIN_SAVEREGS() \
i860_saveregs()
extern int is_mask PARAMS ((unsigned int));
extern int bitstr PARAMS ((unsigned int, int *, int *));
extern int compute_frame_size PARAMS ((int));
-extern void i960_function_prologue PARAMS ((FILE *, unsigned int));
extern void output_function_profiler PARAMS ((FILE *, int));
-extern void i960_function_epilogue PARAMS ((FILE *, unsigned int));
extern void i960_scan_opcode PARAMS ((const char *));
#ifdef GCC_C_PRAGMA_H
#include "target.h"
#include "target-def.h"
+static void i960_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void i960_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
|| current_function_varargs)
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE i960_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE i960_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Output code for the function prologue. */
-void
-i960_function_prologue (file, size)
+static void
+i960_output_function_prologue (file, size)
FILE *file;
- unsigned int size;
+ HOST_WIDE_INT size;
{
register int i, j, nr;
int n_saved_regs = 0;
int n_remaining_saved_regs;
- int lvar_size;
- int actual_fsize, offset;
+ HOST_WIDE_INT lvar_size;
+ HOST_WIDE_INT actual_fsize, offset;
int gnw, lnw;
struct reg_group *g, *l;
char tmpstr[1000];
/* Output code for the function epilogue. */
-void
-i960_function_epilogue (file, size)
+static void
+i960_output_function_epilogue (file, size)
FILE *file;
- unsigned int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
if (i960_leaf_ret_reg >= 0)
{
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
i960_function_name_declare (FILE, NAME, DECL)
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) i960_function_prologue ((FILE), (SIZE))
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
No definition is equivalent to always zero. */
#define EXIT_IGNORE_STACK 1
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) i960_function_epilogue (FILE, SIZE)
\f
/* Addressing modes, and classification of registers for them. */
extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int));
extern void ia64_expand_prologue PARAMS((void));
extern void ia64_expand_epilogue PARAMS((int));
-extern void ia64_function_prologue PARAMS((FILE *, int));
-extern void ia64_function_epilogue PARAMS((FILE *, int));
extern int ia64_direct_return PARAMS((void));
extern void ia64_expand_load_address PARAMS((rtx, rtx, rtx));
tree, rtx));
static rtx ia64_expand_lock_release PARAMS ((enum machine_mode, tree, rtx));
static int ia64_valid_type_attribute PARAMS((tree, tree, tree, tree));
+static void ia64_function_prologue PARAMS((FILE *, HOST_WIDE_INT));
+static void ia64_function_epilogue PARAMS((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE ia64_valid_type_attribute
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE ia64_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE ia64_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
/* Called after register allocation to add any instructions needed for the
prologue. Using a prologue insn is favored compared to putting all of the
- instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+ instructions in output_function_prologue(), since it allows the scheduler
to intermix instructions with the saves of the caller saved registers. In
some cases, it might be necessary to emit a barrier instruction as the last
insn to prevent such scheduling.
/* Called after register allocation to add any instructions needed for the
epilogue. Using a epilogue insn is favored compared to putting all of the
- instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+ instructions in output_function_prologue(), since it allows the scheduler
to intermix instructions with the saves of the caller saved registers. In
some cases, it might be necessary to emit a barrier instruction as the last
insn to prevent such scheduling. */
/* Emit the function prologue. */
-void
-ia64_function_prologue (file, size)
+static void
+ia64_output_function_prologue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
int mask, grsave, grsave_prev;
/* Emit the function epilogue. */
-void
-ia64_function_epilogue (file, size)
+static void
+ia64_output_function_epilogue (file, size)
FILE *file ATTRIBUTE_UNUSED;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
int i;
\f
/* Function Entry and Exit */
-/* A C compound statement that outputs the assembler code for entry to a
- function. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- ia64_function_prologue (FILE, SIZE)
-
/* This macro notes the end of the prologue. */
#define FUNCTION_END_PROLOGUE(FILE) ia64_output_end_prologue (FILE)
#define EPILOGUE_USES(REGNO) ia64_epilogue_uses (REGNO)
-/* A C compound statement that outputs the assembler code for exit from a
- function. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
- ia64_function_epilogue (FILE, SIZE)
-
/* Output at beginning of assembler file. */
#define ASM_FILE_START(FILE) \
extern unsigned m32r_compute_frame_size PARAMS ((int));
extern int m32r_first_insn_address PARAMS ((void));
extern void m32r_expand_prologue PARAMS ((void));
-extern void m32r_output_function_prologue PARAMS ((FILE *, int));
-extern void m32r_output_function_epilogue PARAMS ((FILE *, int));
extern void m32r_finalize_pic PARAMS ((void));
extern void m32r_asm_file_start PARAMS ((FILE *));
extern void m32r_sched_init PARAMS ((FILE *, int));
static int m32r_is_insn PARAMS ((rtx));
static int m32r_valid_decl_attribute PARAMS ((tree, tree,
tree, tree));
+static void m32r_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void m32r_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE m32r_valid_decl_attribute
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE m32r_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Called by OVERRIDE_OPTIONS to initialize various things. */
Note, if this is changed, you need to mirror the changes in
m32r_compute_frame_size which calculates the prolog size. */
-void
+static void
m32r_output_function_prologue (file, size)
FILE * file;
- int size;
+ HOST_WIDE_INT size;
{
enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
/* Do any necessary cleanup after a function to restore stack, frame,
and regs. */
-void
+static void
m32r_output_function_epilogue (file, size)
FILE * file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
int regno;
int noepilogue = FALSE;
init_emit, once for each function, before code is generated. */
#define INIT_EXPANDERS m32r_init_expanders ()
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-m32r_output_function_prologue (FILE, SIZE)
-
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
functions that have frame pointers.
No definition is equivalent to always zero. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-m32r_output_function_epilogue (FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define FUNCTION_PROFILER(FILE, LABELNO) abort ()
extern void expand_prologue PARAMS((void));
extern void expand_epilogue PARAMS((void));
-extern void output_function_prologue PARAMS((FILE*, int));
-extern void output_function_epilogue PARAMS((FILE*, int));
extern int m68hc11_function_block_profiler PARAMS((FILE*,int));
extern int m68hc11_block_profiler PARAMS((FILE*,int));
tree, tree));
void create_regs_rtx PARAMS ((void));
+static void m68hc11_add_gc_roots PARAMS ((void));
static void asm_print_register PARAMS ((FILE *, int));
+static void m68hc11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
rtx m68hc11_soft_tmp_reg;
const char *m68hc11_reg_alloc_order;
const char *m68hc11_soft_reg_count;
-static void m68hc11_add_gc_roots PARAMS ((void));
-
static int nb_soft_regs;
\f
/* Initialize the GCC target structure. */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE m68hc11_valid_type_attribute_p
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
int
return size;
}
-void
-m68hc11_function_epilogue (out, size)
+static void
+m68hc11_output_function_epilogue (out, size)
FILE *out ATTRIBUTE_UNUSED;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
/* We catch the function epilogue generation to have a chance
to clear the z_replacement_completed flag. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
m68hc11_va_arg (valist, type)
-#define FUNCTION_EPILOGUE(FILE, SIZE) m68hc11_function_epilogue(FILE, SIZE)
-
/* For an arg passed partly in registers and partly in memory,
this is the number of registers used.
For args passed entirely in registers or entirely in memory, zero.
(sdb_begin_function_line \
? last_linenum - sdb_begin_function_line : 1))
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-/* Note that the order of the bit mask for fmovem is the opposite
- of the order for movem! */
-
-#undef FUNCTION_PROLOGUE
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno; \
- register int mask = 0; \
- extern char call_used_regs[]; \
- int fsize = ((SIZE) + 3) & -4; \
- /* unos stack probe */ \
- if ( fsize > 30000 ) { \
- fprintf (FILE, "\tmovel sp,a0\n"); \
- fprintf (FILE, "\taddl $-%d,a0\n", 2048 + fsize); \
- fprintf (FILE, "\ttstb (a0)\n"); \
- } else { \
- fprintf (FILE, "\ttstb -%d(sp)\n", 2048 + fsize); \
- } \
- if (frame_pointer_needed) \
- { if (TARGET_68020 || fsize < 0x8000) \
- fprintf (FILE, "\tlink a6,$%d\n", -fsize); \
- else \
- fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize); } \
- else if (fsize) \
- { \
- /* Adding negative number is faster on the 68040. */ \
- if (fsize + 4 < 0x8000) \
- { \
- fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
- } \
- else \
- { \
- fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
- } \
- } \
- for (regno = 16; regno < 24; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- mask |= 1 << (regno - 16); \
- if ((mask & 0xff) != 0) \
- fprintf (FILE, "\tfmovem $0x%x,-(sp)\n", mask & 0xff); \
- mask = 0; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- mask |= 1 << (15 - regno); \
- if (frame_pointer_needed) \
- mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
- if (exact_log2 (mask) >= 0) \
- fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
- else if (mask) fprintf (FILE, "\tmovem $0x%x,-(sp)\n", mask); }
-
/* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
/* UNOS ?? */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABEL_NO) \
fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#undef FUNCTION_EPILOGUE
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int regno; \
- register int mask, fmask; \
- register int nregs; \
- int offset, foffset, fpoffset; \
- extern char call_used_regs[]; \
- int fsize = ((SIZE) + 3) & -4; \
- int big = 0; \
- nregs = 0; fmask = 0; fpoffset = 0; \
- for (regno = 16; regno < 24; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { nregs++; fmask |= 1 << (23 - regno); } \
- foffset = fpoffset + nregs * 12; \
- nregs = 0; mask = 0; \
- if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { nregs++; mask |= 1 << regno; } \
- offset = foffset + nregs * 4; \
- if (offset + fsize >= 0x8000 \
- && frame_pointer_needed \
- && (mask || fmask || fpoffset)) \
- { fprintf (FILE, "\tmovel $%d,a0\n", -fsize); \
- fsize = 0, big = 1; } \
- if (exact_log2 (mask) >= 0) { \
- if (big) \
- fprintf (FILE, "\tmovel -%d(a6,a0.l),%s\n", \
- offset + fsize, reg_names[exact_log2 (mask)]); \
- else if (! frame_pointer_needed) \
- fprintf (FILE, "\tmovel (sp)+,%s\n", \
- reg_names[exact_log2 (mask)]); \
- else \
- fprintf (FILE, "\tmovel -%d(a6),%s\n", \
- offset + fsize, reg_names[exact_log2 (mask)]); } \
- else if (mask) { \
- if (big) \
- fprintf (FILE, "\tmovem -%d(a6,a0.l),$0x%x\n", \
- offset + fsize, mask); \
- else if (! frame_pointer_needed) \
- fprintf (FILE, "\tmovem (sp)+,$0x%x\n", mask); \
- else \
- fprintf (FILE, "\tmovem -%d(a6),$0x%x\n", \
- offset + fsize, mask); } \
- if (fmask) { \
- if (big) \
- fprintf (FILE, "\tfmovem -%d(a6,a0.l),$0x%x\n", \
- foffset + fsize, fmask); \
- else if (! frame_pointer_needed) \
- fprintf (FILE, "\tfmovem (sp)+,$0x%x\n", fmask); \
- else \
- fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n", \
- foffset + fsize, fmask); } \
- if (fpoffset != 0) \
- for (regno = 55; regno >= 24; regno--) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) { \
- if (big) \
- fprintf(FILE, "\tfpmoved -%d(a6,a0.l), %s\n", \
- fpoffset + fsize, reg_names[regno]); \
- else if (! frame_pointer_needed) \
- fprintf(FILE, "\tfpmoved (sp)+, %s\n", \
- reg_names[regno]); \
- else \
- fprintf(FILE, "\tfpmoved -%d(a6), %s\n", \
- fpoffset + fsize, reg_names[regno]); \
- fpoffset -= 8; \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tunlk a6\n"); \
- else if (fsize) \
- { \
- if (fsize + 4 < 0x8000) \
- { \
- fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
- } \
- else \
- { \
- fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
- } \
- } \
- if (current_function_pops_args) \
- fprintf (FILE, "\trtd $%d\n", current_function_pops_args); \
- else fprintf (FILE, "\trts\n"); }
-
#undef SELECT_RTX_SECTION
#include "svr3.h"
+#define DPX2
+
/* See m68k.h. 7 means 68020 with 68881.
* We really have 68030 and 68882,
* but this will get us going.
/* Output type in decimal not in octal as done in sdbout.c */
#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%d%s", a, SDB_DELIM)
-#undef FUNCTION_PROLOGUE
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ \
- register int regno; \
- register int mask = 0; \
- int num_saved_regs = 0, first = 1; \
- extern char call_used_regs[]; \
- int fsize = ((SIZE) + 3) & -4; \
- \
- \
- if (frame_pointer_needed) \
- { \
- /* Adding negative number is faster on the 68040. */ \
- if (fsize < 0x8000 && !TARGET_68040) \
- { \
- fprintf (FILE, "\tlink %s,#%d\n", \
- reg_names[FRAME_POINTER_REGNUM], -fsize); \
- } \
- else if (TARGET_68020) \
- { \
- fprintf (FILE, "\tlink %s,#%d\n", \
- reg_names[FRAME_POINTER_REGNUM], -fsize); \
- } \
- else \
- { \
- fprintf (FILE, "\tlink %s,#0\n\tadd.l #%d,sp\n", \
- reg_names[FRAME_POINTER_REGNUM], -fsize); \
- } \
- } \
- else if (fsize) \
- { \
- /* Adding negative number is faster on the 68040. */ \
- if (fsize + 4 < 0x8000) \
- { \
- fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
- } \
- else \
- { \
- fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
- } \
- } \
- for (regno = 23; regno >= 16; regno--) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- if (first) { \
- fprintf (FILE, "\tfmovem.x %s", reg_names[regno]); \
- first = 0; \
- } \
- else fprintf (FILE, "/%s", reg_names[regno]); \
- if (!first) fprintf (FILE, ",-(sp)\n"); \
- \
- mask = 0; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { \
- mask |= 1 << (15 - regno); \
- num_saved_regs++; \
- } \
- if (frame_pointer_needed) \
- { \
- mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM)); \
- num_saved_regs--; \
- } \
- \
- \
- if (num_saved_regs <= 2) \
- { \
- /* Store each separately in the same order moveml uses. \
- Using two movel instructions instead of a single moveml \
- is about 15% faster for the 68020 and 68030 at no expense \
- in code size */ \
- \
- int i; \
- \
- /* Undo the work from above. */ \
- for (i = 0; i< 16; i++) \
- if (mask & (1 << i)) \
- fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - i]); \
- } \
- else if (mask) \
- { \
- first = 1; \
- for (regno = 0; regno < 16; regno++) \
- if (mask & (1 << regno)) \
- if (first) { \
- fprintf (FILE, "\tmovem.l %s", reg_names[15 - regno]); \
- first = 0; \
- } \
- else fprintf (FILE, "/%s", reg_names[15 - regno]); \
- fprintf (FILE, ",-(sp)\n"); \
- } \
- if (flag_pic && current_function_uses_pic_offset_table) \
- { \
- fprintf (FILE, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n", \
- reg_names[PIC_OFFSET_TABLE_REGNUM]); \
- fprintf (FILE, "\tlea.l (pc,%s.l),%s\n", \
- reg_names[PIC_OFFSET_TABLE_REGNUM], \
- reg_names[PIC_OFFSET_TABLE_REGNUM]); \
- } \
-}
-
-
-#undef FUNCTION_EPILOGUE
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ \
- register int regno; \
- register int mask, fmask; \
- register int nregs; \
- int offset, foffset, fpoffset, first = 1; \
- extern char call_used_regs[]; \
- int fsize = ((SIZE) + 3) & -4; \
- int big = 0; \
- rtx insn = get_last_insn (); \
- \
- /* If the last insn was a BARRIER, we don't have to write any code. */ \
- if (GET_CODE (insn) == NOTE) \
- insn = prev_nonnote_insn (insn); \
- if (insn && GET_CODE (insn) == BARRIER) \
- { \
- /* Output just a no-op so that debuggers don't get confused \
- about which function the pc is in at this address. */ \
- fprintf (FILE, "\tnop\n"); \
- return; \
- } \
- \
- nregs = 0; fmask = 0; fpoffset = 0; \
- for (regno = 16; regno < 24; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { \
- nregs++; \
- fmask |= 1 << (23 - regno); \
- } \
- foffset = fpoffset + nregs * 12; \
- nregs = 0; mask = 0; \
- if (frame_pointer_needed) \
- regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { \
- nregs++; \
- mask |= 1 << regno; \
- } \
- offset = foffset + nregs * 4; \
- if (offset + fsize >= 0x8000 \
- && frame_pointer_needed \
- && (mask || fmask || fpoffset)) \
- { \
- fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
- fsize = 0, big = 1; \
- } \
- if (nregs <= 2) \
- { \
- /* Restore each separately in the same order moveml does. \
- Using two movel instructions instead of a single moveml \
- is about 15% faster for the 68020 and 68030 at no expense \
- in code size. */ \
- \
- int i; \
- \
- /* Undo the work from above. */ \
- for (i = 0; i< 16; i++) \
- if (mask & (1 << i)) \
- { \
- if (big) \
- { \
- fprintf (FILE, "\tmove.l -%d(%s,a0.l),%s\n", \
- offset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[i]); \
- } \
- else if (! frame_pointer_needed) \
- { \
- fprintf (FILE, "\tmove.l (sp)+,%s\n", \
- reg_names[i]); \
- } \
- else \
- { \
- fprintf (FILE, "\tmove.l -%d(%s),%s\n", \
- offset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[i]); \
- } \
- offset = offset - 4; \
- } \
- } \
- else if (mask) \
- { \
- first = 1; \
- for (regno = 0; regno < 16; regno++) \
- if (mask & (1 << regno)) \
- if (first && big) { \
- fprintf (FILE, "\tmovem.l -%d(%s,a0.l),%s", \
- offset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[regno]); \
- first = 0; \
- } \
- else if (first && ! frame_pointer_needed) { \
- fprintf (FILE, "\tmovem.l (sp)+,%s", \
- offset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[regno]); \
- first = 0; \
- } \
- else if (first) { \
- fprintf (FILE, "\tmovem.l -%d(%s),%s", \
- offset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[regno]); \
- first = 0; \
- } \
- else \
- fprintf (FILE, "/%s", reg_names[regno]); \
- fprintf (FILE, "\n"); \
- } \
- if (fmask) \
- { \
- first = 1; \
- for (regno = 16; regno < 24; regno++) \
- if (fmask & (1 << (23 - regno))) \
- if (first && big) { \
- fprintf (FILE, "\tfmovem.x -%d(%s,a0.l),%s", \
- foffset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[regno]); \
- first = 0; \
- } \
- else if (first && ! frame_pointer_needed) { \
- fprintf (FILE, "\tfmovem.x (sp)+,%s", \
- foffset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[regno]); \
- first = 0; \
- } \
- else if (first) { \
- fprintf (FILE, "\tfmovem.x -%d(%s),%s", \
- foffset + fsize, \
- reg_names[FRAME_POINTER_REGNUM], \
- reg_names[regno]); \
- first = 0; \
- } \
- else fprintf (FILE, "/%s", reg_names[regno]); \
- fprintf (FILE, "\n"); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tunlk %s\n", \
- reg_names[FRAME_POINTER_REGNUM]); \
- else if (fsize) \
- { \
- if (fsize + 4 < 0x8000) \
- { \
- fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
- } \
- else \
- { \
- fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
- } \
- } \
- if (current_function_pops_args) \
- fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
- else \
- fprintf (FILE, "\trts\n"); \
-}
-
/* Translate Motorola opcodes such as `jbeq'
into VERSAdos opcodes such as `beq'.
Change `fbeq' to `fbseq', `fbne' to `fbsneq'.
#endif /* RTX_CODE */
extern int flags_in_68881 PARAMS ((void));
-extern void output_function_prologue PARAMS ((FILE *, int));
-extern void output_function_epilogue PARAMS ((FILE *, int));
extern int use_return_insn PARAMS ((void));
extern void override_options PARAMS ((void));
extern void init_68881_table PARAMS ((void));
static rtx find_addr_reg PARAMS ((rtx));
static const char *singlemove_string PARAMS ((rtx *));
+static void m68k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void m68k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Alignment to use for loops and jumps */
int m68k_last_compare_had_fp_operands;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Note that the order of the bit mask for fmovem is the opposite
of the order for movem! */
+#ifdef CRDS
-void
-output_function_prologue (stream, size)
+static void
+m68k_output_function_prologue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask = 0;
+ extern char call_used_regs[];
+ HOST_WIDE_INT fsize = ((size) + 3) & -4;
+
+ /* unos stack probe */
+ if (fsize > 30000)
+ {
+ fprintf (stream, "\tmovel sp,a0\n");
+ fprintf (stream, "\taddl $-%d,a0\n", 2048 + fsize);
+ fprintf (stream, "\ttstb (a0)\n");
+ }
+ else
+ fprintf (stream, "\ttstb -%d(sp)\n", 2048 + fsize);
+
+ if (frame_pointer_needed)
+ {
+ if (TARGET_68020 || fsize < 0x8000)
+ fprintf (stream, "\tlink a6,$%d\n", -fsize);
+ else
+ fprintf (stream, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize);
+ }
+ else if (fsize)
+ {
+ /* Adding negative number is faster on the 68040. */
+ if (fsize + 4 < 0x8000)
+ fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
+ else
+ fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
+ }
+
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ mask |= 1 << (regno - 16);
+
+ if ((mask & 0xff) != 0)
+ fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);
+
+ mask = 0;
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ mask |= 1 << (15 - regno);
+ if (frame_pointer_needed)
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
+
+ if (exact_log2 (mask) >= 0)
+ fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
+ else if (mask)
+ fprintf (stream, "\tmovem $0x%x,-(sp)\n", mask);
+}
+
+#else
+#if defined (DPX2) && defined (MOTOROLA)
+
+static void
+m68k_output_function_prologue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask = 0;
+ int num_saved_regs = 0, first = 1;
+ extern char call_used_regs[];
+ HOST_WIDE_INT fsize = ((size) + 3) & -4;
+
+ if (frame_pointer_needed)
+ {
+ /* Adding negative number is faster on the 68040. */
+ if (fsize < 0x8000 && !TARGET_68040)
+ fprintf (stream, "\tlink %s,#%d\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+ else if (TARGET_68020)
+ fprintf (stream, "\tlink %s,#%d\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+ else
+ fprintf (stream, "\tlink %s,#0\n\tadd.l #%d,sp\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+ }
+ else if (fsize)
+ {
+ /* Adding negative number is faster on the 68040. */
+ if (fsize + 4 < 0x8000)
+ fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
+ else
+ fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
+ }
+
+ for (regno = 23; regno >= 16; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ if (first)
+ {
+ fprintf (stream, "\tfmovem.x %s", reg_names[regno]);
+ first = 0;
+ }
+ else
+ fprintf (stream, "/%s", reg_names[regno]);
+ }
+ if (!first)
+ fprintf (stream, ",-(sp)\n");
+
+ mask = 0;
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ mask |= 1 << (15 - regno);
+ num_saved_regs++;
+ }
+
+ if (frame_pointer_needed)
+ {
+ mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
+ num_saved_regs--;
+ }
+
+ if (num_saved_regs <= 2)
+ {
+ /* Store each separately in the same order moveml uses.
+ Using two movel instructions instead of a single moveml
+ is about 15% faster for the 68020 and 68030 at no expense
+ in code size */
+
+ int i;
+
+ /* Undo the work from above. */
+ for (i = 0; i< 16; i++)
+ if (mask & (1 << i))
+ fprintf (stream, "\tmove.l %s,-(sp)\n", reg_names[15 - i]);
+ }
+ else if (mask)
+ {
+ first = 1;
+ for (regno = 0; regno < 16; regno++)
+ if (mask & (1 << regno))
+ {
+ if (first)
+ {
+ fprintf (stream, "\tmovem.l %s", reg_names[15 - regno]);
+ first = 0;
+ }
+ else
+ fprintf (stream, "/%s", reg_names[15 - regno]);
+ }
+ fprintf (stream, ",-(sp)\n");
+ }
+
+ if (flag_pic && current_function_uses_pic_offset_table)
+ {
+ fprintf (stream, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+ fprintf (stream, "\tlea.l (pc,%s.l),%s\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM],
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+ }
+}
+
+#else
+#if defined (NEWS) && defined (MOTOROLA)
+
+static void
+m68k_output_function_prologue (stream, size)
FILE *stream;
- int size;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask = 0;
+ extern char call_used_regs[];
+ HOST_WIDE_INT fsize = ((size) + 3) & -4;
+
+ if (frame_pointer_needed)
+ {
+ if (fsize < 0x8000)
+ fprintf (stream, "\tlink fp,#%d\n", -fsize);
+ else if (TARGET_68020)
+ fprintf (stream, "\tlink.l fp,#%d\n", -fsize);
+ else
+ fprintf (stream, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);
+ }
+ else if (fsize)
+ {
+ int amt = fsize + 4;
+ /* Adding negative number is faster on the 68040. */
+ if (fsize + 4 < 0x8000)
+ asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - amt);
+ else
+ asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - amt);
+ }
+
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ mask |= 1 << (regno - 16);
+
+ if (mask != 0)
+ fprintf (stream, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff);
+
+ mask = 0;
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ mask |= 1 << (15 - regno);
+
+ if (frame_pointer_needed)
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
+
+ if (exact_log2 (mask) >= 0)
+ fprintf (stream, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
+ else
+ if (mask) fprintf (stream, "\tmovem.l #0x%x,-(sp)\n", mask);
+}
+
+#else /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
+
+static void
+m68k_output_function_prologue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
{
register int regno;
register int mask = 0;
int num_saved_regs = 0;
extern char call_used_regs[];
- int fsize = (size + 3) & -4;
- int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
+ HOST_WIDE_INT fsize = (size + 3) & -4;
+ HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
+ HOST_WIDE_INT cfa_store_offset = cfa_offset;
/* If the stack limit is a symbol, we can check it here,
before actually allocating the space. */
#if NEED_PROBE
#ifdef MOTOROLA
-#ifdef CRDS
- asm_fprintf (stream, "\ttstl %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
-#else
asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
-#endif
#else
asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
#endif
#endif
}
}
+#endif /* ! (DPX2 && MOTOROLA) */
+#endif /* ! (NEWS && MOTOROLA) */
+#endif /* !CRDS */
\f
/* Return true if this function's epilogue can be output as RTL. */
}
/* This function generates the assembly code for function exit,
- on machines that need it. Args are same as for FUNCTION_PROLOGUE.
+ on machines that need it.
The function epilogue should not depend on the current stack pointer!
It should use the frame pointer only, if there is a frame pointer.
This is mandatory because of alloca; we also take advantage of it to
omit stack adjustments before returning. */
-void
-output_function_epilogue (stream, size)
+#ifdef CRDS
+
+static void
+m68k_output_function_epilogue (stream, size)
FILE *stream;
- int size;
+ HOST_WIDE_INT size;
{
register int regno;
register int mask, fmask;
register int nregs;
- int offset, foffset, fpoffset;
+ HOST_WIDE_INT offset, foffset, fpoffset;
extern char call_used_regs[];
- int fsize = (size + 3) & -4;
+ HOST_WIDE_INT fsize = ((size) + 3) & -4;
+ int big = 0;
+
+ nregs = 0; fmask = 0; fpoffset = 0;
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ fmask |= 1 << (23 - regno);
+ }
+
+ foffset = fpoffset + nregs * 12;
+ nregs = 0; mask = 0;
+ if (frame_pointer_needed)
+ regs_ever_live[FRAME_POINTER_REGNUM] = 0;
+
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ mask |= 1 << regno;
+ }
+
+ offset = foffset + nregs * 4;
+ if (offset + fsize >= 0x8000
+ && frame_pointer_needed
+ && (mask || fmask || fpoffset))
+ {
+ fprintf (stream, "\tmovel $%d,a0\n", -fsize);
+ fsize = 0, big = 1;
+ }
+
+ if (exact_log2 (mask) >= 0)
+ {
+ if (big)
+ fprintf (stream, "\tmovel -%d(a6,a0.l),%s\n",
+ offset + fsize, reg_names[exact_log2 (mask)]);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tmovel (sp)+,%s\n",
+ reg_names[exact_log2 (mask)]);
+ else
+ fprintf (stream, "\tmovel -%d(a6),%s\n",
+ offset + fsize, reg_names[exact_log2 (mask)]);
+ }
+ else if (mask)
+ {
+ if (big)
+ fprintf (stream, "\tmovem -%d(a6,a0.l),$0x%x\n",
+ offset + fsize, mask);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tmovem (sp)+,$0x%x\n", mask);
+ else
+ fprintf (stream, "\tmovem -%d(a6),$0x%x\n",
+ offset + fsize, mask);
+ }
+
+ if (fmask)
+ {
+ if (big)
+ fprintf (stream, "\tfmovem -%d(a6,a0.l),$0x%x\n",
+ foffset + fsize, fmask);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tfmovem (sp)+,$0x%x\n", fmask);
+ else
+ fprintf (stream, "\tfmovem -%d(a6),$0x%x\n",
+ foffset + fsize, fmask);
+ }
+
+ if (fpoffset != 0)
+ for (regno = 55; regno >= 24; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ if (big)
+ fprintf(stream, "\tfpmoved -%d(a6,a0.l), %s\n",
+ fpoffset + fsize, reg_names[regno]);
+ else if (! frame_pointer_needed)
+ fprintf(stream, "\tfpmoved (sp)+, %s\n",
+ reg_names[regno]);
+ else
+ fprintf(stream, "\tfpmoved -%d(a6), %s\n",
+ fpoffset + fsize, reg_names[regno]);
+ fpoffset -= 8;
+ }
+
+ if (frame_pointer_needed)
+ fprintf (stream, "\tunlk a6\n");
+ else if (fsize)
+ {
+ if (fsize + 4 < 0x8000)
+ fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
+ else
+ fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
+ }
+
+ if (current_function_pops_args)
+ fprintf (stream, "\trtd $%d\n", current_function_pops_args);
+ else
+ fprintf (stream, "\trts\n");
+}
+
+#else
+#if defined (DPX2) && defined (MOTOROLA)
+
+static void
+m68k_output_function_epilogue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask, fmask;
+ register int nregs;
+ HOST_WIDE_INT offset, foffset, fpoffset, first = 1;
+ extern char call_used_regs[];
+ HOST_WIDE_INT fsize = ((size) + 3) & -4;
+ int big = 0;
+ rtx insn = get_last_insn ();
+
+ /* If the last insn was a BARRIER, we don't have to write any code. */
+ if (GET_CODE (insn) == NOTE)
+ insn = prev_nonnote_insn (insn);
+ if (insn && GET_CODE (insn) == BARRIER)
+ {
+ /* Output just a no-op so that debuggers don't get confused
+ about which function the pc is in at this address. */
+ fprintf (stream, "\tnop\n");
+ return;
+ }
+
+ nregs = 0; fmask = 0; fpoffset = 0;
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ fmask |= 1 << (23 - regno);
+ }
+
+ foffset = fpoffset + nregs * 12;
+ nregs = 0; mask = 0;
+ if (frame_pointer_needed)
+ regs_ever_live[FRAME_POINTER_REGNUM] = 0;
+
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ mask |= 1 << regno;
+ }
+
+ offset = foffset + nregs * 4;
+ if (offset + fsize >= 0x8000
+ && frame_pointer_needed
+ && (mask || fmask || fpoffset))
+ {
+ fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
+ fsize = 0, big = 1;
+ }
+
+ if (nregs <= 2)
+ {
+ /* Restore each separately in the same order moveml does.
+ Using two movel instructions instead of a single moveml
+ is about 15% faster for the 68020 and 68030 at no expense
+ in code size. */
+
+ int i;
+
+ /* Undo the work from above. */
+ for (i = 0; i< 16; i++)
+ if (mask & (1 << i))
+ {
+ if (big)
+ fprintf (stream, "\tmove.l -%d(%s,a0.l),%s\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[i]);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tmove.l (sp)+,%s\n",
+ reg_names[i]);
+ else
+ fprintf (stream, "\tmove.l -%d(%s),%s\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[i]);
+ offset = offset - 4;
+ }
+ }
+ else if (mask)
+ {
+ first = 1;
+ for (regno = 0; regno < 16; regno++)
+ if (mask & (1 << regno))
+ {
+ if (first && big)
+ {
+ fprintf (stream, "\tmovem.l -%d(%s,a0.l),%s",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[regno]);
+ first = 0;
+ }
+ else if (first && ! frame_pointer_needed)
+ {
+ fprintf (stream, "\tmovem.l (sp)+,%s",
+ reg_names[regno]);
+ first = 0;
+ }
+ else if (first)
+ {
+ fprintf (stream, "\tmovem.l -%d(%s),%s",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[regno]);
+ first = 0;
+ }
+ else
+ fprintf (stream, "/%s", reg_names[regno]);
+ }
+ fprintf (stream, "\n");
+ }
+
+ if (fmask)
+ {
+ first = 1;
+ for (regno = 16; regno < 24; regno++)
+ if (fmask & (1 << (23 - regno)))
+ {
+ if (first && big)
+ {
+ fprintf (stream, "\tfmovem.x -%d(%s,a0.l),%s",
+ foffset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[regno]);
+ first = 0;
+ }
+ else if (first && ! frame_pointer_needed)
+ {
+ fprintf (stream, "\tfmovem.x (sp)+,%s",
+ reg_names[regno]);
+ first = 0;
+ }
+ else if (first)
+ {
+ fprintf (stream, "\tfmovem.x -%d(%s),%s",
+ foffset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[regno]);
+ first = 0;
+ }
+ else
+ fprintf (stream, "/%s", reg_names[regno]);
+ }
+ fprintf (stream, "\n");
+ }
+
+ if (frame_pointer_needed)
+ fprintf (stream, "\tunlk %s\n",
+ reg_names[FRAME_POINTER_REGNUM]);
+ else if (fsize)
+ {
+ if (fsize + 4 < 0x8000)
+ fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
+ else
+ fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
+ }
+
+ if (current_function_pops_args)
+ fprintf (stream, "\trtd #%d\n", current_function_pops_args);
+ else
+ fprintf (stream, "\trts\n");
+}
+
+#else
+#if defined (NEWS) && defined (MOTOROLA)
+
+static void
+m68k_output_function_epilogue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask, fmask;
+ register int nregs;
+ HOST_WIDE_INT offset, foffset;
+ extern char call_used_regs[];
+ HOST_WIDE_INT fsize = ((size) + 3) & -4;
+ int big = 0;
+
+ nregs = 0; fmask = 0;
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ fmask |= 1 << (23 - regno);
+ }
+
+ foffset = nregs * 12;
+ nregs = 0; mask = 0;
+ if (frame_pointer_needed)
+ regs_ever_live[FRAME_POINTER_REGNUM] = 0;
+
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ mask |= 1 << regno;
+ }
+
+ offset = foffset + nregs * 4;
+ if (offset + fsize >= 0x8000
+ && frame_pointer_needed
+ && (mask || fmask))
+ {
+ fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
+ fsize = 0, big = 1;
+ }
+
+ if (exact_log2 (mask) >= 0)
+ {
+ if (big)
+ fprintf (stream, "\tmove.l (-%d,fp,a0.l),%s\n",
+ offset + fsize, reg_names[exact_log2 (mask)]);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tmove.l (sp)+,%s\n",
+ reg_names[exact_log2 (mask)]);
+ else
+ fprintf (stream, "\tmove.l (-%d,fp),%s\n",
+ offset + fsize, reg_names[exact_log2 (mask)]);
+ }
+ else if (mask)
+ {
+ if (big)
+ fprintf (stream, "\tmovem.l (-%d,fp,a0.l),#0x%x\n",
+ offset + fsize, mask);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tmovem.l (sp)+,#0x%x\n", mask);
+ else
+ fprintf (stream, "\tmovem.l (-%d,fp),#0x%x\n",
+ offset + fsize, mask);
+ }
+
+ if (fmask)
+ {
+ if (big)
+ fprintf (stream, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n",
+ foffset + fsize, fmask);
+ else if (! frame_pointer_needed)
+ fprintf (stream, "\tfmovem.x (sp)+,#0x%x\n", fmask);
+ else
+ fprintf (stream, "\tfmovem.x (-%d,fp),#0x%x\n",
+ foffset + fsize, fmask);
+ }
+
+ if (frame_pointer_needed)
+ fprintf (stream, "\tunlk fp\n");
+ else if (fsize)
+ {
+ if (fsize + 4 < 0x8000)
+ fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
+ else
+ fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
+ }
+
+ if (current_function_pops_args)
+ fprintf (stream, "\trtd #%d\n", current_function_pops_args);
+ else
+ fprintf (stream, "\trts\n");
+}
+
+#else /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
+
+static void
+m68k_output_function_epilogue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask, fmask;
+ register int nregs;
+ HOST_WIDE_INT offset, foffset, fpoffset;
+ extern char call_used_regs[];
+ HOST_WIDE_INT fsize = (size + 3) & -4;
int big = 0;
rtx insn = get_last_insn ();
int restore_from_sp = 0;
else
fprintf (stream, "\trts\n");
}
+
+#endif /* ! (DPX2 && MOTOROLA) */
+#endif /* ! (NEWS && MOTOROLA) */
+#endif /* !CRDS */
\f
/* Similar to general_operand, but exclude stack_pointer_rtx. */
: GET_MODE_SIZE (MODE)))) \
? 2 - (CUM) / 4 : 0)
-/* Generate the assembly code for function entry. */
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_function_prologue(FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 1
-/* Generate the assembly code for function exit. */
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_function_epilogue (FILE, SIZE)
-
/* This is a hook for other tm files to change. */
/* #define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) */
#define SGS_NO_LI /* Suppress jump table label usage */
#endif
+#define NEWS
#define NO_DOLLAR_IN_LABEL
#define NO_DOT_IN_LABEL
#undef FUNCTION_PROFILER
#ifdef MOTOROLA
-#undef FUNCTION_PROLOGUE
-#undef FUNCTION_EPILOGUE
#undef REGISTER_NAMES
#undef ASM_OUTPUT_REG_PUSH
#undef ASM_OUTPUT_REG_POP
\f
#ifdef MOTOROLA
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno; \
- register int mask = 0; \
- extern char call_used_regs[]; \
- int fsize = ((SIZE) + 3) & -4; \
- if (frame_pointer_needed) \
- { if (fsize < 0x8000) \
- fprintf (FILE, "\tlink fp,#%d\n", -fsize); \
- else if (TARGET_68020) \
- fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \
- else \
- fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);\
- } \
- else if (fsize) \
- { \
- int amt = fsize + 4; \
- /* Adding negative number is faster on the 68040. */ \
- if (fsize + 4 < 0x8000) \
- asm_fprintf (FILE, "\tadd.w %0I%d,%Rsp\n", - amt); \
- else \
- asm_fprintf (FILE, "\tadd.l %0I%d,%Rsp\n", - amt); \
- } \
- for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- mask |= 1 << (regno - 16); \
- if (mask != 0) \
- fprintf (FILE, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff); \
- mask = 0; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- mask |= 1 << (15 - regno); \
- if (frame_pointer_needed) \
- mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
- if (exact_log2 (mask) >= 0) \
- fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
- else if (mask) fprintf (FILE, "\tmovem.l #0x%x,-(sp)\n", mask); }
-
#define FUNCTION_PROFILER(FILE, LABEL_NO) \
fprintf (FILE, "\tmove.l #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int regno; \
- register int mask, fmask; \
- register int nregs; \
- int offset, foffset; \
- extern char call_used_regs[]; \
- int fsize = ((SIZE) + 3) & -4; \
- int big = 0; \
- nregs = 0; fmask = 0; \
- for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { nregs++; fmask |= 1 << (23 - regno); } \
- foffset = nregs * 12; \
- nregs = 0; mask = 0; \
- if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- { nregs++; mask |= 1 << regno; } \
- offset = foffset + nregs * 4; \
- if (offset + fsize >= 0x8000 \
- && frame_pointer_needed \
- && (mask || fmask)) \
- { fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
- fsize = 0, big = 1; } \
- if (exact_log2 (mask) >= 0) { \
- if (big) \
- fprintf (FILE, "\tmove.l (-%d,fp,a0.l),%s\n", \
- offset + fsize, reg_names[exact_log2 (mask)]); \
- else if (! frame_pointer_needed) \
- fprintf (FILE, "\tmove.l (sp)+,%s\n", \
- reg_names[exact_log2 (mask)]); \
- else \
- fprintf (FILE, "\tmove.l (-%d,fp),%s\n", \
- offset + fsize, reg_names[exact_log2 (mask)]); } \
- else if (mask) { \
- if (big) \
- fprintf (FILE, "\tmovem.l (-%d,fp,a0.l),#0x%x\n", \
- offset + fsize, mask); \
- else if (! frame_pointer_needed) \
- fprintf (FILE, "\tmovem.l (sp)+,#0x%x\n", mask); \
- else \
- fprintf (FILE, "\tmovem.l (-%d,fp),#0x%x\n", \
- offset + fsize, mask); } \
- if (fmask) { \
- if (big) \
- fprintf (FILE, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n", \
- foffset + fsize, fmask); \
- else if (! frame_pointer_needed) \
- fprintf (FILE, "\tfmovem.x (sp)+,#0x%x\n", fmask); \
- else \
- fprintf (FILE, "\tfmovem.x (-%d,fp),#0x%x\n", \
- foffset + fsize, fmask); } \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tunlk fp\n"); \
- else if (fsize) \
- { \
- if (fsize + 4 < 0x8000) \
- fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
- else \
- fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
- } \
- if (current_function_pops_args) \
- fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
- else fprintf (FILE, "\trts\n"); }
-
/* Difference from m68k.h is in `fp' instead of `a6'. */
#define REGISTER_NAMES \
extern int integer_ok_for_set PARAMS ((unsigned));
extern void m88k_layout_frame PARAMS ((void));
extern void m88k_expand_prologue PARAMS ((void));
-extern void m88k_begin_prologue PARAMS ((FILE *, int));
extern void m88k_end_prologue PARAMS ((FILE *));
extern void m88k_expand_epilogue PARAMS ((void));
extern void m88k_begin_epilogue PARAMS ((FILE *));
-extern void m88k_end_epilogue PARAMS ((FILE *, int));
extern void output_function_profiler PARAMS ((FILE *, int, const char *, int));
extern void output_function_block_profiler PARAMS ((FILE *, int));
extern void output_block_profiler PARAMS ((FILE *, int));
extern void output_ascii PARAMS ((FILE *, const char *, int,
- const unsigned char *, int));
+ const char *, int));
extern void output_label PARAMS ((int));
extern struct rtx_def *m88k_builtin_saveregs PARAMS ((void));
extern enum m88k_instruction classify_integer PARAMS ((enum machine_mode, int));
rtx m88k_compare_op1; /* cmpsi operand 1 */
enum processor_type m88k_cpu; /* target cpu */
+
+static void m88k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
FILE *file;
const char *opcode;
int max;
- const unsigned char *p;
+ const char *p;
int size;
{
int i;
fprintf (file, "%s\"", opcode);
for (i = 0; i < size; i++)
{
- register int c = p[i];
+ register int c = (unsigned char) p[i];
if (num > max)
{
(((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
\f
/* Establish the position of the FP relative to the SP. This is done
- either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
+ either during output_function_prologue() or by
+ INITIAL_ELIMINATION_OFFSET. */
void
m88k_layout_frame ()
return 0;
}
\f
-void
-m88k_begin_prologue (stream, size)
+static void
+m88k_output_function_prologue (stream, size)
FILE *stream ATTRIBUTE_UNUSED;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
fprintf (stderr, "$");
}
\f
/* This function generates the assembly code for function exit,
- on machines that need it. Args are same as for FUNCTION_PROLOGUE.
+ on machines that need it.
The function epilogue should not depend on the current stack pointer!
It should use the frame pointer only, if there is a frame pointer.
epilogue_marked = 1;
}
-void
-m88k_end_epilogue (stream, size)
+static void
+m88k_output_function_epilogue (stream, size)
FILE *stream;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
rtx insn = get_last_insn ();
enum processor_type {
PROCESSOR_M88100,
PROCESSOR_M88110,
- PROCESSOR_M88000,
+ PROCESSOR_M88000
};
/* Recast the cpu class to be the cpu attribute. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
m88k_va_arg (valist, type)
-/* Generate the assembly code for function entry. */
-#define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE)
-
/* Perform special actions at the point where the prologue ends. */
#define FUNCTION_END_PROLOGUE(FILE) m88k_end_prologue(FILE)
No definition is equivalent to always zero. */
#define EXIT_IGNORE_STACK (1)
-/* Generate the assembly code for function exit. */
-#define FUNCTION_EPILOGUE(FILE, SIZE) m88k_end_epilogue(FILE, SIZE)
-
/* Perform special actions at the point where the epilogue begins. */
#define FUNCTION_BEGIN_EPILOGUE(FILE) m88k_begin_epilogue(FILE)
#define GCC_MIPS_PROTOS_H
extern HOST_WIDE_INT compute_frame_size PARAMS ((HOST_WIDE_INT));
-extern void function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-extern void function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
extern void mips_asm_file_end PARAMS ((FILE *));
extern void mips_asm_file_start PARAMS ((FILE *));
extern int mips_can_use_return_insn PARAMS ((void));
ATTRIBUTE_NORETURN;
static int symbolic_expression_p PARAMS ((rtx));
static void mips_add_gc_roots PARAMS ((void));
+static void mips_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void mips_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static enum processor_type mips_parse_cpu PARAMS ((const char *));
/* Global variables for machine-dependent things. */
};
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
\f
/* Set up the stack and frame (if desired) for the function. */
-void
-function_prologue (file, size)
+static void
+mips_output_function_prologue (file, size)
FILE *file;
HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
#define RA_MASK BITMASK_HIGH /* 1 << 31 */
#define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
-void
-function_epilogue (file, size)
+static void
+mips_output_function_epilogue (file, size)
FILE *file ATTRIBUTE_UNUSED;
HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
- const char *fnname;
+ const char *fnname = ""; /* FIXME: Correct initialisation? */
#ifndef FUNCTION_NAME_ALREADY_DECLARED
/* Get the function name the same way that toplev.c does before calling
: GET_MODE_ALIGNMENT(MODE)))
\f
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue(FILE, SIZE)
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE)
-
/* Tell prologue and epilogue if register REGNO should be saved / restored. */
#define MUST_SAVE_REGISTER(regno) \
#include "ns32k/ns32k.h"
+#define MERLIN_TARGET
+
/* This is BSD, so it wants DBX format. */
#define DBX_DEBUGGING_INFO
fprintf (FILE, "$0f%.20e", u.d); } \
else output_addr_const (FILE, X); }
-#undef FUNCTION_PROLOGUE
-
-/* This differs from the one in ns32k.h in printing a bitmask
- rather than a register list in the enter or save instruction. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno, g_regs_used = 0; \
- int used_regs_buf[8], *bufp = used_regs_buf; \
- int used_fregs_buf[8], *fbufp = used_fregs_buf; \
- extern char call_used_regs[]; \
- MAIN_FUNCTION_PROLOGUE; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] \
- && ! call_used_regs[regno]) \
- { \
- *bufp++ = regno; g_regs_used++; \
- } \
- *bufp = -1; \
- for (; regno < 16; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) { \
- *fbufp++ = regno; \
- } \
- *fbufp = -1; \
- bufp = used_regs_buf; \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tenter "); \
- else if (g_regs_used) \
- fprintf (FILE, "\tsave "); \
- if (frame_pointer_needed || g_regs_used) \
- { \
- char mask = 0; \
- while (*bufp >= 0) \
- mask |= 1 << *bufp++; \
- fprintf (FILE, "$0x%x", (int) mask & 0xff); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, ",%d\n", SIZE); \
- else if (g_regs_used) \
- fprintf (FILE, "\n"); \
- fbufp = used_fregs_buf; \
- while (*fbufp >= 0) \
- { \
- if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) \
- fprintf (FILE, "\tmovf f%d,tos\n", *fbufp++ - 8); \
- else \
- { \
- fprintf (FILE, "\tmovl f%d,tos\n", fbufp[0] - 8); \
- fbufp += 2; \
- } \
- } \
-}
-
-#undef FUNCTION_EPILOGUE
-
-/* This differs from the one in ns32k.h in printing a bitmask
- rather than a register list in the exit or restore instruction. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int regno, g_regs_used = 0, f_regs_used = 0; \
- int used_regs_buf[8], *bufp = used_regs_buf; \
- int used_fregs_buf[8], *fbufp = used_fregs_buf; \
- extern char call_used_regs[]; \
- *fbufp++ = -2; \
- for (regno = 8; regno < 16; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) { \
- *fbufp++ = regno; f_regs_used++; \
- } \
- fbufp--; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] \
- && ! call_used_regs[regno]) \
- { \
- *bufp++ = regno; g_regs_used++; \
- } \
- while (fbufp > used_fregs_buf) \
- { \
- if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) \
- { \
- fprintf (FILE, "\tmovl tos,f%d\n", fbufp[-1] - 8); \
- fbufp -= 2; \
- } \
- else fprintf (FILE, "\tmovf tos,f%d\n", *fbufp-- - 8); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, "\texit "); \
- else if (g_regs_used) \
- fprintf (FILE, "\trestore "); \
- if (g_regs_used || frame_pointer_needed) \
- { \
- char mask = 0; \
- \
- while (bufp > used_regs_buf) \
- { \
- /* Utek assembler takes care of reversing this */ \
- mask |= 1 << *--bufp; \
- } \
- fprintf (FILE, "$0x%x\n", (int) mask & 0xff); \
- } \
- if (current_function_pops_args) \
- fprintf (FILE, "\tret %d\n", current_function_pops_args); \
- else fprintf (FILE, "\tret 0\n"); }
-
#endif /* UTEK_ASM */
#undef PRINT_OPERAND_ADDRESS
static const char *singlemove_string PARAMS ((rtx *));
static void move_tail PARAMS ((rtx[], int, int));
static int ns32k_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
+static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE ns32k_valid_type_attribute_p
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+/*
+ * The function prologue for the ns32k is fairly simple.
+ * If a frame pointer is needed (decided in reload.c ?) then
+ * we need assembler of the form
+ *
+ * # Save the oldframe pointer, set the new frame pointer, make space
+ * # on the stack and save any general purpose registers necessary
+ *
+ * enter [<general purpose regs to save>], <local stack space>
+ *
+ * movf fn, tos # Save any floating point registers necessary
+ * .
+ * .
+ *
+ * If a frame pointer is not needed we need assembler of the form
+ *
+ * # Make space on the stack
+ *
+ * adjspd <local stack space + 4>
+ *
+ * # Save any general purpose registers necessary
+ *
+ * save [<general purpose regs to save>]
+ *
+ * movf fn, tos # Save any floating point registers necessary
+ * .
+ * .
+ */
+
+#if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
+
+#if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
+#define ADJSP(FILE, N) \
+ fprintf (FILE, "\tadjspd %c%d\n", IMMEDIATE_PREFIX, (N))
+#else
+#define ADJSP(FILE, N) \
+ fprintf (FILE, "\tadjspd %d\n", (N))
+#endif
+
+static void
+ns32k_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ register int regno, g_regs_used = 0;
+ int used_regs_buf[8], *bufp = used_regs_buf;
+ int used_fregs_buf[17], *fbufp = used_fregs_buf;
+ extern char call_used_regs[];
+
+ for (regno = R0_REGNUM; regno < F0_REGNUM; regno++)
+ if (regs_ever_live[regno]
+ && ! call_used_regs[regno])
+ {
+ *bufp++ = regno; g_regs_used++;
+ }
+ *bufp = -1;
+
+ for (; regno < FRAME_POINTER_REGNUM; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ {
+ *fbufp++ = regno;
+ }
+ *fbufp = -1;
+
+ bufp = used_regs_buf;
+ if (frame_pointer_needed)
+ fprintf (file, "\tenter [");
+ else
+ {
+ if (size)
+ ADJSP (file, size + 4);
+ if (g_regs_used && g_regs_used > 4)
+ fprintf (file, "\tsave [");
+ else
+ {
+ while (*bufp >= 0)
+ fprintf (file, "\tmovd r%d,tos\n", *bufp++);
+ g_regs_used = 0;
+ }
+ }
+
+ while (*bufp >= 0)
+ {
+ fprintf (file, "r%d", *bufp++);
+ if (*bufp >= 0)
+ fputc (',', file);
+ }
+
+ if (frame_pointer_needed)
+ fprintf (file, "],%d\n", size);
+ else if (g_regs_used)
+ fprintf (file, "]\n");
+
+ fbufp = used_fregs_buf;
+ while (*fbufp >= 0)
+ {
+ if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
+ fprintf (file, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]);
+ else
+ {
+ fprintf (file, "\tmovl %s,tos\n",
+ ns32k_out_reg_names[fbufp[0]]);
+ fbufp += 2;
+ }
+ }
+
+ if (flag_pic && current_function_uses_pic_offset_table)
+ {
+ fprintf (file, "\tsprd sb,tos\n");
+ if (TARGET_REGPARM)
+ {
+ fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n");
+ fprintf (file, "\tlprd sb,tos\n");
+ }
+ else
+ {
+ fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n");
+ fprintf (file, "\tlprd sb,r0\n");
+ }
+ }
+}
+
+#else /* MERLIN_TARGET || UTEK_ASM */
+
+/* This differs from the standard one above in printing a bitmask
+ rather than a register list in the enter or save instruction. */
+
+static void
+ns32k_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ register int regno, g_regs_used = 0;
+ int used_regs_buf[8], *bufp = used_regs_buf;
+ int used_fregs_buf[8], *fbufp = used_fregs_buf;
+ extern char call_used_regs[];
+
+ for (regno = 0; regno < 8; regno++)
+ if (regs_ever_live[regno]
+ && ! call_used_regs[regno])
+ {
+ *bufp++ = regno; g_regs_used++;
+ }
+ *bufp = -1;
+
+ for (; regno < 16; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno]) {
+ *fbufp++ = regno;
+ }
+ *fbufp = -1;
+
+ bufp = used_regs_buf;
+ if (frame_pointer_needed)
+ fprintf (file, "\tenter ");
+ else if (g_regs_used)
+ fprintf (file, "\tsave ");
+
+ if (frame_pointer_needed || g_regs_used)
+ {
+ char mask = 0;
+ while (*bufp >= 0)
+ mask |= 1 << *bufp++;
+ fprintf (file, "$0x%x", (int) mask & 0xff);
+ }
+
+ if (frame_pointer_needed)
+#ifdef UTEK_ASM
+ fprintf (file, ",$%d\n", size);
+#else
+ fprintf (file, ",%d\n", size);
+#endif
+ else if (g_regs_used)
+ fprintf (file, "\n");
+
+ fbufp = used_fregs_buf;
+ while (*fbufp >= 0)
+ {
+ if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
+ fprintf (file, "\tmovf f%d,tos\n", *fbufp++ - 8);
+ else
+ {
+ fprintf (file, "\tmovl f%d,tos\n", fbufp[0] - 8);
+ fbufp += 2;
+ }
+ }
+}
+
+#endif /* MERLIN_TARGET || UTEK_ASM */
+
+/* This function generates the assembly code for function exit,
+ on machines that need it.
+
+ The function epilogue should not depend on the current stack pointer,
+ if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
+
+ If a frame pointer is needed (decided in reload.c ?) then
+ we need assembler of the form
+
+ movf tos, fn # Restore any saved floating point registers
+ .
+ .
+
+ # Restore any saved general purpose registers, restore the stack
+ # pointer from the frame pointer, restore the old frame pointer.
+ exit [<general purpose regs to save>]
+
+ If a frame pointer is not needed we need assembler of the form
+ # Restore any general purpose registers saved
+
+ movf tos, fn # Restore any saved floating point registers
+ .
+ .
+ .
+ restore [<general purpose regs to save>]
+
+ # reclaim space allocated on stack
+
+ adjspd <-(local stack space + 4)> */
+
+#if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
+
+static void
+ns32k_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ register int regno, g_regs_used = 0, f_regs_used = 0;
+ int used_regs_buf[8], *bufp = used_regs_buf;
+ int used_fregs_buf[17], *fbufp = used_fregs_buf;
+ extern char call_used_regs[];
+
+ if (flag_pic && current_function_uses_pic_offset_table)
+ fprintf (file, "\tlprd sb,tos\n");
+
+ *fbufp++ = -2;
+ for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ {
+ *fbufp++ = regno; f_regs_used++;
+ }
+ fbufp--;
+
+ for (regno = 0; regno < F0_REGNUM; regno++)
+ if (regs_ever_live[regno]
+ && ! call_used_regs[regno])
+ {
+ *bufp++ = regno; g_regs_used++;
+ }
+
+ while (fbufp > used_fregs_buf)
+ {
+ if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
+ {
+ fprintf (file, "\tmovl tos,%s\n",
+ ns32k_out_reg_names[fbufp[-1]]);
+ fbufp -= 2;
+ }
+ else fprintf (file, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]);
+ }
+
+ if (frame_pointer_needed)
+ fprintf (file, "\texit [");
+ else
+ {
+ if (g_regs_used && g_regs_used > 4)
+ fprintf (file, "\trestore [");
+ else
+ {
+ while (bufp > used_regs_buf)
+ fprintf (file, "\tmovd tos,r%d\n", *--bufp);
+ g_regs_used = 0;
+ }
+ }
+
+ while (bufp > used_regs_buf)
+ {
+ fprintf (file, "r%d", *--bufp);
+ if (bufp > used_regs_buf)
+ fputc (',', file);
+ }
+
+ if (g_regs_used || frame_pointer_needed)
+ fprintf (file, "]\n");
+
+ if (size && !frame_pointer_needed)
+ ADJSP (file, -(size + 4));
+
+ if (current_function_pops_args)
+ fprintf (file, "\tret %d\n", current_function_pops_args);
+ else
+ fprintf (file, "\tret 0\n");
+}
+
+#else /* MERLIN_TARGET || UTEK_ASM */
+
+/* This differs from the standard one above in printing a bitmask
+ rather than a register list in the exit or restore instruction. */
+
+static void
+ns32k_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ register int regno, g_regs_used = 0, f_regs_used = 0;
+ int used_regs_buf[8], *bufp = used_regs_buf;
+ int used_fregs_buf[8], *fbufp = used_fregs_buf;
+ extern char call_used_regs[];
+
+ *fbufp++ = -2;
+ for (regno = 8; regno < 16; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno]) {
+ *fbufp++ = regno; f_regs_used++;
+ }
+ fbufp--;
+
+ for (regno = 0; regno < 8; regno++)
+ if (regs_ever_live[regno]
+ && ! call_used_regs[regno])
+ {
+ *bufp++ = regno; g_regs_used++;
+ }
+
+ while (fbufp > used_fregs_buf)
+ {
+ if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
+ {
+ fprintf (file, "\tmovl tos,f%d\n", fbufp[-1] - 8);
+ fbufp -= 2;
+ }
+ else fprintf (file, "\tmovf tos,f%d\n", *fbufp-- - 8);
+ }
+
+ if (frame_pointer_needed)
+ fprintf (file, "\texit ");
+ else if (g_regs_used)
+ fprintf (file, "\trestore ");
+
+ if (g_regs_used || frame_pointer_needed)
+ {
+ char mask = 0;
+
+ while (bufp > used_regs_buf)
+ {
+ /* Utek assembler takes care of reversing this */
+ mask |= 1 << *--bufp;
+ }
+ fprintf (file, "$0x%x\n", (int) mask & 0xff);
+ }
+
+#ifdef UTEK_ASM
+ if (current_function_pops_args)
+ fprintf (file, "\tret $%d\n", current_function_pops_args);
+ else
+ fprintf (file, "\tret $0\n");
+#else
+ if (current_function_pops_args)
+ fprintf (file, "\tret %d\n", current_function_pops_args);
+ else
+ fprintf (file, "\tret 0\n");
+#endif
+}
+
+#endif /* MERLIN_TARGET || UTEK_ASM */
+
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
int
hard_regno_mode_ok (regno, mode)
: GET_MODE_SIZE (MODE)))) \
? 2 - (CUM) / 4 : 0)
-#ifndef MAIN_FUNCTION_PROLOGUE
-#define MAIN_FUNCTION_PROLOGUE
-#endif
-
-/*
- * The function prologue for the ns32k is fairly simple.
- * If a frame pointer is needed (decided in reload.c ?) then
- * we need assembler of the form
- *
- * # Save the oldframe pointer, set the new frame pointer, make space
- * # on the stack and save any general purpose registers necessary
- *
- * enter [<general purpose regs to save>], <local stack space>
- *
- * movf fn, tos # Save any floating point registers necessary
- * .
- * .
- *
- * If a frame pointer is not needed we need assembler of the form
- *
- * # Make space on the stack
- *
- * adjspd <local stack space + 4>
- *
- * # Save any general purpose registers necessary
- *
- * save [<general purpose regs to save>]
- *
- * movf fn, tos # Save any floating point registers necessary
- * .
- * .
- */
-#if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
-#define ADJSP(FILE, N) \
- fprintf (FILE, "\tadjspd %c%d\n", IMMEDIATE_PREFIX, (N))
-#else
-#define ADJSP(FILE, N) \
- fprintf (FILE, "\tadjspd %d\n", (N))
-#endif
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno, g_regs_used = 0; \
- int used_regs_buf[8], *bufp = used_regs_buf; \
- int used_fregs_buf[17], *fbufp = used_fregs_buf; \
- extern char call_used_regs[]; \
- MAIN_FUNCTION_PROLOGUE; \
- for (regno = R0_REGNUM; regno < F0_REGNUM; regno++) \
- if (regs_ever_live[regno] \
- && ! call_used_regs[regno]) \
- { \
- *bufp++ = regno; g_regs_used++; \
- } \
- *bufp = -1; \
- for (; regno < FRAME_POINTER_REGNUM; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- { \
- *fbufp++ = regno; \
- } \
- *fbufp = -1; \
- bufp = used_regs_buf; \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tenter ["); \
- else \
- { \
- if (SIZE) \
- ADJSP (FILE, SIZE + 4); \
- if (g_regs_used && g_regs_used > 4) \
- fprintf (FILE, "\tsave ["); \
- else \
- { \
- while (*bufp >= 0) \
- fprintf (FILE, "\tmovd r%d,tos\n", *bufp++); \
- g_regs_used = 0; \
- } \
- } \
- while (*bufp >= 0) \
- { \
- fprintf (FILE, "r%d", *bufp++); \
- if (*bufp >= 0) \
- fputc (',', FILE); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, "],%d\n", SIZE); \
- else if (g_regs_used) \
- fprintf (FILE, "]\n"); \
- fbufp = used_fregs_buf; \
- while (*fbufp >= 0) \
- { \
- if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) \
- fprintf (FILE, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]); \
- else \
- { \
- fprintf (FILE, "\tmovl %s,tos\n", \
- ns32k_out_reg_names[fbufp[0]]); \
- fbufp += 2; \
- } \
- } \
- if (flag_pic && current_function_uses_pic_offset_table) \
- { \
- fprintf (FILE, "\tsprd sb,tos\n"); \
- if (TARGET_REGPARM) \
- { \
- fprintf (FILE, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n"); \
- fprintf (FILE, "\tlprd sb,tos\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n"); \
- fprintf (FILE, "\tlprd sb,r0\n"); \
- } \
- } \
-}
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry.
functions that have frame pointers.
No definition is equivalent to always zero.
- We use 0, because using 1 requires hair in FUNCTION_EPILOGUE
+ We use 0, because using 1 requires hair in output_function_epilogue()
that is worse than the stack adjust we could save. */
/* #define EXIT_IGNORE_STACK 1 */
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer,
- if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
-
- If a frame pointer is needed (decided in reload.c ?) then
- we need assembler of the form
-
- movf tos, fn # Restore any saved floating point registers
- .
- .
-
- # Restore any saved general purpose registers, restore the stack
- # pointer from the frame pointer, restore the old frame pointer.
- exit [<general purpose regs to save>]
-
- If a frame pointer is not needed we need assembler of the form
- # Restore any general purpose registers saved
-
- movf tos, fn # Restore any saved floating point registers
- .
- .
- .
- restore [<general purpose regs to save>]
-
- # reclaim space allocated on stack
-
- adjspd <-(local stack space + 4)> */
-
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int regno, g_regs_used = 0, f_regs_used = 0; \
- int used_regs_buf[8], *bufp = used_regs_buf; \
- int used_fregs_buf[17], *fbufp = used_fregs_buf; \
- extern char call_used_regs[]; \
- if (flag_pic && current_function_uses_pic_offset_table) \
- fprintf (FILE, "\tlprd sb,tos\n"); \
- *fbufp++ = -2; \
- for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- { \
- *fbufp++ = regno; f_regs_used++; \
- } \
- fbufp--; \
- for (regno = 0; regno < F0_REGNUM; regno++) \
- if (regs_ever_live[regno] \
- && ! call_used_regs[regno]) \
- { \
- *bufp++ = regno; g_regs_used++; \
- } \
- while (fbufp > used_fregs_buf) \
- { \
- if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) \
- { \
- fprintf (FILE, "\tmovl tos,%s\n", \
- ns32k_out_reg_names[fbufp[-1]]); \
- fbufp -= 2; \
- } \
- else fprintf (FILE, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, "\texit ["); \
- else \
- { \
- if (g_regs_used && g_regs_used > 4) \
- fprintf (FILE, "\trestore ["); \
- else \
- { \
- while (bufp > used_regs_buf) \
- fprintf (FILE, "\tmovd tos,r%d\n", *--bufp); \
- g_regs_used = 0; \
- } \
- } \
- while (bufp > used_regs_buf) \
- { \
- fprintf (FILE, "r%d", *--bufp); \
- if (bufp > used_regs_buf) \
- fputc (',', FILE); \
- } \
- if (g_regs_used || frame_pointer_needed) \
- fprintf (FILE, "]\n"); \
- if (SIZE && !frame_pointer_needed) \
- ADJSP (FILE, -(SIZE + 4)); \
- if (current_function_pops_args) \
- fprintf (FILE, "\tret %d\n", current_function_pops_args); \
- else fprintf (FILE, "\tret 0\n"); }
-
/* Store in the variable DEPTH the initial difference between the
frame pointer reg contents and the stack pointer reg contents,
as of the start of the function body. This depends on the layout
#define SHARED_SECTION_ASM_OP "\t.shdata"
#ifdef UTEK_ASM
-#undef FUNCTION_PROLOGUE
-
-/* This differs from the one in ns32k.h in printing a bitmask
- rather than a register list in the enter or save instruction. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno, g_regs_used = 0; \
- int used_regs_buf[8], *bufp = used_regs_buf; \
- int used_fregs_buf[8], *fbufp = used_fregs_buf; \
- extern char call_used_regs[]; \
- MAIN_FUNCTION_PROLOGUE; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] \
- && ! call_used_regs[regno]) \
- { \
- *bufp++ = regno; g_regs_used++; \
- } \
- *bufp = -1; \
- for (; regno < 16; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) { \
- *fbufp++ = regno; \
- } \
- *fbufp = -1; \
- bufp = used_regs_buf; \
- if (frame_pointer_needed) \
- fprintf (FILE, "\tenter "); \
- else if (g_regs_used) \
- fprintf (FILE, "\tsave "); \
- if (frame_pointer_needed || g_regs_used) \
- { \
- char mask = 0; \
- while (*bufp >= 0) \
- mask |= 1 << *bufp++; \
- fprintf (FILE, "$0x%x", (int) mask & 0xff); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, ",$%d\n", SIZE); \
- else if (g_regs_used) \
- fprintf (FILE, "\n"); \
- fbufp = used_fregs_buf; \
- while (*fbufp >= 0) \
- { \
- if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) \
- fprintf (FILE, "\tmovf f%d,tos\n", *fbufp++ - 8); \
- else \
- { \
- fprintf (FILE, "\tmovl f%d,tos\n", fbufp[0] - 8); \
- fbufp += 2; \
- } \
- } \
-}
-
-#undef FUNCTION_EPILOGUE
-
-/* This differs from the one in ns32k.h in printing a bitmask
- rather than a register list in the exit or restore instruction. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int regno, g_regs_used = 0, f_regs_used = 0; \
- int used_regs_buf[8], *bufp = used_regs_buf; \
- int used_fregs_buf[8], *fbufp = used_fregs_buf; \
- extern char call_used_regs[]; \
- *fbufp++ = -2; \
- for (regno = 8; regno < 16; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) { \
- *fbufp++ = regno; f_regs_used++; \
- } \
- fbufp--; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] \
- && ! call_used_regs[regno]) \
- { \
- *bufp++ = regno; g_regs_used++; \
- } \
- while (fbufp > used_fregs_buf) \
- { \
- if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) \
- { \
- fprintf (FILE, "\tmovl tos,f%d\n", fbufp[-1] - 8); \
- fbufp -= 2; \
- } \
- else fprintf (FILE, "\tmovf tos,f%d\n", *fbufp-- - 8); \
- } \
- if (frame_pointer_needed) \
- fprintf (FILE, "\texit "); \
- else if (g_regs_used) \
- fprintf (FILE, "\trestore "); \
- if (g_regs_used || frame_pointer_needed) \
- { \
- char mask = 0; \
- \
- while (bufp > used_regs_buf) \
- { \
- /* Utek assembler takes care of reversing this */ \
- mask |= 1 << *--bufp; \
- } \
- fprintf (FILE, "$0x%x\n", (int) mask & 0xff); \
- } \
- if (current_function_pops_args) \
- fprintf (FILE, "\tret $%d\n", current_function_pops_args); \
- else fprintf (FILE, "\tret $0\n"); }
/* UTek assembler needs "ret $0", not "ret 0". */
#undef TRANSFER_FROM_TRAMPOLINE
extern void output_deferred_plabels PARAMS ((FILE *));
extern void override_options PARAMS ((void));
extern void output_ascii PARAMS ((FILE *, const unsigned char *, int));
-extern void output_function_prologue PARAMS ((FILE *, int));
-extern void output_function_epilogue PARAMS ((FILE *, int));
extern int compute_frame_size PARAMS ((int, int *));
extern int and_mask_p PARAMS ((unsigned HOST_WIDE_INT));
extern int cint_ok_for_move PARAMS ((HOST_WIDE_INT));
static rtx store_reg PARAMS ((int, int, int));
static rtx load_reg PARAMS ((int, int, int));
static rtx set_reg_plus_d PARAMS ((int, int, int));
+static void pa_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
int n_deferred_plabels = 0;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
*/
-/* Global variables set by FUNCTION_PROLOGUE. */
+/* Global variables set by output_function_prologue(). */
/* Size of frame. Need to know this to emit return insns from
leaf procedures. */
static int actual_fsize;
return (fsize + STACK_BOUNDARY - 1) & ~(STACK_BOUNDARY - 1);
}
-void
-output_function_prologue (file, size)
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+/* On HP-PA, move-double insns between fpu and cpu need an 8-byte block
+ of memory. If any fpu reg is used in the function, we allocate
+ such a block here, at the bottom of the frame, just in case it's needed.
+
+ If this function is a leaf procedure, then we may choose not
+ to do a "save" insn. The decision about whether or not
+ to do this is made in regclass.c. */
+
+static void
+pa_output_function_prologue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
/* The function's label and associated .PROC must never be
separated and must be output *after* any profiling declarations
return i;
}
-void
-output_function_epilogue (file, size)
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+pa_output_function_epilogue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
rtx insn = get_last_insn ();
fprintf (FILE, "\n\t.EXIT\n\t.PROCEND\n"); \
}
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-/* On HP-PA, move-double insns between fpu and cpu need an 8-byte block
- of memory. If any fpu reg is used in the function, we allocate
- such a block here, at the bottom of the frame, just in case it's needed.
-
- If this function is a leaf procedure, then we may choose not
- to do a "save" insn. The decision about whether or not
- to do this is made in regclass.c. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- output_function_prologue (FILE, SIZE)
-
/* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
as assembly via FUNCTION_PROFILER. */
(get_frame_size () != 0 \
|| current_function_calls_alloca || current_function_outgoing_args_size)
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
- output_function_epilogue (FILE, SIZE)
-
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.\
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This macro generates the assembly code for function entry. */
-#undef FUNCTION_PROLOGUE
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-do { \
-fprintf(FILE, "\tjsr r5, csv\n"); \
-if ((SIZE) != 0) \
- { \
- fprintf(FILE, "\t/*abuse empty parameter slot for locals!*/\n"); \
- if ((SIZE) > 2) \
- fprintf(FILE, "\tsub $%d, sp\n", (SIZE)-2); \
- }; \
-} while (0)
+#define TWO_BSD
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
#undef EXIT_IGNORE_STACK
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-*/
-
-#undef FUNCTION_EPILOGUE
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-do { \
-fprintf(FILE, "\t/* SP ignored by cret? */\n"); \
-fprintf(FILE, "\tjmp cret\n"); \
-} while (0)
-
#undef INITIAL_FRAME_POINTER_OFFSET
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) \
{ \
#endif /* RTX_CODE */
extern void output_ascii PARAMS ((FILE *, const char *, int));
-extern void output_function_epilogue PARAMS ((FILE *, int));
-extern void output_function_prologue PARAMS ((FILE *, int));
extern const char *output_jump PARAMS ((const char *, const char *, int));
static rtx find_addr_reg PARAMS ((rtx));
static const char *singlemove_string PARAMS ((rtx *));
+static void pdp11_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void pdp11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
knowing which registers should not be saved even if used.
*/
-void
-output_function_prologue(stream, size)
- FILE *stream;
- int size;
+#ifdef TWO_BSD
+
+static void
+pdp11_output_function_prologue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
{
- int fsize = ((size) + 1) & ~1;
- int regno;
+ fprintf (stream, "\tjsr r5, csv\n");
+ if (size)
+ {
+ fprintf (stream, "\t/*abuse empty parameter slot for locals!*/\n");
+ if (size > 2)
+ fprintf(stream, "\tsub $%d, sp\n", size - 2);
+ }
+}
+
+#else /* !TWO_BSD */
+
+static void
+pdp11_output_function_prologue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
+{
+ HOST_WIDE_INT fsize = ((size) + 1) & ~1;
+ int regno;
int via_ac = -1;
-
- fprintf (stream, "\n\t; /* function prologue %s*/\n", current_function_name);
+
+ fprintf (stream,
+ "\n\t; /* function prologue %s*/\n", current_function_name);
/* if we are outputting code for main,
the switch FPU to right mode if TARGET_FPU */
if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
{
- fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
+ fprintf(stream,
+ "\t;/* switch cpu to double float, single integer */\n");
fprintf(stream, "\tsetd\n");
fprintf(stream, "\tseti\n\n");
}
fprintf (stream, "\t;/* end of prologue */\n\n");
}
+#endif /* !TWO_BSD */
+
/*
The function epilogue should not depend on the current stack pointer!
It should use the frame pointer only. This is mandatory because
maybe as option if you want to generate code for kernel mode? */
+#ifdef TWO_BSD
+
+static void
+pdp11_output_function_epilogue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ fprintf (stream, "\t/* SP ignored by cret? */\n");
+ fprintf (stream, "\tjmp cret\n");
+}
-void
-output_function_epilogue(stream, size)
- FILE *stream;
- int size;
+#else /* !TWO_BSD */
+
+static void
+pdp11_output_function_epilogue (stream, size)
+ FILE *stream;
+ HOST_WIDE_INT size;
{
- int fsize = ((size) + 1) & ~1;
+ HOST_WIDE_INT fsize = ((size) + 1) & ~1;
int i, j, k;
int via_ac;
fprintf (stream, "\trts pc\n");
fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
}
+
+#endif /* !TWO_BSD */
/* Return the best assembler insn template
for moving operands[1] into operands[0] as a fullword. */
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
-/* This macro generates the assembly code for function entry. */
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- output_function_prologue(FILE, SIZE);
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-*/
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
- output_function_epilogue(FILE, SIZE);
-
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) \
{ \
int offset, regno; \
extern int null_epilogue PARAMS ((void));
extern int romp_sa_size PARAMS ((void));
extern int romp_makes_calls PARAMS ((void));
-extern void output_prolog PARAMS ((FILE *, int));
extern void output_encoded_offset PARAMS ((FILE *, unsigned));
-extern void output_epilog PARAMS ((FILE *, int));
extern int romp_debugger_auto_correction PARAMS ((int));
extern int romp_debugger_arg_correction PARAMS ((int));
extern const char *output_in_line_mul PARAMS ((void));
static void init_fpops PARAMS ((void));
static int memory_offset_in_range_p PARAMS ((rtx, enum machine_mode, int, int));
static unsigned int hash_rtx PARAMS ((rtx));
+static void romp_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void romp_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE romp_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE romp_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
word for static link, as many words as required for general register
save area, plus 2 words for each FP reg 2-7 that must be saved. */
-void
-output_prolog (file, size)
+static void
+romp_output_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int first_reg;
int reg_save_offset;
- int fp_save = size + current_function_outgoing_args_size;
+ HOST_WIDE_INT fp_save = size + current_function_outgoing_args_size;
init_fpops ();
}
\f
/* Output the offset information used by debuggers.
- This is the exactly the total_size value of output_epilog
+ This is the exactly the total_size value of output_function_epilogue()
which is added to the frame pointer. However the value in the debug
table is encoded in a space-saving way as follows:
\f
/* Write function epilogue. */
-void
-output_epilog (file, size)
+static void
+romp_output_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
int first_reg = first_reg_to_save();
int pushes_stack = romp_pushes_stack ();
int reg_save_offset = - ((16 - first_reg) + 1 + 4 + 4) * 4;
- int total_size = (size + romp_sa_size ()
- + current_function_outgoing_args_size);
- int fp_save = size + current_function_outgoing_args_size;
+ HOST_WIDE_INT total_size = (size + romp_sa_size ()
+ + current_function_outgoing_args_size);
+ HOST_WIDE_INT fp_save = size + current_function_outgoing_args_size;
int long_frame = total_size >= 32768;
rtx insn = get_last_insn ();
int write_code = 1;
#define SELECT_RTX_SECTION(MODE, X) data_section ()
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
functions that have frame pointers.
No definition is equivalent to always zero. */
/* #define EXIT_IGNORE_STACK 1 */
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
\f
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.
extern int first_reg_to_save PARAMS ((void));
extern int first_fp_reg_to_save PARAMS ((void));
extern rs6000_stack_t *rs6000_stack_info PARAMS ((void));
-extern void output_prolog PARAMS ((FILE *, int));
-extern void output_epilog PARAMS ((FILE *, int));
extern void output_ascii PARAMS ((FILE *, const char *, int));
extern void rs6000_gen_section_name PARAMS ((char **, const char *,
const char *));
static void rs6000_init_machine_status PARAMS ((struct function *));
static int rs6000_ra_ever_killed PARAMS ((void));
static int rs6000_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
+static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Default register names. */
char rs6000_reg_names[][8] =
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE rs6000_valid_type_attribute_p
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Override command line options. Mostly we process the processor
/* Write function prologue. */
-void
-output_prolog (file, size)
+static void
+rs6000_output_function_prologue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
rs6000_stack_t *info = rs6000_stack_info ();
/* Write function epilogue. */
-void
-output_epilog (file, size)
+static void
+rs6000_output_function_epilogue (file, size)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
rs6000_stack_t *info = rs6000_stack_info ();
The effect must be as if FUNCTION had been called directly with the adjusted
first argument. This macro is responsible for emitting all of the code for
- a thunk function; `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' are not
- invoked.
+ a thunk function; output_function_prologue() and output_function_epilogue()
+ are not invoked.
The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been
extracted from it.) It might possibly be useful on some targets, but
argument is passed depends on whether or not it is a named argument. */
#define STRICT_ARGUMENT_NAMING 1
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
|| (current_function_calls_eh_return \
&& TARGET_AIX \
&& (REGNO) == TOC_REGISTER))
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
\f
/* TRAMPOLINE_TEMPLATE deleted */
the return address. Hence returning from FUNCTION will return to whoever
called the current thunk'.
- The effect must be as if FUNCTION had been called directly with the adjusted
- first argument. This macro is responsible for emitting all of the code for
- a thunk function; FUNCTION_PROLOGUE' and FUNCTION_EPILOGUE' are not
+ The effect must be as if FUNCTION had been called directly with
+ the adjusted first argument. This macro is responsible for
+ emitting all of the code for a thunk function;
+ output_function_prologue() and output_function_epilogue() are not
invoked.
The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been
extern void sh_expand_prologue PARAMS ((void));
extern void sh_expand_epilogue PARAMS ((void));
extern int sh_need_epilogue PARAMS ((void));
-extern void function_epilogue PARAMS ((FILE *, int));
extern int initial_elimination_offset PARAMS ((int, int));
extern int fldi_ok PARAMS ((void));
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
static rtx mark_constant_pool_use PARAMS ((rtx));
static int sh_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
+static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE sh_valid_decl_attribute
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
+
struct gcc_target target = TARGET_INITIALIZER;
\f
/* Print the operand address in x to the stream. */
/* Clear variables at function end. */
-void
-function_epilogue (stream, size)
- FILE *stream ATTRIBUTE_UNUSED;
- int size ATTRIBUTE_UNUSED;
+static void
+sh_output_function_epilogue (file, size)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
trap_exit = pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0;
sh_need_epilogue_known = 0;
#define EXIT_IGNORE_STACK 1
-/* Generate the assembly code for function exit
- Just dump out any accumulated constant table. */
-
-#define FUNCTION_EPILOGUE(STREAM, SIZE) function_epilogue ((STREAM), (SIZE))
-
/*
On the SH, the trampoline looks like
2 0002 D202 mov.l l2,r2
extern void ultrasparc_sched_init PARAMS ((FILE *, int));
extern void load_pic_register PARAMS ((void));
extern void order_regs_for_local_alloc PARAMS ((void));
-extern void output_function_epilogue PARAMS ((FILE *, int, int));
-extern void output_function_prologue PARAMS ((FILE *, int, int));
-extern void sparc_flat_output_function_epilogue PARAMS ((FILE *, int));
-extern void sparc_flat_output_function_prologue PARAMS ((FILE *, int));
extern int compute_frame_size PARAMS ((int, int));
extern int check_pic PARAMS ((int));
extern int short_branch PARAMS ((int, int));
static void ultra_rescan_pipeline_state PARAMS ((rtx *, int));
static int set_extends PARAMS ((rtx));
static void output_restore_regs PARAMS ((FILE *, int));
+static void sparc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_flat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_flat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_nonflat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT,
+ int));
+static void sparc_nonflat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT,
+ int));
\f
/* Option handling. */
enum processor_type sparc_cpu;
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE sparc_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE sparc_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
#endif
}
+/* This function generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
+ of memory. If any fpu reg is used in the function, we allocate
+ such a block here, at the bottom of the frame, just in case it's needed.
+
+ If this function is a leaf procedure, then we may choose not
+ to do a "save" insn. The decision about whether or not
+ to do this is made in regclass.c. */
+
+static void
+sparc_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ if (TARGET_FLAT)
+ sparc_flat_function_prologue (file, size);
+ else
+ sparc_nonflat_function_prologue (file, size,
+ current_function_uses_only_leaf_regs);
+}
+
/* Output code for the function prologue. */
-void
-output_function_prologue (file, size, leaf_function)
+static void
+sparc_nonflat_function_prologue (file, size, leaf_function)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
int leaf_function;
{
sparc_output_scratch_registers (file);
restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
}
+/* This function generates the assembly code for function exit,
+ on machines that need it.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+static void
+sparc_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ if (TARGET_FLAT)
+ sparc_flat_function_epilogue (file, size);
+ else
+ sparc_nonflat_function_epilogue (file, size,
+ current_function_uses_only_leaf_regs);
+}
+
/* Output code for the function epilogue. */
-void
-output_function_epilogue (file, size, leaf_function)
+static void
+sparc_nonflat_function_epilogue (file, size, leaf_function)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
int leaf_function;
{
const char *ret;
\f
/* Set up the stack and frame (if desired) for the function. */
-void
-sparc_flat_output_function_prologue (file, size)
+static void
+sparc_flat_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
const char *sp_str = reg_names[STACK_POINTER_REGNUM];
unsigned long gmask = current_frame_info.gmask;
/* Subtract %sp in two steps, but make sure there is always a
64 byte register save area, and %sp is properly aligned. */
/* Amount to decrement %sp by, the first time. */
- unsigned int size1 = ((size - reg_offset + 64) + 15) & -16;
+ unsigned HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
/* Offset to register save area from %sp. */
- unsigned int offset = size1 - (size - reg_offset);
+ unsigned HOST_WIDE_INT offset = size1 - (size - reg_offset);
if (size1 <= 4096)
{
/* Do any necessary cleanup after a function to restore stack, frame,
and regs. */
-void
-sparc_flat_output_function_epilogue (file, size)
+static void
+sparc_flat_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
rtx epilogue_delay = current_function_epilogue_delay_list;
int noepilogue = FALSE;
if (!noepilogue)
{
- unsigned int reg_offset = current_frame_info.reg_offset;
- unsigned int size1;
+ unsigned HOST_WIDE_INT reg_offset = current_frame_info.reg_offset;
+ unsigned HOST_WIDE_INT size1;
const char *sp_str = reg_names[STACK_POINTER_REGNUM];
const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
const char *t1_str = "%g1";
#define MASK_FPU 1
#define TARGET_FPU (target_flags & MASK_FPU)
-/* Nonzero if we should use FUNCTION_EPILOGUE. Otherwise, we
+/* Nonzero if we should use function_epilogue(). Otherwise, we
use fast return insns, but lose some generality. */
#define MASK_EPILOGUE 2
#define TARGET_EPILOGUE (target_flags & MASK_EPILOGUE)
N_("Do not use hardware fp") }, \
{"soft-float", MASK_FPU_SET, NULL }, \
{"epilogue", MASK_EPILOGUE, \
- N_("Use FUNCTION_EPILOGUE") }, \
+ N_("Use function_epilogue()") }, \
{"no-epilogue", -MASK_EPILOGUE, \
- N_("Do not use FUNCTION_EPILOGUE") }, \
+ N_("Do not use function_epilogue()") }, \
{"unaligned-doubles", MASK_UNALIGNED_DOUBLES, \
N_("Assume possible double misalignment") }, \
{"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES, \
} while (0)
#endif
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
- of memory. If any fpu reg is used in the function, we allocate
- such a block here, at the bottom of the frame, just in case it's needed.
-
- If this function is a leaf procedure, then we may choose not
- to do a "save" insn. The decision about whether or not
- to do this is made in regclass.c. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- (TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, (int)SIZE) \
- : output_function_prologue (FILE, (int)SIZE, \
- current_function_uses_only_leaf_regs))
\f
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
(get_frame_size () != 0 \
|| current_function_calls_alloca || current_function_outgoing_args_size)
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
- (TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, (int)SIZE) \
- : output_function_epilogue (FILE, (int)SIZE, \
- current_function_uses_only_leaf_regs))
-
#define DELAY_SLOTS_FOR_EPILOGUE \
(TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \
#include "function.h"
#include "output.h"
#include "insn-attr.h"
-#ifdef VMS_TARGET
#include "tree.h"
-#endif
+#include "recog.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+
+static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
struct gcc_target target = TARGET_INITIALIZER;
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+static void
+vax_output_function_prologue (file, size)
+ FILE * file;
+ HOST_WIDE_INT size;
+{
+ register int regno;
+ register int mask = 0;
+ extern char call_used_regs[];
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ mask |= 1 << regno;
+
+ fprintf (file, "\t.word 0x%x\n", mask);
+
+ if (VMS_TARGET)
+ {
+ /*
+ * This works for both gcc and g++. It first checks to see if
+ * the current routine is "main", which will only happen for
+ * GCC, and add the jsb if it is. If is not the case then try
+ * and see if __MAIN_NAME is part of current_function_name,
+ * which will only happen if we are running g++, and add the jsb
+ * if it is. In gcc there should never be a paren in the
+ * function name, and in g++ there is always a "(" in the
+ * function name, thus there should never be any confusion.
+ *
+ * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
+ * is required when linking with the VMS POSIX version of the C
+ * run-time library; using `subl2 $4,r0' is adequate but we use
+ * `clrl -(sp)' instead. The extra 4 bytes could be removed
+ * after the call because STARTING_FRAME_OFFSET's setting of -4
+ * will end up adding them right back again, but don't bother.
+ */
+
+ const char *p = current_function_name;
+ int is_main = strcmp ("main", p) == 0;
+# define __MAIN_NAME " main("
+
+ while (!is_main && *p != '\0')
+ {
+ if (*p == *__MAIN_NAME
+ && strncmp (p, __MAIN_NAME, sizeof __MAIN_NAME - sizeof "") == 0)
+ is_main = 1;
+ else
+ p++;
+ }
+
+ if (is_main)
+ fprintf (file, "\t%s\n\t%s\n", "clrl -(sp)", "jsb _C$MAIN_ARGS");
+ }
+
+ size -= STARTING_FRAME_OFFSET;
+ if (size >= 64)
+ fprintf (file, "\tmovab %d(sp),sp\n", -size);
+ else if (size)
+ fprintf (file, "\tsubl2 $%d,sp\n", size);
+}
+
/* This is like nonimmediate_operand with a restriction on the type of MEM. */
void
return 0;
}
\f
-#ifdef VMS_TARGET
+#if VMS_TARGET
/* Additional support code for VMS target. */
/* Linked list of all externals that are to be emitted when optimizing
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#define VMS_TARGET 0
/* Names to predefine in the preprocessor for this target machine. */
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate,
- adjusted by STARTING_FRAME_OFFSET to accommodate vms.h.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno; \
- register int mask = 0; \
- register int size = SIZE - STARTING_FRAME_OFFSET; \
- extern char call_used_regs[]; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- mask |= 1 << regno; \
- fprintf (FILE, "\t.word 0x%x\n", mask); \
- MAYBE_VMS_FUNCTION_PROLOGUE(FILE) \
- if ((size) >= 64) fprintf (FILE, "\tmovab %d(sp),sp\n", -size);\
- else if (size) fprintf (FILE, "\tsubl2 $%d,sp\n", (size)); }
-
-/* vms.h redefines this. */
-#define MAYBE_VMS_FUNCTION_PROLOGUE(FILE)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE. */
-
-/* #define FUNCTION_EPILOGUE(FILE, SIZE) */
-
/* Store in the variable DEPTH the initial difference between the
frame pointer reg contents and the stack pointer reg contents,
as of the start of the function body. This depends on the layout
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define VMS_TARGET
-
#define TARGET_EXECUTABLE_SUFFIX ".exe"
#define TARGET_OBJECT_SUFFIX ".obj"
#include "vax/vax.h"
+#undef VMS_TARGET
+#define VMS_TARGET 1
+
#undef LIB_SPEC
#undef CPP_PREDEFINES
#undef TARGET_NAME
#undef TARGET_DEFAULT
#undef CALL_USED_REGISTERS
-#undef MAYBE_VMS_FUNCTION_PROLOGUE
#undef STARTING_FRAME_OFFSET
/* Predefine this in CPP because VMS limits the size of command options
#define STARTING_FRAME_OFFSET -4
-#define __MAIN_NAME " main("
-/*
- * The MAYBE_VMS_FUNCTION_PROLOGUE macro works for both gcc and g++. It
- * first checks to see if the current routine is "main", which will only
- * happen for GCC, and add the jsb if it is. If is not the case then try and
- * see if __MAIN_NAME is part of current_function_name, which will only happen
- * if we are running g++, and add the jsb if it is. In gcc there should never
- * be a paren in the function name, and in g++ there is always a "(" in the
- * function name, thus there should never be any confusion.
- *
- * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS is required
- * when linking with the VMS POSIX version of the C run-time library; using
- * `subl2 $4,r0' is adequate but we use `clrl -(sp)' instead. The extra 4
- * bytes could be removed after the call because STARTING_FRAME_OFFSET's
- * setting of -4 will end up adding them right back again, but don't bother.
- */
-#define MAYBE_VMS_FUNCTION_PROLOGUE(FILE) \
-{ const char *p = current_function_name; \
- int is_main = strcmp ("main", p) == 0; \
- while (!is_main && *p != '\0') \
- { \
- if (*p == *__MAIN_NAME \
- && strncmp (p, __MAIN_NAME, sizeof __MAIN_NAME - sizeof "") == 0) \
- is_main = 1; \
- else \
- p++; \
- } \
- if (is_main) \
- fprintf (FILE, "\t%s\n\t%s\n", "clrl -(sp)", "jsb _C$MAIN_ARGS"); \
-}
-
/* This macro definition sets up a default value for `main' to return. */
#define DEFAULT_MAIN_RETURN c_expand_return (integer_one_node)
\f
#include "real.h"
#include "recog.h"
#include "output.h"
+#include "regs.h"
+#include "tree.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+
+static void we32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void we32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
\f
/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE we32k_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE we32k_output_function_epilogue
struct gcc_target target = TARGET_INITIALIZER;
\f
+/* Generate the assembly code for function entry. FILE is a stdio
+ stream to output the code to. SIZE is an int: how many units of
+ temporary storage to allocate.
+
+ Refer to the array `regs_ever_live' to determine which registers to
+ save; `regs_ever_live[I]' is nonzero if register number I is ever
+ used in the function. This function is responsible for knowing
+ which registers should not be saved even if used. */
+
+static void
+we32k_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ register int nregs_to_save;
+ register int regno;
+ extern char call_used_regs[];
+
+ nregs_to_save = 0;
+ for (regno = 8; regno > 2; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ nregs_to_save = (9 - regno);
+
+ fprintf (file, "\tsave &%d\n", nregs_to_save);
+ if (size)
+ fprintf (file, "\taddw2 &%d,%%sp\n", (size + 3) & ~3);
+}
+
+/* This function generates the assembly code for function exit.
+ Args are as for output_function_prologue ().
+
+ The function epilogue should not depend on the current stack
+ pointer! It should use the frame pointer only. This is mandatory
+ because of alloca; we also take advantage of it to omit stack
+ adjustments before returning. */
+
+static void
+we32k_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ register int nregs_to_restore;
+ register int regno;
+ extern char call_used_regs[];
+
+ nregs_to_restore = 0;
+ for (regno = 8; regno > 2; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ nregs_to_restore = (9 - regno);
+
+ fprintf (file, "\tret &%d\n", nregs_to_restore);
+}
+
void
output_move_double (operands)
rtx *operands;
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int nregs_to_save; \
- register int regno; \
- extern char call_used_regs[]; \
- nregs_to_save = 0; \
- for (regno = 8; regno > 2; regno--) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- nregs_to_save = (9 - regno); \
- fprintf (FILE, "\tsave &%d\n", nregs_to_save); \
- if (SIZE) \
- fprintf (FILE, "\taddw2 &%d,%%sp\n", ((SIZE) + 3) & ~3); }
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 0
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
-{ register int nregs_to_restore; \
- register int regno; \
- extern char call_used_regs[]; \
- nregs_to_restore = 0; \
- for (regno = 8; regno > 2; regno--) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- nregs_to_restore = (9 - regno); \
- fprintf (FILE, "\tret &%d\n", nregs_to_restore); }
-
/* Store in the variable DEPTH the initial difference between the
frame pointer reg contents and the stack pointer reg contents,
as of the start of the function body. This depends on the layout
@findex current_function_is_leaf
@findex current_function_uses_only_leaf_regs
-Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
-treat leaf functions specially. They can test the C variable
-@code{current_function_is_leaf} which is nonzero for leaf functions.
-@code{current_function_is_leaf} is set prior to local register allocation
-and is valid for the remaining compiler passes. They can also test the C
-variable @code{current_function_uses_only_leaf_regs} which is nonzero for
-leaf functions which only use leaf registers.
+Normally, @code{TARGET_ASM_FUNCTION_PROLOGUE} and
+@code{TARGET_ASM_FUNCTION_EPILOGUE} must treat leaf functions specially.
+They can test the C variable @code{current_function_is_leaf} which is
+nonzero for leaf functions. @code{current_function_is_leaf} is set
+prior to local register allocation and is valid for the remaining
+compiler passes. They can also test the C variable
+@code{current_function_uses_only_leaf_regs} which is nonzero for leaf
+functions which only use leaf registers.
@code{current_function_uses_only_leaf_regs} is valid after reload and is
only useful if @code{LEAF_REGISTERS} is defined.
@c changed this to fix overfull. ALSO: why the "it" at the beginning
If the value of the @code{STACK_CHECK_BUILTIN} macro is nonzero, GCC
will assume that you have arranged for stack checking to be done at
appropriate places in the configuration files, e.g., in
-@code{FUNCTION_PROLOGUE}. GCC will do not other special processing.
+@code{TARGET_ASM_FUNCTION_PROLOGUE}. GCC will do not other special
+processing.
@item
If @code{STACK_CHECK_BUILTIN} is zero and you defined a named pattern
This section describes the macros that output function entry
(@dfn{prologue}) and exit (@dfn{epilogue}) code.
-@table @code
-@findex FUNCTION_PROLOGUE
-@item FUNCTION_PROLOGUE (@var{file}, @var{size})
-A C compound statement that outputs the assembler code for entry to a
+@deftypefn {Target Hook} void TARGET_ASM_FUNCTION_PROLOGUE (FILE *@var{file}, HOST_WIDE_INT @var{size})
+If defined, a function that outputs the assembler code for entry to a
function. The prologue is responsible for setting up the stack frame,
initializing the frame pointer register, saving registers that must be
saved, and allocating @var{size} additional bytes of storage for the
@code{regs_ever_live}: element @var{r} is nonzero if hard register
@var{r} is used anywhere within the function. This implies the function
prologue should save register @var{r}, provided it is not one of the
-call-used registers. (@code{FUNCTION_EPILOGUE} must likewise use
+call-used registers. (@code{TARGET_ASM_FUNCTION_EPILOGUE} must likewise use
@code{regs_ever_live}.)
On machines that have ``register windows'', the function entry code does
compatibility reasons. Except in cases where required by standard
or by a debugger, there is no reason why the stack layout used by GCC
need agree with that used by other compilers for a machine.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_ASM_FUNCTION_EPILOGUE (FILE *@var{file}, HOST_WIDE_INT @var{size})
+If defined, a function that outputs the assembler code for exit from a
+function. The epilogue is responsible for restoring the saved
+registers and stack pointer to their values when the function was
+called, and returning control to the caller. This macro takes the
+same arguments as the macro @code{TARGET_ASM_FUNCTION_PROLOGUE}, and the
+registers to restore are determined from @code{regs_ever_live} and
+@code{CALL_USED_REGISTERS} in the same way.
+
+On some machines, there is a single instruction that does all the work
+of returning from the function. On these machines, give that
+instruction the name @samp{return} and do not define the macro
+@code{TARGET_ASM_FUNCTION_EPILOGUE} at all.
+
+Do not define a pattern named @samp{return} if you want the
+@code{TARGET_ASM_FUNCTION_EPILOGUE} to be used. If you want the target
+switches to control whether return instructions or epilogues are used,
+define a @samp{return} pattern with a validity condition that tests the
+target switches appropriately. If the @samp{return} pattern's validity
+condition is false, epilogues will be used.
+
+On machines where functions may or may not have frame-pointers, the
+function exit code must vary accordingly. Sometimes the code for these
+two cases is completely different. To determine whether a frame pointer
+is wanted, the macro can refer to the variable
+@code{frame_pointer_needed}. The variable's value will be 1 when compiling
+a function that needs a frame pointer.
+
+Normally, @code{TARGET_ASM_FUNCTION_PROLOGUE} and
+@code{TARGET_ASM_FUNCTION_EPILOGUE} must treat leaf functions specially.
+The C variable @code{current_function_is_leaf} is nonzero for such a
+function. @xref{Leaf Functions}.
+
+On some machines, some functions pop their arguments on exit while
+others leave that for the caller to do. For example, the 68020 when
+given @option{-mrtd} pops arguments in functions that take a fixed
+number of arguments.
+
+@findex current_function_pops_args
+Your definition of the macro @code{RETURN_POPS_ARGS} decides which
+functions pop their own arguments. @code{TARGET_ASM_FUNCTION_EPILOGUE}
+needs to know what was decided. The variable that is called
+@code{current_function_pops_args} is the number of bytes of its
+arguments that a function should pop. @xref{Scalar Return}.
+@c what is the "its arguments" in the above sentence referring to, pray
+@c tell? --mew 5feb93
+@end deftypefn
+
+@table @code
@itemize @bullet
@item
argument lists of the function. @xref{Stack Arguments}.
@end itemize
-Normally, it is necessary for the macros @code{FUNCTION_PROLOGUE} and
-@code{FUNCTION_EPILOGUE} to treat leaf functions specially. The C
-variable @code{current_function_is_leaf} is nonzero for such a function.
+Normally, it is necessary for the macros
+@code{TARGET_ASM_FUNCTION_PROLOGUE} and
+@code{TARGET_ASM_FUNCTION_EPILOGUE} to treat leaf functions specially.
+The C variable @code{current_function_is_leaf} is nonzero for such a
+function.
@findex EXIT_IGNORE_STACK
@item EXIT_IGNORE_STACK
used by the epilogue or the @samp{return} pattern. The stack and frame
pointer registers are already be assumed to be used as needed.
-@findex FUNCTION_EPILOGUE
-@item FUNCTION_EPILOGUE (@var{file}, @var{size})
-A C compound statement that outputs the assembler code for exit from a
-function. The epilogue is responsible for restoring the saved
-registers and stack pointer to their values when the function was
-called, and returning control to the caller. This macro takes the
-same arguments as the macro @code{FUNCTION_PROLOGUE}, and the
-registers to restore are determined from @code{regs_ever_live} and
-@code{CALL_USED_REGISTERS} in the same way.
-
-On some machines, there is a single instruction that does all the work
-of returning from the function. On these machines, give that
-instruction the name @samp{return} and do not define the macro
-@code{FUNCTION_EPILOGUE} at all.
-
-Do not define a pattern named @samp{return} if you want the
-@code{FUNCTION_EPILOGUE} to be used. If you want the target switches
-to control whether return instructions or epilogues are used, define a
-@samp{return} pattern with a validity condition that tests the target
-switches appropriately. If the @samp{return} pattern's validity
-condition is false, epilogues will be used.
-
-On machines where functions may or may not have frame-pointers, the
-function exit code must vary accordingly. Sometimes the code for these
-two cases is completely different. To determine whether a frame pointer
-is wanted, the macro can refer to the variable
-@code{frame_pointer_needed}. The variable's value will be 1 when compiling
-a function that needs a frame pointer.
-
-Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
-treat leaf functions specially. The C variable @code{current_function_is_leaf}
-is nonzero for such a function. @xref{Leaf Functions}.
-
-On some machines, some functions pop their arguments on exit while
-others leave that for the caller to do. For example, the 68020 when
-given @option{-mrtd} pops arguments in functions that take a fixed
-number of arguments.
-
-@findex current_function_pops_args
-Your definition of the macro @code{RETURN_POPS_ARGS} decides which
-functions pop their own arguments. @code{FUNCTION_EPILOGUE} needs to
-know what was decided. The variable that is called
-@code{current_function_pops_args} is the number of bytes of its
-arguments that a function should pop. @xref{Scalar Return}.
-@c what is the "its arguments" in the above sentence referring to, pray
-@c tell? --mew 5feb93
-
@findex DELAY_SLOTS_FOR_EPILOGUE
@item DELAY_SLOTS_FOR_EPILOGUE
Define this macro if the function epilogue contains delay slots to which
list made with @code{insn_list} objects, stored in the variable
@code{current_function_epilogue_delay_list}. The insn for the first
delay slot comes first in the list. Your definition of the macro
-@code{FUNCTION_EPILOGUE} should fill the delay slots by outputting the
-insns in this list, usually by calling @code{final_scan_insn}.
+@code{TARGET_ASM_FUNCTION_EPILOGUE} should fill the delay slots by
+outputting the insns in this list, usually by calling
+@code{final_scan_insn}.
You need not define this macro if you did not define
@code{DELAY_SLOTS_FOR_EPILOGUE}.
The effect must be as if @var{function} had been called directly with
the adjusted first argument. This macro is responsible for emitting all
-of the code for a thunk function; @code{FUNCTION_PROLOGUE} and
-@code{FUNCTION_EPILOGUE} are not invoked.
+of the code for a thunk function; @code{TARGET_ASM_FUNCTION_PROLOGUE}
+and @code{TARGET_ASM_FUNCTION_EPILOGUE} are not invoked.
The @var{thunk_fndecl} is redundant. (@var{delta} and @var{function}
have already been extracted from it.) It might possibly be useful on
@findex __bb_trace_ret
@vindex profile_block_flag
@item FUNCTION_BLOCK_PROFILER_EXIT (@var{file})
-A C statement or compound statement to output to @var{file}
-assembler code to call function @code{__bb_trace_ret}. The
-assembler code should only be output
-if the global compile flag @code{profile_block_flag} == 2. This
-macro has to be used at every place where code for returning from
-a function is generated (e.g.@: @code{FUNCTION_EPILOGUE}). Although
-you have to write the definition of @code{FUNCTION_EPILOGUE}
-as well, you have to define this macro to tell the compiler, that
-the proper call to @code{__bb_trace_ret} is produced.
+A C statement or compound statement to output to @var{file} assembler
+code to call function @code{__bb_trace_ret}. The assembler code should
+only be output if the global compile flag @code{profile_block_flag} ==
+2. This macro has to be used at every place where code for returning
+from a function is generated (e.g.@:
+@code{TARGET_ASM_FUNCTION_EPILOGUE}). Although you have to write the
+definition of @code{TARGET_ASM_FUNCTION_EPILOGUE} as well, you have to
+define this macro to tell the compiler, that the proper call to
+@code{__bb_trace_ret} is produced.
@findex MACHINE_STATE_SAVE
@findex __bb_init_trace_func
task. Local labels in the assembler code can be concatenated with the
string @var{id}, to obtain a unique label name.
-Registers or condition codes clobbered by @code{FUNCTION_PROLOGUE} or
-@code{FUNCTION_EPILOGUE} must be saved in the macros
+Registers or condition codes clobbered by
+@code{TARGET_ASM_FUNCTION_PROLOGUE} or
+@code{TARGET_ASM_FUNCTION_EPILOGUE} must be saved in the macros
@code{FUNCTION_BLOCK_PROFILER}, @code{FUNCTION_BLOCK_PROFILER_EXIT} and
@code{BLOCK_PROFILER} prior calling @code{__bb_init_trace_func},
@code{__bb_trace_ret} and @code{__bb_trace_func} respectively.
A C statement or compound statement to restore all registers, including
condition codes, saved by @code{MACHINE_STATE_SAVE}.
-Registers or condition codes clobbered by @code{FUNCTION_PROLOGUE} or
-@code{FUNCTION_EPILOGUE} must be restored in the macros
+Registers or condition codes clobbered by
+@code{TARGET_ASM_FUNCTION_PROLOGUE} or
+@code{TARGET_ASM_FUNCTION_EPILOGUE} must be restored in the macros
@code{FUNCTION_BLOCK_PROFILER}, @code{FUNCTION_BLOCK_PROFILER_EXIT} and
@code{BLOCK_PROFILER} after calling @code{__bb_init_trace_func},
@code{__bb_trace_ret} and @code{__bb_trace_func} respectively.
expression value should be an RTX representing a memory reference to the
space for the trampoline.
-@cindex @code{FUNCTION_EPILOGUE} and trampolines
-@cindex @code{FUNCTION_PROLOGUE} and trampolines
+@cindex @code{TARGET_ASM_FUNCTION_EPILOGUE} and trampolines
+@cindex @code{TARGET_ASM_FUNCTION_PROLOGUE} and trampolines
If this macro is not defined, by default the trampoline is allocated as
a stack slot. This default is right for most machines. The exceptions
are machines where it is impossible to execute instructions in the stack
area. On such machines, you may have to implement a separate stack,
-using this macro in conjunction with @code{FUNCTION_PROLOGUE} and
-@code{FUNCTION_EPILOGUE}.
+using this macro in conjunction with @code{TARGET_ASM_FUNCTION_PROLOGUE}
+and @code{TARGET_ASM_FUNCTION_EPILOGUE}.
@var{fp} points to a data structure, a @code{struct function}, which
describes the compilation status of the immediate containing function of
define @code{INCOMING_RETURN_ADDR_RTX} and either set
@code{RTX_FRAME_RELATED_P} on the prologue insns if you use RTL for the
prologue, or call @code{dwarf2out_def_cfa} and @code{dwarf2out_reg_save}
-as appropriate from @code{FUNCTION_PROLOGUE} if you don't.
+as appropriate from @code{TARGET_ASM_FUNCTION_PROLOGUE} if you don't.
@findex DWARF2_FRAME_INFO
@item DWARF2_FRAME_INFO
(the one that tests the condition codes) to be modified.
The code for the function prologue and epilogue are generated
- directly as assembler code by the macros FUNCTION_PROLOGUE and
- FUNCTION_EPILOGUE. Those instructions never exist as rtl. */
+ directly in assembler by the target functions function_prologue and
+ function_epilogue. Those instructions never exist as rtl. */
#include "config.h"
#include "system.h"
#include "reload.h"
#include "intl.h"
#include "basic-block.h"
+#include "target.h"
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
#include "dbxout.h"
}
}
+/* Default target function prologue and epilogue assembler output.
+
+ If not overridden for epilogue code, then the function body itself
+ contains return instructions wherever needed. */
+void
+default_function_pro_epilogue (file, size)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+}
+
/* Enable APP processing of subsequent output.
Used before the output from an `asm' statement. */
TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
}
-#ifdef FUNCTION_PROLOGUE
/* First output the function prologue: code to set up the stack frame. */
- FUNCTION_PROLOGUE (file, get_frame_size ());
-#endif
+ (*target.asm_out.function_prologue) (file, get_frame_size ());
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
xcoffout_end_function (file, high_function_linenum);
#endif
-#ifdef FUNCTION_EPILOGUE
/* Finally, output the function epilogue:
code to restore the stack frame and return to the caller. */
- FUNCTION_EPILOGUE (file, get_frame_size ());
-#endif
+ (*target.asm_out.function_epilogue) (file, get_frame_size ());
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
#endif
bb_func_label_num = -1; /* not in function, nuke label # */
-
- /* If FUNCTION_EPILOGUE is not defined, then the function body
- itself contains return instructions wherever needed. */
}
\f
/* Add a block to the linked list that remembers the current line/file/function
REAL_VALUE_TYPE
real_hex_to_f (s, mode)
- char *s;
+ const char *s;
enum machine_mode mode;
{
REAL_VALUE_TYPE ip;
- char *p = s;
+ const char *p = s;
unsigned HOST_WIDE_INT low, high;
int shcount, nrmcount, k;
int sign, expsign, isfloat;
/* Assign unique numbers to labels generated for profiling. */
extern int profile_label_no;
+
+/* Default target function prologue and epilogue assembler output. */
+extern void default_function_pro_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Hexadecimal floating constant input for use with host computer's
fp arithmetic. */
#ifndef REAL_VALUE_HTOF
-extern REAL_VALUE_TYPE real_hex_to_f PARAMS ((char *, enum machine_mode));
+extern REAL_VALUE_TYPE real_hex_to_f PARAMS ((const char *,
+ enum machine_mode));
#define REAL_VALUE_HTOF(s,m) real_hex_to_f(s,m)
#endif
We want to have non-NULL default definitions of all hook functions,
even if they do nothing. */
+#define TARGET_ASM_FUNCTION_PROLOGUE default_function_pro_epilogue
+#define TARGET_ASM_FUNCTION_EPILOGUE default_function_pro_epilogue
+
+#define TARGET_ASM_OUT {TARGET_ASM_FUNCTION_PROLOGUE, \
+ TARGET_ASM_FUNCTION_EPILOGUE}
+
/* All in tree.c. */
#define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
#define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
/* The whole shebang. */
#define TARGET_INITIALIZER \
{ \
+ TARGET_ASM_OUT, \
TARGET_MERGE_DECL_ATTRIBUTES, \
TARGET_MERGE_TYPE_ATTRIBUTES, \
TARGET_VALID_DECL_ATTRIBUTE, \
struct gcc_target
{
+ /* Functions that output assembler for the target. */
+ struct asm_out
+ {
+ /* Output the assembler code for entry to a function. */
+ void (* function_prologue) PARAMS ((FILE *, HOST_WIDE_INT));
+
+ /* Output the assembler code for function exit. */
+ void (* function_epilogue) PARAMS ((FILE *, HOST_WIDE_INT));
+ } asm_out;
+
/* Given two decls, merge their attributes and return the result. */
tree (* merge_decl_attributes) PARAMS ((tree, tree));