From: Neil Booth Date: Fri, 6 Jul 2001 18:40:17 +0000 (+0000) Subject: Makefile.in (final.o): Depend on target.h. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=08c148a85ce39064798592a90839497c098fbc93;p=gcc.git Makefile.in (final.o): Depend on target.h. * 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 --- diff --git a/gcc/Makefile.in b/gcc/Makefile.in index b6689c64115..84eaf0ca35e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1518,7 +1518,7 @@ final.o : final.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h intl.h \ $(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) diff --git a/gcc/config.in b/gcc/config.in index 53995ba2e4b..e9b10ef750d 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1,4 +1,4 @@ -/* 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 diff --git a/gcc/config/1750a/1750a.c b/gcc/config/1750a/1750a.c index cdeecd29701..39a0ebb0ba7 100644 --- a/gcc/config/1750a/1750a.c +++ b/gcc/config/1750a/1750a.c @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ #include "real.h" #include "regs.h" #include "output.h" +#include "flags.h" #include "tm_p.h" #include "target.h" #include "target-def.h" @@ -46,11 +47,106 @@ const char *const sectname[4] = {"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)); /* 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; +/* 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; diff --git a/gcc/config/1750a/1750a.h b/gcc/config/1750a/1750a.h index c410378f740..26ce2edb277 100644 --- a/gcc/config/1750a/1750a.h +++ b/gcc/config/1750a/1750a.h @@ -550,51 +550,6 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA #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. */ @@ -619,38 +574,6 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA #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. diff --git a/gcc/config/a29k/a29k-protos.h b/gcc/config/a29k/a29k-protos.h index 574021e18ff..a2821e30df3 100644 --- a/gcc/config/a29k/a29k-protos.h +++ b/gcc/config/a29k/a29k-protos.h @@ -60,6 +60,4 @@ extern int uses_local_reg_p PARAMS ((rtx)); 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 */ diff --git a/gcc/config/a29k/a29k.c b/gcc/config/a29k/a29k.c index 3d6e85d52be..67c84efb80a 100644 --- a/gcc/config/a29k/a29k.c +++ b/gcc/config/a29k/a29k.c @@ -46,6 +46,8 @@ static int shift_constant_operand PARAMS ((rtx, enum machine_mode, int)); 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)) @@ -93,6 +95,10 @@ rtx a29k_compare_op0, a29k_compare_op1; int a29k_compare_fp_p; /* 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; @@ -1293,10 +1299,10 @@ a29k_compute_reg_names () /* 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; @@ -1465,10 +1471,10 @@ check_epilogue_internal_label (file) 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 diff --git a/gcc/config/a29k/a29k.h b/gcc/config/a29k/a29k.h index 5cf9906e2ac..f6bfe382778 100644 --- a/gcc/config/a29k/a29k.h +++ b/gcc/config/a29k/a29k.h @@ -935,16 +935,6 @@ extern const char *a29k_function_name; 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. */ @@ -957,18 +947,6 @@ extern const char *a29k_function_name; #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, diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h index b264d632364..fef052b9428 100644 --- a/gcc/config/arc/arc-protos.h +++ b/gcc/config/arc/arc-protos.h @@ -71,8 +71,6 @@ extern void arc_asm_file_start PARAMS ((FILE *)); 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)); diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index c579cd5f9b7..03e77ae1a0d 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -88,8 +88,14 @@ static void record_cc_ref PARAMS ((rtx)); 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)); /* 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 @@ -1087,10 +1093,10 @@ arc_save_restore (file, base_reg, offset, gmask, op) /* 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]; @@ -1165,10 +1171,10 @@ arc_output_function_prologue (file, size) /* 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; diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index 80ad885d806..9695d8ce664 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -834,36 +834,12 @@ arc_setup_incoming_varargs(&ARGS_SO_FAR, MODE, TYPE, &PRETEND_SIZE, NO_RTL) is passed to a function, or 0 to use `invisible' first argument. */ #define STRUCT_VALUE 0 -/* 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 () diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 653d788ded3..70780582022 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -29,7 +29,6 @@ extern int arm_regno_class PARAMS ((int)); 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)); @@ -123,7 +122,6 @@ extern const char * arithmetic_instr PARAMS ((rtx, 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)); @@ -160,7 +158,6 @@ extern void thumb_expand_epilogue PARAMS ((void)); 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 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 24c3317bd30..7d18b71ec6f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -106,6 +106,12 @@ static int arm_valid_type_attribute_p PARAMS ((tree, tree, 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 @@ -130,6 +136,12 @@ static void arm_set_default_type_attributes PARAMS ((tree)); # 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 @@ -7313,12 +7325,18 @@ arm_poke_function_name (stream, name) /* 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) @@ -7637,9 +7655,10 @@ arm_output_epilogue (really_return) 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) { @@ -9892,9 +9911,10 @@ thumb_expand_epilogue () 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; diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index a4dff6dc6cc..59884cdf390 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1532,17 +1532,6 @@ typedef struct (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. */ @@ -1602,10 +1591,6 @@ typedef struct 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. diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 3d99a313b94..9d9839831b3 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -35,8 +35,6 @@ extern int frame_pointer_required_p PARAMS ((void)); 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)); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 7ca4ab78813..f242aa45b2d 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -60,6 +60,8 @@ static int io_address_p PARAMS ((rtx x, int size)); 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 @@ -171,6 +173,10 @@ static const struct mcu_type_s avr_mcu_types[] = { int avr_case_values_threshold = 30000; /* 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 @@ -538,10 +544,10 @@ out_set_stack_ptr (file, before, after) /* 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; @@ -675,10 +681,10 @@ function_prologue (file, size) /* 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; diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 25aeca38548..8d6764e4e05 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -1349,133 +1349,12 @@ extern int avr_reg_order[]; 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. diff --git a/gcc/config/clipper/clipper-protos.h b/gcc/config/clipper/clipper-protos.h index d702165d6b5..bfdb7c7b9da 100644 --- a/gcc/config/clipper/clipper-protos.h +++ b/gcc/config/clipper/clipper-protos.h @@ -33,8 +33,6 @@ extern int fp_reg_operand PARAMS ((rtx, enum machine_mode)); 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 */ diff --git a/gcc/config/clipper/clipper.c b/gcc/config/clipper/clipper.c index 42a5ad7ff38..3adcff7c6a8 100644 --- a/gcc/config/clipper/clipper.c +++ b/gcc/config/clipper/clipper.c @@ -31,15 +31,18 @@ Boston, MA 02111-1307, USA. */ #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; @@ -47,6 +50,10 @@ extern int frame_pointer_needed; static int frame_size; /* 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; @@ -84,10 +91,10 @@ clipper_frame_size (lsize) 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; @@ -138,10 +145,10 @@ output_function_prologue (file, lsize) } } -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; diff --git a/gcc/config/clipper/clipper.h b/gcc/config/clipper/clipper.h index f411fe3c33c..4b439732944 100644 --- a/gcc/config/clipper/clipper.h +++ b/gcc/config/clipper/clipper.h @@ -550,16 +550,6 @@ do \ #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. */ @@ -582,13 +572,6 @@ do \ #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 diff --git a/gcc/config/convex/convex.c b/gcc/config/convex/convex.c index eecf2bd8699..6f563e29edc 100644 --- a/gcc/config/convex/convex.c +++ b/gcc/config/convex/convex.c @@ -64,11 +64,53 @@ static int frame_argblock_size; 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)); /* 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; +/* 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 diff --git a/gcc/config/convex/convex.h b/gcc/config/convex/convex.h index beed9a3feb2..10f8cb95794 100644 --- a/gcc/config/convex/convex.h +++ b/gcc/config/convex/convex.h @@ -818,32 +818,6 @@ enum reg_class { #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. */ diff --git a/gcc/config/d30v/d30v-protos.h b/gcc/config/d30v/d30v-protos.h index c395ef7cfff..f681a40fd8b 100644 --- a/gcc/config/d30v/d30v-protos.h +++ b/gcc/config/d30v/d30v-protos.h @@ -110,9 +110,7 @@ extern rtx d30v_expand_builtin_va_arg PARAMS ((tree, tree)); #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 diff --git a/gcc/config/d30v/d30v.c b/gcc/config/d30v/d30v.c index c63dd528c1c..e73cad011ff 100644 --- a/gcc/config/d30v/d30v.c +++ b/gcc/config/d30v/d30v.c @@ -49,6 +49,8 @@ static void d30v_add_gc_roots PARAMS ((void)); 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. */ @@ -80,6 +82,10 @@ enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; enum reg_class reg_class_from_letter[256]; /* 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; @@ -2321,96 +2327,32 @@ d30v_expand_builtin_va_arg(valist, type) return ptr_rtx; } +/* 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. */ } -/* 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 () @@ -2492,60 +2434,33 @@ d30v_expand_prologue () } -/* 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 */ } -/* 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 () diff --git a/gcc/config/d30v/d30v.h b/gcc/config/d30v/d30v.h index 2b08b117c89..3565cc71a4c 100644 --- a/gcc/config/d30v/d30v.h +++ b/gcc/config/d30v/d30v.h @@ -2656,93 +2656,6 @@ typedef int CUMULATIVE_ARGS; /* #define CALLER_SAVE_PROFITABLE(REFS, CALLS) */ -/* 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 @@ -2751,44 +2664,6 @@ typedef int CUMULATIVE_ARGS; 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 @@ -2809,8 +2684,8 @@ typedef int CUMULATIVE_ARGS; 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 @@ -2833,10 +2708,10 @@ typedef int CUMULATIVE_ARGS; 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 @@ -2975,8 +2850,8 @@ typedef struct machine_function 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) */ @@ -2987,17 +2862,18 @@ typedef struct machine_function 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. */ @@ -3131,7 +3007,8 @@ typedef struct machine_function 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 @@ -5399,8 +5276,8 @@ fprintf (STREAM, "\t.word .L%d\n", VALUE) 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 */ diff --git a/gcc/config/d30v/d30v.md b/gcc/config/d30v/d30v.md index 5892a1aff8f..4f62f3c64d4 100644 --- a/gcc/config/d30v/d30v.md +++ b/gcc/config/d30v/d30v.md @@ -2934,7 +2934,7 @@ ;; 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. @@ -2950,7 +2950,7 @@ ;; 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. diff --git a/gcc/config/dsp16xx/dsp16xx-protos.h b/gcc/config/dsp16xx/dsp16xx-protos.h index 3d540a62054..6401f70ee49 100644 --- a/gcc/config/dsp16xx/dsp16xx-protos.h +++ b/gcc/config/dsp16xx/dsp16xx-protos.h @@ -81,5 +81,3 @@ extern struct rtx_def *(*dsp16xx_compare_gen) PARAMS (()); 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)); diff --git a/gcc/config/dsp16xx/dsp16xx.c b/gcc/config/dsp16xx/dsp16xx.c index 2a333ea06d6..f20754fc945 100644 --- a/gcc/config/dsp16xx/dsp16xx.c +++ b/gcc/config/dsp16xx/dsp16xx.c @@ -58,7 +58,6 @@ const char *save_chip_name; rtx dsp16xx_compare_op0; rtx dsp16xx_compare_op1; -struct rtx_def *(*dsp16xx_compare_gen)(); static const char *fp; static const char *sp; @@ -147,8 +146,14 @@ static const char *const lshift_right_asm_first[] = }; 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)); /* 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; @@ -1176,10 +1181,10 @@ ybase_regs_ever_used () 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; @@ -1294,10 +1299,11 @@ init_emulation_routines () 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 @@ -1669,7 +1675,7 @@ print_operand(file, op, letter) 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)); @@ -1682,7 +1688,7 @@ print_operand(file, op, letter) 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); } diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h index d5aa7c68b45..15bd722fd4c 100644 --- a/gcc/config/dsp16xx/dsp16xx.h +++ b/gcc/config/dsp16xx/dsp16xx.h @@ -1162,16 +1162,6 @@ extern struct dsp16xx_frame_info current_frame_info; #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. */ @@ -1211,18 +1201,6 @@ extern struct dsp16xx_frame_info current_frame_info; #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. */ diff --git a/gcc/config/elxsi/elxsi.c b/gcc/config/elxsi/elxsi.c index 41b33631efa..0939bd1f36b 100644 --- a/gcc/config/elxsi/elxsi.c +++ b/gcc/config/elxsi/elxsi.c @@ -37,11 +37,104 @@ rtx cmp_op0=0, cmp_op1=0; 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)); /* 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; +/* 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 * diff --git a/gcc/config/elxsi/elxsi.h b/gcc/config/elxsi/elxsi.h index 332172c361b..fb2885d1165 100644 --- a/gcc/config/elxsi/elxsi.h +++ b/gcc/config/elxsi/elxsi.h @@ -390,35 +390,6 @@ enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES }; #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. */ @@ -432,37 +403,6 @@ enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES }; #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. diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c index 8fcad88314a..3086334b0c7 100644 --- a/gcc/config/fr30/fr30.c +++ b/gcc/config/fr30/fr30.c @@ -204,7 +204,7 @@ fr30_compute_frame_size (from_reg, to_reg) /* 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. */ @@ -333,7 +333,7 @@ fr30_expand_prologue () /* 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. */ diff --git a/gcc/config/fr30/fr30.md b/gcc/config/fr30/fr30.md index d7e6115daa2..bf3ae73a667 100644 --- a/gcc/config/fr30/fr30.md +++ b/gcc/config/fr30/fr30.md @@ -1358,7 +1358,7 @@ ;; 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. @@ -1373,7 +1373,7 @@ ;; 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. diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 0c3aa2967e4..9b0fa0297ec 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -68,8 +68,6 @@ extern void h8300_encode_label PARAMS ((tree)); #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)); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index d46af431b1f..5fa079fda41 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -54,6 +54,8 @@ static void push PARAMS ((FILE *, 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; @@ -98,6 +100,11 @@ const char *h8_push_op, *h8_pop_op, *h8_mov_op; #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; /* Initialize various cpu specific globals at start up. */ @@ -271,10 +278,10 @@ pop (file, rn) /* 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; @@ -382,10 +389,10 @@ function_prologue (file, size) /* 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; diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index 47450e51d46..1df7c08a65e 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -664,11 +664,6 @@ struct cum_arg #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. */ @@ -710,14 +705,6 @@ struct cum_arg #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. diff --git a/gcc/config/i370/i370-protos.h b/gcc/config/i370/i370-protos.h index eff85464438..8ca7ca64085 100644 --- a/gcc/config/i370/i370-protos.h +++ b/gcc/config/i370/i370-protos.h @@ -46,7 +46,6 @@ extern void mvs_add_alias PARAMS ((const char *, const char *, int)); 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)); diff --git a/gcc/config/i370/i370.c b/gcc/config/i370/i370.c index ebd1d85ef3a..43b5929805c 100644 --- a/gcc/config/i370/i370.c +++ b/gcc/config/i370/i370.c @@ -100,6 +100,8 @@ static FILE *assembler_source = 0; 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 */ @@ -287,6 +289,10 @@ static const unsigned char ebcasc[256] = }; /* 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; @@ -1195,13 +1201,21 @@ unsigned_jump_follows_p (insn) } } +/* 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); @@ -1388,10 +1402,10 @@ i370_function_prolog (f, l) 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; @@ -1461,3 +1475,47 @@ i370_function_prolog (f, frame_size) 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); +} diff --git a/gcc/config/i370/i370.h b/gcc/config/i370/i370.h index 71e95c44dd1..fa187f33afd 100644 --- a/gcc/config/i370/i370.h +++ b/gcc/config/i370/i370.h @@ -1590,10 +1590,6 @@ enum reg_class } \ } -/* 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) \ @@ -1618,62 +1614,6 @@ enum reg_class 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. */ @@ -1951,40 +1891,6 @@ abort(); \ } \ } -/* 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 */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 58350e21596..bb337a2537c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -624,6 +624,13 @@ static int ix86_comp_type_attributes PARAMS ((tree, tree)); #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; /* Sometimes certain combinations of command options do not make @@ -931,6 +938,105 @@ ix86_valid_type_attribute_p (type, attributes, identifier, args) 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). */ diff --git a/gcc/config/i386/osf1elf.h b/gcc/config/i386/osf1elf.h index 5aee6fa1926..4c5238990e9 100644 --- a/gcc/config/i386/osf1elf.h +++ b/gcc/config/i386/osf1elf.h @@ -8,6 +8,8 @@ #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 @@ -133,41 +135,6 @@ #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 diff --git a/gcc/config/i386/osfrose.h b/gcc/config/i386/osfrose.h index 3385d7a5c17..7d74f7ac1bc 100644 --- a/gcc/config/i386/osfrose.h +++ b/gcc/config/i386/osfrose.h @@ -183,18 +183,6 @@ Boston, MA 02111-1307, USA. */ #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 \ @@ -203,56 +191,6 @@ Boston, MA 02111-1307, USA. */ || (!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' diff --git a/gcc/config/i860/i860-protos.h b/gcc/config/i860/i860-protos.h index ac91f43c8c0..42cbe184fae 100644 --- a/gcc/config/i860/i860-protos.h +++ b/gcc/config/i860/i860-protos.h @@ -59,6 +59,3 @@ extern rtx i860_va_arg PARAMS ((tree, tree)); #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)); diff --git a/gcc/config/i860/i860.c b/gcc/config/i860/i860.c index fd04a3a30ab..ae72157e774 100644 --- a/gcc/config/i860/i860.c +++ b/gcc/config/i860/i860.c @@ -51,6 +51,8 @@ static const char *singlemove_string PARAMS ((rtx *)); 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 "" @@ -63,6 +65,10 @@ const char *i860_reg_prefix = I860_REG_PREFIX; rtx i860_compare_op0, i860_compare_op1; /* 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; @@ -1557,7 +1563,6 @@ sfmode_constant_to_ulong (x) } /* 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. @@ -1663,14 +1668,14 @@ char *current_function_original_name; 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; @@ -1929,7 +1934,6 @@ function_prologue (asm_file, local_bytes) } /* 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. @@ -1985,14 +1989,14 @@ typedef struct TDESC { 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; diff --git a/gcc/config/i860/i860.h b/gcc/config/i860/i860.h index 510a863b033..1f681314374 100644 --- a/gcc/config/i860/i860.h +++ b/gcc/config/i860/i860.h @@ -557,14 +557,6 @@ struct cumulative_args { int ints, floats; }; ? 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. */ @@ -584,19 +576,6 @@ struct cumulative_args { int ints, floats; }; #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() diff --git a/gcc/config/i960/i960-protos.h b/gcc/config/i960/i960-protos.h index 99667436bc7..483c15bb417 100644 --- a/gcc/config/i960/i960-protos.h +++ b/gcc/config/i960/i960-protos.h @@ -101,9 +101,7 @@ extern int bitpos PARAMS ((unsigned int)); 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 diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c index 663539b9ecc..264f7ee439f 100644 --- a/gcc/config/i960/i960.c +++ b/gcc/config/i960/i960.c @@ -47,6 +47,9 @@ Boston, MA 02111-1307, USA. */ #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. */ @@ -90,6 +93,10 @@ static int ret_label = 0; || current_function_varargs) /* 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; @@ -1261,16 +1268,16 @@ i960_split_reg_group (reg_groups, nw, subgroup_length) /* 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]; @@ -1539,10 +1546,10 @@ output_function_profiler (file, labelno) /* 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) { diff --git a/gcc/config/i960/i960.h b/gcc/config/i960/i960.h index 8a1d0beed50..3a11007a04e 100644 --- a/gcc/config/i960/i960.h +++ b/gcc/config/i960/i960.h @@ -997,16 +997,6 @@ struct cum_args { int ca_nregparms; int ca_nstackparms; }; #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. */ @@ -1019,18 +1009,6 @@ struct cum_args { int ca_nregparms; int ca_nstackparms; }; 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) /* Addressing modes, and classification of registers for them. */ diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index f0bae81e5cf..1bdfbc4cee1 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -77,8 +77,6 @@ extern void ia64_expand_call PARAMS((rtx, rtx, rtx, int)); 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)); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 11a21a52290..296306b1f82 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -137,11 +137,18 @@ static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode, 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)); /* 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; /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ @@ -1830,7 +1837,7 @@ gen_fr_restore_x (dest, src, offset) /* 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. @@ -2188,7 +2195,7 @@ ia64_expand_prologue () /* 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. */ @@ -2496,10 +2503,10 @@ ia64_hard_regno_rename_ok (from, to) /* 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; @@ -2577,10 +2584,10 @@ ia64_output_end_prologue (file) /* 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; diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 5a89629fa49..05b8f9eba21 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1458,12 +1458,6 @@ do { \ /* 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) @@ -1480,12 +1474,6 @@ do { \ #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) \ diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index a73b312158d..f0a1a5bed0a 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -29,8 +29,6 @@ extern void m32r_init_expanders PARAMS ((void)); 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)); diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index ca213af8e26..12dad0d3171 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -64,11 +64,18 @@ static void block_move_call PARAMS ((rtx, rtx, rtx)); 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)); /* 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; /* Called by OVERRIDE_OPTIONS to initialize various things. */ @@ -1962,10 +1969,10 @@ m32r_expand_prologue () 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); @@ -1992,10 +1999,10 @@ m32r_output_function_prologue (file, size) /* 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; diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index dfe4f289da7..69efdb7d50c 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -1190,34 +1190,12 @@ M32R_STACK_ALIGN (current_function_outgoing_args_size) 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 () diff --git a/gcc/config/m68hc11/m68hc11-protos.h b/gcc/config/m68hc11/m68hc11-protos.h index b31770b9c77..af265e88920 100644 --- a/gcc/config/m68hc11/m68hc11-protos.h +++ b/gcc/config/m68hc11/m68hc11-protos.h @@ -30,8 +30,6 @@ extern int m68hc11_initial_elimination_offset PARAMS((int, int)); 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)); diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index e7dc1dfe16d..a05eae51843 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -70,8 +70,10 @@ static int m68hc11_valid_type_attribute_p PARAMS((tree, tree, 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; @@ -202,14 +204,15 @@ const char *m68hc11_regparm_string; 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; /* 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; int @@ -1529,10 +1532,10 @@ m68hc11_total_frame_size () 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. */ diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h index 25472c22405..5f5982638a3 100644 --- a/gcc/config/m68hc11/m68hc11.h +++ b/gcc/config/m68hc11/m68hc11.h @@ -1092,8 +1092,6 @@ typedef struct m68hc11_args #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. diff --git a/gcc/config/m68k/crds.h b/gcc/config/m68k/crds.h index 12f0fb797bc..b2442d48770 100644 --- a/gcc/config/m68k/crds.h +++ b/gcc/config/m68k/crds.h @@ -459,160 +459,8 @@ do { int i; \ (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"); } - diff --git a/gcc/config/m68k/dpx2.h b/gcc/config/m68k/dpx2.h index 0b45c8273ef..886a34b2f7a 100644 --- a/gcc/config/m68k/dpx2.h +++ b/gcc/config/m68k/dpx2.h @@ -31,6 +31,8 @@ Boston, MA 02111-1307, USA. */ #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. @@ -238,269 +240,6 @@ Boston, MA 02111-1307, USA. */ /* 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'. diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h index b73c628a9ff..6a132beeb62 100644 --- a/gcc/config/m68k/m68k-protos.h +++ b/gcc/config/m68k/m68k-protos.h @@ -65,8 +65,6 @@ extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx)); #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)); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 8eaee6ec424..5df64bf1503 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -56,6 +56,8 @@ int switch_table_difference_label_flag; 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)); /* Alignment to use for loops and jumps */ @@ -79,6 +81,10 @@ int m68k_align_funcs; int m68k_last_compare_had_fp_operands; /* 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; @@ -146,18 +152,236 @@ override_options () /* 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. */ @@ -385,11 +609,7 @@ output_function_prologue (stream, size) #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 @@ -515,6 +735,9 @@ output_function_prologue (stream, size) #endif } } +#endif /* ! (DPX2 && MOTOROLA) */ +#endif /* ! (NEWS && MOTOROLA) */ +#endif /* !CRDS */ /* Return true if this function's epilogue can be output as RTL. */ @@ -540,24 +763,406 @@ use_return_insn () } /* 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; @@ -875,6 +1480,10 @@ output_function_epilogue (stream, size) else fprintf (stream, "\trts\n"); } + +#endif /* ! (DPX2 && MOTOROLA) */ +#endif /* ! (NEWS && MOTOROLA) */ +#endif /* !CRDS */ /* Similar to general_operand, but exclude stack_pointer_rtx. */ diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 133e16ff297..68017af17de 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -1050,9 +1050,6 @@ extern enum reg_class regno_reg_class[]; : 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. */ @@ -1228,9 +1225,6 @@ while(0) #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) */ diff --git a/gcc/config/m68k/news.h b/gcc/config/m68k/news.h index 25e820e772b..96ce23c53f1 100644 --- a/gcc/config/m68k/news.h +++ b/gcc/config/m68k/news.h @@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */ #define SGS_NO_LI /* Suppress jump table label usage */ #endif +#define NEWS #define NO_DOLLAR_IN_LABEL #define NO_DOT_IN_LABEL @@ -98,8 +99,6 @@ Boston, MA 02111-1307, USA. */ #undef FUNCTION_PROFILER #ifdef MOTOROLA -#undef FUNCTION_PROLOGUE -#undef FUNCTION_EPILOGUE #undef REGISTER_NAMES #undef ASM_OUTPUT_REG_PUSH #undef ASM_OUTPUT_REG_POP @@ -139,111 +138,9 @@ Boston, MA 02111-1307, USA. */ #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 \ diff --git a/gcc/config/m88k/m88k-protos.h b/gcc/config/m88k/m88k-protos.h index 2812b20060a..a8204a37dec 100644 --- a/gcc/config/m88k/m88k-protos.h +++ b/gcc/config/m88k/m88k-protos.h @@ -84,16 +84,14 @@ extern int null_prologue PARAMS ((void)); 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)); diff --git a/gcc/config/m88k/m88k.c b/gcc/config/m88k/m88k.c index 86332bfad3f..3cb88902c5e 100644 --- a/gcc/config/m88k/m88k.c +++ b/gcc/config/m88k/m88k.c @@ -62,8 +62,15 @@ rtx m88k_compare_op0; /* cmpsi operand 0 */ 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)); /* 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; @@ -1611,7 +1618,7 @@ output_ascii (file, opcode, max, p, size) FILE *file; const char *opcode; int max; - const unsigned char *p; + const char *p; int size; { int i; @@ -1622,7 +1629,7 @@ output_ascii (file, opcode, max, p, size) 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) { @@ -1781,7 +1788,8 @@ static int prologue_marked; (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1)) /* 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 () @@ -1935,10 +1943,10 @@ uses_arg_area_p () return 0; } -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, "$"); @@ -2016,7 +2024,7 @@ m88k_expand_prologue () } /* 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. @@ -2034,10 +2042,10 @@ m88k_begin_epilogue (stream) 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 (); diff --git a/gcc/config/m88k/m88k.h b/gcc/config/m88k/m88k.h index 73015c16734..3af1c291a6d 100644 --- a/gcc/config/m88k/m88k.h +++ b/gcc/config/m88k/m88k.h @@ -86,7 +86,7 @@ enum m88k_instruction { enum processor_type { PROCESSOR_M88100, PROCESSOR_M88110, - PROCESSOR_M88000, + PROCESSOR_M88000 }; /* Recast the cpu class to be the cpu attribute. */ @@ -1046,9 +1046,6 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS, #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) @@ -1083,9 +1080,6 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS, 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) diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 81e15a1f272..21abf47fc82 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -27,8 +27,6 @@ Boston, MA 02111-1307, USA. */ #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)); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index f2805e2d00e..94308af3a40 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -107,6 +107,8 @@ static void abort_with_insn PARAMS ((rtx, const char *)) 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. */ @@ -439,6 +441,10 @@ enum reg_class mips_char_to_class[256] = }; /* 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; @@ -6846,8 +6852,8 @@ save_restore_insns (store_p, large_reg, large_offset, file) /* 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; { @@ -7437,12 +7443,12 @@ mips_expand_prologue () #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 diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 453396e207f..134b546b7ce 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2584,23 +2584,6 @@ typedef struct mips_args { : 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. - 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) \ diff --git a/gcc/config/ns32k/merlin.h b/gcc/config/ns32k/merlin.h index 411c25107d8..a3b41baf260 100644 --- a/gcc/config/ns32k/merlin.h +++ b/gcc/config/ns32k/merlin.h @@ -26,6 +26,8 @@ Boston, MA 02111-1307, USA. */ #include "ns32k/ns32k.h" +#define MERLIN_TARGET + /* This is BSD, so it wants DBX format. */ #define DBX_DEBUGGING_INFO @@ -123,108 +125,6 @@ Boston, MA 02111-1307, USA. */ 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 diff --git a/gcc/config/ns32k/ns32k.c b/gcc/config/ns32k/ns32k.c index 6dc89b16878..ca84f6e3feb 100644 --- a/gcc/config/ns32k/ns32k.c +++ b/gcc/config/ns32k/ns32k.c @@ -65,13 +65,393 @@ static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx)); 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)); /* 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; +/* 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 [], + * + * 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 + * + * # Save any general purpose registers necessary + * + * 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 [] + + 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 [] + + # 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) diff --git a/gcc/config/ns32k/ns32k.h b/gcc/config/ns32k/ns32k.h index 3adc9bbd1b7..778644c5a41 100644 --- a/gcc/config/ns32k/ns32k.h +++ b/gcc/config/ns32k/ns32k.h @@ -678,119 +678,6 @@ enum reg_class : 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 [], - * - * 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 - * - * # Save any general purpose registers necessary - * - * 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. @@ -804,101 +691,11 @@ enum reg_class 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 [] - - 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 [] - - # 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 diff --git a/gcc/config/ns32k/tek6000.h b/gcc/config/ns32k/tek6000.h index 1565ae863be..219d9198903 100644 --- a/gcc/config/ns32k/tek6000.h +++ b/gcc/config/ns32k/tek6000.h @@ -112,107 +112,6 @@ Boston, MA 02111-1307, USA. */ #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 diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 4f15aa72367..6446f5b2a23 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -132,8 +132,6 @@ extern struct rtx_def *hppa_builtin_saveregs PARAMS ((void)); 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)); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 59aaf6165eb..04233835cde 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -68,6 +68,8 @@ static void remove_useless_addtr_insns PARAMS ((rtx, 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. */ @@ -109,6 +111,10 @@ struct deferred_plabel int n_deferred_plabels = 0; /* 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; @@ -2778,7 +2784,7 @@ remove_useless_addtr_insns (insns, check_notes) */ -/* 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; @@ -2893,10 +2899,27 @@ compute_frame_size (size, fregs_live) 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 @@ -3213,10 +3236,18 @@ load_reg (reg, disp, base) 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 (); diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index d006fbeb20e..380b6d2b7d4 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -887,25 +887,6 @@ extern enum cmp_type hppa_branch_type; 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. */ @@ -925,20 +906,6 @@ extern int may_call_alloca; (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.\ diff --git a/gcc/config/pdp11/2bsd.h b/gcc/config/pdp11/2bsd.h index 117992a82f2..1994d803a5b 100644 --- a/gcc/config/pdp11/2bsd.h +++ b/gcc/config/pdp11/2bsd.h @@ -19,18 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to 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 @@ -40,19 +29,6 @@ if ((SIZE) != 0) \ #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) \ { \ diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h index ddac12d478d..e2031c3ab81 100644 --- a/gcc/config/pdp11/pdp11-protos.h +++ b/gcc/config/pdp11/pdp11-protos.h @@ -40,6 +40,4 @@ extern int comparison_operator_index PARAMS ((rtx)); #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)); diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index a06f17faf43..2fdf0b05796 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -52,8 +52,14 @@ int current_first_parm_offset; 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)); /* 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; @@ -102,23 +108,43 @@ expand_shift_operand (op, mode) 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"); } @@ -176,6 +202,8 @@ output_function_prologue(stream, size) 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 @@ -195,13 +223,25 @@ output_function_prologue(stream, size) 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; @@ -299,6 +339,8 @@ output_function_epilogue(stream, size) 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. */ diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h index 58ce77ff6b3..f931b45da49 100644 --- a/gcc/config/pdp11/pdp11.h +++ b/gcc/config/pdp11/pdp11.h @@ -649,10 +649,6 @@ maybe ac0 ? - as option someday! */ #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. */ @@ -668,15 +664,6 @@ extern int may_call_alloca; #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; \ diff --git a/gcc/config/romp/romp-protos.h b/gcc/config/romp/romp-protos.h index b9f1069720d..fcf2439a54c 100644 --- a/gcc/config/romp/romp-protos.h +++ b/gcc/config/romp/romp-protos.h @@ -55,9 +55,7 @@ extern int romp_using_r14 PARAMS ((void)); 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)); diff --git a/gcc/config/romp/romp.c b/gcc/config/romp/romp.c index aec840ca44c..3fd24b5387f 100644 --- a/gcc/config/romp/romp.c +++ b/gcc/config/romp/romp.c @@ -50,8 +50,14 @@ static void output_fpops PARAMS ((FILE *)); 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)); /* 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; @@ -1078,14 +1084,14 @@ romp_pushes_stack () 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 (); @@ -1133,7 +1139,7 @@ output_prolog (file, size) } /* 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: @@ -1188,17 +1194,17 @@ output_encoded_offset (file, reg_offset) /* 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; diff --git a/gcc/config/romp/romp.h b/gcc/config/romp/romp.h index ce9fcd7de8c..3c82c6545ef 100644 --- a/gcc/config/romp/romp.h +++ b/gcc/config/romp/romp.h @@ -719,16 +719,6 @@ struct rt_cargs {int gregs, fregs; }; #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. */ @@ -740,18 +730,6 @@ struct rt_cargs {int gregs, fregs; }; 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) /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 41124437121..66547b10ba0 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -158,8 +158,6 @@ extern union tree_node *rs6000_build_va_list PARAMS ((void)); 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 *)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 2f35583bb34..9c77e7a3590 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -126,6 +126,8 @@ static void rs6000_free_machine_status PARAMS ((struct function *)); 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)); /* Default register names. */ char rs6000_reg_names[][8] = @@ -168,6 +170,11 @@ static char alt_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; /* Override command line options. Mostly we process the processor @@ -6175,10 +6182,10 @@ rs6000_emit_prologue () /* 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 (); @@ -6532,10 +6539,10 @@ rs6000_emit_epilogue (sibcall) /* 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 (); @@ -6793,8 +6800,8 @@ output_epilog (file, size) 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 diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 1a569045255..eca6be15fc7 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1551,16 +1551,6 @@ typedef struct rs6000_args 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. */ @@ -1585,18 +1575,6 @@ typedef struct rs6000_args || (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) /* TRAMPOLINE_TEMPLATE deleted */ diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index c9a78640599..9500e72025c 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -694,9 +694,10 @@ extern int rs6000_pic_labelno; 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 diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 2296e414bd8..5cfec06a911 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -116,7 +116,6 @@ extern void output_file_start PARAMS ((FILE *)); 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)); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index c36d13c69b2..63c0f166a70 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -154,11 +154,15 @@ static void mark_use PARAMS ((rtx, rtx *)); 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)); /* 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; /* Print the operand address in x to the stream. */ @@ -4194,10 +4198,10 @@ sh_need_epilogue () /* 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; diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 0b36079560d..8c34084e1fd 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1217,11 +1217,6 @@ extern int current_function_anonymous_args; #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 diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 523be16cc95..b941aa95da0 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -53,10 +53,6 @@ extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree)); 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)); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 05fff2b35b2..ad63e331035 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -156,6 +156,14 @@ static void ultra_flush_pipeline PARAMS ((void)); 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)); /* Option handling. */ @@ -179,6 +187,10 @@ struct sparc_cpu_select sparc_select[] = enum processor_type sparc_cpu; /* 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; @@ -3388,12 +3400,40 @@ sparc_output_scratch_registers (file) #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); @@ -3555,12 +3595,32 @@ output_restore_regs (file, leaf_function) 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; @@ -6571,10 +6631,10 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, /* 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; @@ -6688,9 +6748,9 @@ sparc_flat_output_function_prologue (file, size) /* 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) { @@ -6756,10 +6816,10 @@ sparc_flat_output_function_prologue (file, size) /* 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; @@ -6791,8 +6851,8 @@ sparc_flat_output_function_epilogue (file, size) 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"; diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index ac0bcb0415a..e413964e6a2 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -435,7 +435,7 @@ extern int target_flags; #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) @@ -584,9 +584,9 @@ extern int target_flags; 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, \ @@ -1929,26 +1929,6 @@ do { \ } 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)) /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. */ @@ -2128,21 +2108,6 @@ LFLGRET"ID":\n\ (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) \ diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index 43d6a9cc7bd..50d9f708b2a 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -30,17 +30,88 @@ Boston, MA 02111-1307, USA. */ #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)); /* 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; +/* 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 @@ -665,7 +736,7 @@ check_float_value (mode, d, overflow) return 0; } -#ifdef VMS_TARGET +#if VMS_TARGET /* Additional support code for VMS target. */ /* Linked list of all externals that are to be emitted when optimizing diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index 4cbb1041eb2..fb461a90c42 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -19,6 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to 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. */ @@ -452,31 +453,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; #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. */ @@ -510,13 +486,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; #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 diff --git a/gcc/config/vax/vms.h b/gcc/config/vax/vms.h index 3c0bec37370..ccc1715dcd4 100644 --- a/gcc/config/vax/vms.h +++ b/gcc/config/vax/vms.h @@ -18,8 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to 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" @@ -32,12 +30,14 @@ Boston, MA 02111-1307, USA. */ #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 @@ -80,37 +80,6 @@ Boston, MA 02111-1307, USA. */ #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) diff --git a/gcc/config/we32k/we32k.c b/gcc/config/we32k/we32k.c index 9fad7d6b33d..1a4fe881735 100644 --- a/gcc/config/we32k/we32k.c +++ b/gcc/config/we32k/we32k.c @@ -29,14 +29,76 @@ Boston, MA 02111-1307, USA. */ #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)); /* 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; +/* 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; diff --git a/gcc/config/we32k/we32k.h b/gcc/config/we32k/we32k.h index e448cabe36f..8a94790ccca 100644 --- a/gcc/config/we32k/we32k.h +++ b/gcc/config/we32k/we32k.h @@ -396,26 +396,6 @@ enum reg_class { NO_REGS, GENERAL_REGS, #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. */ @@ -442,26 +422,6 @@ enum reg_class { NO_REGS, GENERAL_REGS, #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 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index ad9e29cf71c..71b5a91666c 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2004,13 +2004,14 @@ this. @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 @@ -2772,7 +2773,8 @@ the stack, if the @option{-fstack-check} is specified, in one of three ways: 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 @@ -3696,10 +3698,8 @@ will select the smallest suitable mode. 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 @@ -3714,7 +3714,7 @@ To determine which registers to save, the macro can refer to the array @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 @@ -3741,6 +3741,57 @@ 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. +@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 @@ -3776,9 +3827,11 @@ Optionally, when @code{ACCUMULATE_OUTGOING_ARGS} is defined, a region of 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 @@ -3798,53 +3851,6 @@ Define this macro as a C expression that is nonzero for registers that are 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 @@ -3872,8 +3878,9 @@ The insns accepted to fill the epilogue delay slots are put in an RTL 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}. @@ -3900,8 +3907,8 @@ return to whoever called the current @samp{thunk}. 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 @@ -4076,15 +4083,15 @@ call __bb_trace_func @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 @@ -4097,8 +4104,9 @@ be clobbered by a function call, including condition codes. The 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. @@ -4111,8 +4119,9 @@ Registers or condition codes clobbered by @code{FUNCTION_PROLOGUE} or 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. @@ -4412,14 +4421,14 @@ A C expression to allocate run-time space for a trampoline. The 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 @@ -7565,7 +7574,7 @@ To support optional call frame debugging information, you must also 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 diff --git a/gcc/final.c b/gcc/final.c index b1d2051c1cd..f40492b8da0 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -41,8 +41,8 @@ Boston, MA 02111-1307, USA. */ (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" @@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */ #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" @@ -534,6 +535,17 @@ end_final (filename) } } +/* 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. */ @@ -1617,10 +1629,8 @@ final_start_function (first, file, optimize) 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. */ @@ -1761,11 +1771,9 @@ final_end_function (first, file, optimize) 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) @@ -1788,9 +1796,6 @@ final_end_function (first, file, optimize) #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. */ } /* Add a block to the linked list that remembers the current line/file/function diff --git a/gcc/fold-const.c b/gcc/fold-const.c index eec059e361e..ce96f113860 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1051,11 +1051,11 @@ fail: 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; diff --git a/gcc/output.h b/gcc/output.h index c8fa63c32a8..a1d5923411d 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -448,3 +448,6 @@ extern const char *user_label_prefix; /* 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)); diff --git a/gcc/real.h b/gcc/real.h index 8f58585453b..3a19864979c 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -392,7 +392,8 @@ extern double (atof) (); /* 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 diff --git a/gcc/target-def.h b/gcc/target-def.h index 35c2ce8f5bb..c0894936f66 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -25,6 +25,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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 @@ -36,6 +42,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* The whole shebang. */ #define TARGET_INITIALIZER \ { \ + TARGET_ASM_OUT, \ TARGET_MERGE_DECL_ATTRIBUTES, \ TARGET_MERGE_TYPE_ATTRIBUTES, \ TARGET_VALID_DECL_ATTRIBUTE, \ diff --git a/gcc/target.h b/gcc/target.h index efdb5846ac1..9515aff31db 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -46,6 +46,16 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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));