From 8f260b977468d4d3ddbaf97b1bea89a31cd1b68f Mon Sep 17 00:00:00 2001 From: kazu Date: Sat, 4 Jan 2003 17:46:24 +0000 Subject: [PATCH] * config/h8300/h8300-protos.h: Add prototypes for the new functions defined below. * config/h8300/h8300.c (TARGET_ASM_FUNCTION_PROLOGUE): Do not define. (dosize): Emit RTL instead of assembly code. (push): Likewise. (pop): Likewise. (h8300_output_function_prologue): Remove. (h8300_expand_prologue): New. (h8300_expand_epilogue): New. (h8300_output_function_epilogue): Do only the reset of pragma_saveall. * config/h8300/h8300.md (push_h8300): New. (push_h8300hs): Likewise. (pop_h8300): Likewise. (pop_h8300hs): Likewise. (*stm_h8300s_2): Change the name to stm_h8300s_2. (*stm_h8300s_3): Change the name to stm_h8300s_3. (*stm_h8300s_4): Change the name to stm_h8300s_4. (*ldm_h8300s_2): New. (*ldm_h8300s_3): Likewise. (*ldm_h8300s_4): Likewise. (return): Likewise. (*return_1): Likewise. (prologue): Likewise. (epilogue): Likewise. (monitor_prologue): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60882 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 30 +++++ gcc/config/h8300/h8300-protos.h | 3 + gcc/config/h8300/h8300.c | 253 ++++++++++++++++------------------------ gcc/config/h8300/h8300.md | 135 ++++++++++++++++++++- 4 files changed, 262 insertions(+), 159 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 70c15568c74..f5ee6e68c99 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2003-01-04 Kazu Hirata + + * config/h8300/h8300-protos.h: Add prototypes for + the new functions defined below. + * config/h8300/h8300.c (TARGET_ASM_FUNCTION_PROLOGUE): Do not + define. + (dosize): Emit RTL instead of assembly code. + (push): Likewise. + (pop): Likewise. + (h8300_output_function_prologue): Remove. + (h8300_expand_prologue): New. + (h8300_expand_epilogue): New. + (h8300_output_function_epilogue): Do only the reset of + pragma_saveall. + * config/h8300/h8300.md (push_h8300): New. + (push_h8300hs): Likewise. + (pop_h8300): Likewise. + (pop_h8300hs): Likewise. + (*stm_h8300s_2): Change the name to stm_h8300s_2. + (*stm_h8300s_3): Change the name to stm_h8300s_3. + (*stm_h8300s_4): Change the name to stm_h8300s_4. + (*ldm_h8300s_2): New. + (*ldm_h8300s_3): Likewise. + (*ldm_h8300s_4): Likewise. + (return): Likewise. + (*return_1): Likewise. + (prologue): Likewise. + (epilogue): Likewise. + (monitor_prologue): Likewise. + 2003-01-03 Dale Johannesen * config/darwin.h: (EXTRA_SECTIONS): Add machopic_symbol_stub1, diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 1ea1ab2664a..f5a59d4b120 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -90,6 +90,9 @@ extern int h8300_tiny_data_p PARAMS ((tree)); #endif /* TREE_CODE */ extern void h8300_init_once PARAMS ((void)); +extern int h8300_can_use_return_insn_p PARAMS ((void)); +extern void h8300_expand_prologue PARAMS ((void)); +extern void h8300_expand_epilogue PARAMS ((void)); extern int h8300_current_function_interrupt_function_p PARAMS ((void)); extern void asm_file_start PARAMS ((FILE *)); extern void asm_file_end PARAMS ((FILE *)); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 5e4063cf53c..f8ec6822c3b 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -50,18 +50,17 @@ static const char *byte_reg PARAMS ((rtx, int)); static int h8300_interrupt_function_p PARAMS ((tree)); static int h8300_monitor_function_p PARAMS ((tree)); static int h8300_os_task_function_p PARAMS ((tree)); -static void dosize PARAMS ((FILE *, int, unsigned int)); +static void dosize PARAMS ((int, unsigned int)); static int round_frame_size PARAMS ((int)); static unsigned int compute_saved_regs PARAMS ((void)); -static void push PARAMS ((FILE *, int)); -static void pop PARAMS ((FILE *, int)); +static void push PARAMS ((int)); +static void pop PARAMS ((int)); static const char *cond_string PARAMS ((enum rtx_code)); static unsigned int h8300_asm_insn_count PARAMS ((const char *)); const struct attribute_spec h8300_attribute_table[]; static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree h8300_handle_tiny_data_attribute PARAMS ((tree *, tree, tree, int, bool *)); -static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); static void h8300_insert_attributes PARAMS ((tree, tree *)); #ifndef OBJECT_FORMAT_ELF @@ -104,8 +103,6 @@ const char *h8_push_op, *h8_pop_op, *h8_mov_op; #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" -#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 #undef TARGET_ENCODE_SECTION_INFO @@ -386,50 +383,32 @@ byte_reg (x, b) SIZE to adjust the stack pointer. */ static void -dosize (file, sign, size) - FILE *file; +dosize (sign, size) int sign; unsigned int size; { - /* On the H8/300H and H8S, for sizes <= 8 bytes, it is as good or - better to use adds/subs insns rather than add.l/sub.l with an - immediate value. - - Also, on the H8/300, if we don't have a temporary to hold the - size of the frame in the prologue, we simply emit a sequence of - subs since this shouldn't happen often. */ - if ((TARGET_H8300 && size <= 4) - || ((TARGET_H8300H || TARGET_H8300S) && size <= 8) - || (TARGET_H8300 && h8300_current_function_interrupt_function_p ()) - || (TARGET_H8300 && current_function_needs_context - && sign < 0)) + /* H8/300 cannot add/subtract a large constant with a single + instruction. If a temporary register is available, load the + constant to it and then do the addition. */ + if (TARGET_H8300 + && size > 4 + && !h8300_current_function_interrupt_function_p () + && !(current_function_needs_context && sign < 0)) { - const char *op = (sign > 0) ? "add" : "sub"; - unsigned int amount; - - /* Try different amounts in descending order. */ - for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2; - amount > 0; - amount /= 2) - { - char insn[100]; - - sprintf (insn, "\t%ss\t#%d,%s\n", op, amount, - TARGET_H8300 ? "r7" : "er7"); - for (; size >= amount; size -= amount) - fputs (insn, file); - } + rtx new_sp; + rtx r3 = gen_rtx_REG (Pmode, 3); + emit_insn (gen_rtx_SET (Pmode, r3, GEN_INT (sign * size))); + new_sp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, r3); + emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx, new_sp)); } else { - if (TARGET_H8300) - { - fprintf (file, "\tmov.w\t#%d,r3\n\tadd.w\tr3,r7\n", sign * size); - } - else - { - fprintf (file, "\tadd.l\t#%d,er7\n", sign * size); - } + /* The stack adjustment made here is further optimized by the + splitter. In case of H8/300, the splitter always splits the + addition emitted here to make the adjustment + interrupt-safe. */ + rtx new_sp = plus_constant (stack_pointer_rtx, sign * size); + emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx, new_sp)); } } @@ -466,30 +445,38 @@ compute_saved_regs () return saved_regs; } -/* Output assembly language code to push register RN. */ +/* Emit an insn to push register RN. */ static void -push (file, rn) - FILE *file; +push (rn) int rn; { + rtx reg = gen_rtx_REG (word_mode, rn); + rtx x; + if (TARGET_H8300) - fprintf (file, "\t%s\t%s,@-r7\n", h8_mov_op, h8_reg_names[rn]); + x = gen_push_h8300 (reg); else - fprintf (file, "\t%s\t%s,@-er7\n", h8_mov_op, h8_reg_names[rn]); + x = gen_push_h8300hs (reg); + x = emit_insn (x); + REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0); } -/* Output assembly language code to pop register RN. */ +/* Emit an insn to pop register RN. */ static void -pop (file, rn) - FILE *file; +pop (rn) int rn; { + rtx reg = gen_rtx_REG (word_mode, rn); + rtx x; + if (TARGET_H8300) - fprintf (file, "\t%s\t@r7+,%s\n", h8_mov_op, h8_reg_names[rn]); + x = gen_pop_h8300 (reg); else - fprintf (file, "\t%s\t@er7+,%s\n", h8_mov_op, h8_reg_names[rn]); + x = gen_pop_h8300hs (reg); + x = emit_insn (x); + REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0); } /* This is what the stack looks like after the prolog of @@ -510,14 +497,12 @@ pop (file, rn) <- sp */ -/* Output assembly language code for the function prologue. */ +/* Generate RTL code for the function prologue. */ -static void -h8300_output_function_prologue (file, size) - FILE *file; - HOST_WIDE_INT size; +void +h8300_expand_prologue () { - int fsize = round_frame_size (size); + int fsize = round_frame_size (get_frame_size ()); int regno; int saved_regs; int n_regs; @@ -525,58 +510,23 @@ h8300_output_function_prologue (file, size) /* If the current function has the OS_Task attribute set, then we have a naked prologue. */ if (h8300_os_task_function_p (current_function_decl)) - { - fprintf (file, ";OS_Task prologue\n"); - return; - } + return; if (h8300_monitor_function_p (current_function_decl)) - { - /* My understanding of monitor functions is they act just - like interrupt functions, except the prologue must - mask interrupts. */ - fprintf (file, ";monitor prologue\n"); - if (TARGET_H8300) - { - fprintf (file, "\tsubs\t#2,sp\n"); - push (file, 0); - fprintf (file, "\tstc\tccr,r0l\n"); - fprintf (file, "\tmov.b\tr0l,@(2,sp)\n"); - pop (file, 0); - fprintf (file, "\torc\t#128,ccr\n"); - } - else if (TARGET_H8300H) - { - push (file, 0); - fprintf (file, "\tstc\tccr,r0l\n"); - fprintf (file, "\tmov.b\tr0l,@(4,sp)\n"); - pop (file, 0); - fprintf (file, "\torc\t#128,ccr\n"); - } - else if (TARGET_H8300S) - { - fprintf (file, "\tstc\texr,@-sp\n"); - push (file, 0); - fprintf (file, "\tstc\tccr,r0l\n"); - fprintf (file, "\tmov.b\tr0l,@(6,sp)\n"); - pop (file, 0); - fprintf (file, "\torc\t#128,ccr\n"); - } - else - abort (); - } + /* My understanding of monitor functions is they act just like + interrupt functions, except the prologue must mask + interrupts. */ + emit_insn (gen_monitor_prologue ()); if (frame_pointer_needed) { /* Push fp. */ - push (file, FRAME_POINTER_REGNUM); - fprintf (file, "\t%s\t%s,%s\n", h8_mov_op, - h8_reg_names[STACK_POINTER_REGNUM], - h8_reg_names[FRAME_POINTER_REGNUM]); + push (FRAME_POINTER_REGNUM); + emit_insn (gen_rtx_SET (Pmode, frame_pointer_rtx, stack_pointer_rtx)); } /* Leave room for locals. */ - dosize (file, -1, fsize); + dosize (-1, fsize); /* Push the rest of the registers in ascending order. */ saved_regs = compute_saved_regs (); @@ -604,22 +554,22 @@ h8300_output_function_prologue (file, size) switch (n_regs) { case 1: - push (file, regno); + push (regno); break; case 2: - fprintf (file, "\tstm.l\t%s-%s,@-er7\n", - h8_reg_names[regno], - h8_reg_names[regno + 1]); + emit_insn (gen_stm_h8300s_2 (gen_rtx_REG (SImode, regno), + gen_rtx_REG (SImode, regno + 1))); break; case 3: - fprintf (file, "\tstm.l\t%s-%s,@-er7\n", - h8_reg_names[regno], - h8_reg_names[regno + 2]); + emit_insn (gen_stm_h8300s_3 (gen_rtx_REG (SImode, regno), + gen_rtx_REG (SImode, regno + 1), + gen_rtx_REG (SImode, regno + 2))); break; case 4: - fprintf (file, "\tstm.l\t%s-%s,@-er7\n", - h8_reg_names[regno], - h8_reg_names[regno + 3]); + emit_insn (gen_stm_h8300s_4 (gen_rtx_REG (SImode, regno), + gen_rtx_REG (SImode, regno + 1), + gen_rtx_REG (SImode, regno + 2), + gen_rtx_REG (SImode, regno + 3))); break; default: abort (); @@ -628,38 +578,29 @@ h8300_output_function_prologue (file, size) } } -/* Output assembly language code for the function epilogue. */ +int +h8300_can_use_return_insn_p () +{ + return (reload_completed + && !frame_pointer_needed + && get_frame_size () == 0 + && compute_saved_regs () == 0); +} -static void -h8300_output_function_epilogue (file, size) - FILE *file; - HOST_WIDE_INT size; +/* Generate RTL code for the function epilogue. */ + +void +h8300_expand_epilogue () { - int fsize = round_frame_size (size); + int fsize = round_frame_size (get_frame_size ()); int regno; - rtx insn = get_last_insn (); int saved_regs; int n_regs; if (h8300_os_task_function_p (current_function_decl)) - { - /* OS_Task epilogues are nearly naked -- they just have an - rts instruction. */ - fprintf (file, ";OS_task epilogue\n"); - fprintf (file, "\trts\n"); - goto out; - } - - /* Monitor epilogues are the same as interrupt function epilogues. - Just make a note that we're in a monitor epilogue. */ - if (h8300_monitor_function_p (current_function_decl)) - fprintf (file, ";monitor epilogue\n"); - - /* 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) - goto out; + /* OS_Task epilogues are nearly naked -- they just have an + rts instruction. */ + return; /* Pop the saved registers in descending order. */ saved_regs = compute_saved_regs (); @@ -687,22 +628,22 @@ h8300_output_function_epilogue (file, size) switch (n_regs) { case 1: - pop (file, regno); + pop (regno); break; case 2: - fprintf (file, "\tldm.l\t@er7+,%s-%s\n", - h8_reg_names[regno - 1], - h8_reg_names[regno]); + emit_insn (gen_ldm_h8300s_2 (gen_rtx_REG (SImode, regno - 1), + gen_rtx_REG (SImode, regno))); break; case 3: - fprintf (file, "\tldm.l\t@er7+,%s-%s\n", - h8_reg_names[regno - 2], - h8_reg_names[regno]); + emit_insn (gen_ldm_h8300s_3 (gen_rtx_REG (SImode, regno - 2), + gen_rtx_REG (SImode, regno - 1), + gen_rtx_REG (SImode, regno))); break; case 4: - fprintf (file, "\tldm.l\t@er7+,%s-%s\n", - h8_reg_names[regno - 3], - h8_reg_names[regno]); + emit_insn (gen_ldm_h8300s_4 (gen_rtx_REG (SImode, regno - 3), + gen_rtx_REG (SImode, regno - 2), + gen_rtx_REG (SImode, regno - 1), + gen_rtx_REG (SImode, regno))); break; default: abort (); @@ -711,21 +652,23 @@ h8300_output_function_epilogue (file, size) } /* Deallocate locals. */ - dosize (file, 1, fsize); + dosize (1, fsize); /* Pop frame pointer if we had one. */ if (frame_pointer_needed) - pop (file, FRAME_POINTER_REGNUM); + pop (FRAME_POINTER_REGNUM); +} - if (h8300_current_function_interrupt_function_p ()) - fprintf (file, "\trte\n"); - else - fprintf (file, "\trts\n"); +/* Output assembly language code for the function epilogue. */ - out: +static void +h8300_output_function_epilogue (file, size) + FILE *file ATTRIBUTE_UNUSED; + HOST_WIDE_INT size ATTRIBUTE_UNUSED; +{ pragma_saveall = 0; } - + /* Return nonzero if the current function is an interrupt function. */ diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 6d0be34d4bd..6a9245ee8ae 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -51,7 +51,8 @@ ;; ---------------------------------------------------------------------- (define_constants - [(UNSPEC_INCDEC 0)]) + [(UNSPEC_INCDEC 0) + (UNSPEC_MONITOR 1)]) (define_constants [(SC_REG 3) @@ -1783,7 +1784,32 @@ ;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "*stm_h8300s_2" +(define_expand "push_h8300" + [(set (mem:HI (pre_dec:HI (reg:HI SP_REG))) + (match_operand:HI 0 "register_operand" "=r"))] + + "TARGET_H8300" + "") + +(define_expand "push_h8300hs" + [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) + (match_operand:SI 0 "register_operand" "=r"))] + "TARGET_H8300H && TARGET_H8300S" + "") + +(define_expand "pop_h8300" + [(set (match_operand:HI 0 "register_operand" "=r") + (mem:HI (post_inc:HI (reg:HI SP_REG))))] + "TARGET_H8300" + "") + +(define_expand "pop_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r") + (mem:SI (post_inc:SI (reg:SI SP_REG))))] + "TARGET_H8300H && TARGET_H8300S" + "") + +(define_insn "stm_h8300s_2" [(parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8))) @@ -1799,7 +1825,7 @@ [(set_attr "cc" "none") (set_attr "length" "4")]) -(define_insn "*stm_h8300s_3" +(define_insn "stm_h8300s_3" [(parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -12))) @@ -1820,7 +1846,7 @@ [(set_attr "cc" "none") (set_attr "length" "4")]) -(define_insn "*stm_h8300s_4" +(define_insn "stm_h8300s_4" [(parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -16))) @@ -1840,6 +1866,107 @@ "stm.l\\t%S0-%S3,@-er7" [(set_attr "cc" "none") (set_attr "length" "4")]) + +(define_insn "ldm_h8300s_2" + [(parallel + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int 8))) + (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4))) + (match_operand:SI 0 "register_operand" "")) + (set (mem:SI (reg:SI SP_REG)) + (match_operand:SI 1 "register_operand" ""))])] + "TARGET_H8300S + && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1) + || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3) + || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))" + "ldm.l\\t@er7+,%S0-%S1" + [(set_attr "cc" "none") + (set_attr "length" "4")]) + +(define_insn "ldm_h8300s_3" + [(parallel + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int 12))) + (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8))) + (match_operand:SI 0 "register_operand" "")) + (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4))) + (match_operand:SI 1 "register_operand" "")) + (set (mem:SI (reg:SI SP_REG)) + (match_operand:SI 2 "register_operand" ""))])] + "TARGET_H8300S + && ((REGNO (operands[0]) == 0 + && REGNO (operands[1]) == 1 + && REGNO (operands[2]) == 2) + || (REGNO (operands[0]) == 4 + && REGNO (operands[1]) == 5 + && REGNO (operands[2]) == 6))" + "ldm.l\\t@er7+,%S0-%S2" + [(set_attr "cc" "none") + (set_attr "length" "4")]) + +(define_insn "ldm_h8300s_4" + [(parallel + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int 16))) + (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 12))) + (match_operand:SI 0 "register_operand" "")) + (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8))) + (match_operand:SI 1 "register_operand" "")) + (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4))) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (reg:SI SP_REG)) + (match_operand:SI 3 "register_operand" ""))])] + "TARGET_H8300S + && REGNO (operands[0]) == 0 + && REGNO (operands[1]) == 1 + && REGNO (operands[2]) == 2 + && REGNO (operands[3]) == 3" + "ldm.l\\t@er7+,%S0-%S3" + [(set_attr "cc" "none") + (set_attr "length" "4")]) + +(define_expand "return" + [(return)] + "h8300_can_use_return_insn_p ()" + "") + +(define_insn "*return_1" + [(return)] + "reload_completed" + "* +{ + if (h8300_current_function_interrupt_function_p ()) + return \"rte\"; + else + return \"rts\"; +}" + [(set_attr "cc" "none") + (set_attr "length" "2")]) + +(define_expand "prologue" + [(const_int 0)] + "" + "h8300_expand_prologue (); DONE;") + +(define_expand "epilogue" + [(return)] + "" + "h8300_expand_epilogue ();") + +(define_insn "monitor_prologue" + [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)] + "" + "* +{ + if (TARGET_H8300) + return \"subs\\t#2,r7\;mov.w\\tr0,@-r7\;stc\\tccr,r0l\;mov.b\tr0l,@(2,r7)\;mov.w\\t@r7+,r0\;orc\t#128,ccr\"; + else if (TARGET_H8300H) + return \"mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr\"; + else if (TARGET_H8300S) + return \"stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr\"; +}" + [(set_attr "length" "20") + (set_attr "cc" "clobber")]) ;; ---------------------------------------------------------------------- ;; EXTEND INSTRUCTIONS -- 2.11.0