Commit 040c5757 by Richard Henderson Committed by Richard Henderson

mn10300: tidy pic address loading

There's little reason to greatly complicate things by splitting
the pic_load patterns and using complex rtl to make it work out.
Instead, use the %= marker to generate unique numbers and emit
the entire load_pic sequence at once.

At the same time, collect all references to outgoing_args_size
into mn10300_frame_size, and all computations of register save
area size into mn10300_initial_offset.

From-SVN: r169012
parent bad41521
2011-01-19 Richard Henderson <rth@redhat.com> 2011-01-19 Richard Henderson <rth@redhat.com>
* config/mn10300/mn10300.c (mn10300_unspec_int_label_counter): Remove.
(mn10300_asm_output_addr_const_extra): Don't handle UNSPEC_INT_LABEL.
(mn10300_legitimate_constant_p): Likewise.
(mn10300_can_use_return_insn): Use mn10300_initial_offset.
(mn10300_frame_size): New.
(mn10300_expand_prologue): Use it.
(mn10300_expand_epilogue): Likewise.
(mn10300_initial_offset): Likewise.
* config/mn10300/mn10300-protos.h: Update.
* config/mn10300/mn10300.h (mn10300_unspec_int_label_counter): Remove.
* config/mn10300/mn10300.md (UNSPEC_INT_LABEL): Remove.
(prologue, epilogue, return_internal): Tidy output code.
(mn10300_store_multiple_operation, return): Likewise.
(int_label, pop_pic_reg, GOTaddr2picreg): Remove.
(am33_loadPC, mn10300_loadPC, call_next_insn): Remove.
(add_GOT_to_pic_reg, add_GOT_to_any_reg): Remove.
(load_pic, am33_load_pic): New.
(mn10300_load_pic0, mn10300_load_pic1): New.
* config/mn10300/mn10300-modes.def (CCZN, CCZNC): New modes. * config/mn10300/mn10300-modes.def (CCZN, CCZNC): New modes.
* config/mn10300/mn10300.c (CC_FLAG_Z): New. * config/mn10300/mn10300.c (CC_FLAG_Z): New.
(CC_FLAG_N, CC_FLAG_C, CC_FLAG_V): New. (CC_FLAG_N, CC_FLAG_C, CC_FLAG_V): New.
......
...@@ -49,6 +49,7 @@ extern int mn10300_can_use_return_insn (void); ...@@ -49,6 +49,7 @@ extern int mn10300_can_use_return_insn (void);
extern void mn10300_expand_prologue (void); extern void mn10300_expand_prologue (void);
extern void mn10300_expand_epilogue (void); extern void mn10300_expand_epilogue (void);
extern int mn10300_initial_offset (int, int); extern int mn10300_initial_offset (int, int);
extern int mn10300_frame_size (void);
#undef Mmode #undef Mmode
#undef Cstar #undef Cstar
......
...@@ -44,10 +44,6 @@ ...@@ -44,10 +44,6 @@
#include "target-def.h" #include "target-def.h"
#include "df.h" #include "df.h"
/* This is used by GOTaddr2picreg to uniquely identify
UNSPEC_INT_LABELs. */
int mn10300_unspec_int_label_counter;
/* This is used in the am33_2.0-linux-gnu port, in which global symbol /* This is used in the am33_2.0-linux-gnu port, in which global symbol
names are not prefixed by underscores, to tell whether to prefix a names are not prefixed by underscores, to tell whether to prefix a
label with a plus sign or not, so that the assembler can tell label with a plus sign or not, so that the assembler can tell
...@@ -544,10 +540,6 @@ mn10300_asm_output_addr_const_extra (FILE *file, rtx x) ...@@ -544,10 +540,6 @@ mn10300_asm_output_addr_const_extra (FILE *file, rtx x)
{ {
switch (XINT (x, 1)) switch (XINT (x, 1))
{ {
case UNSPEC_INT_LABEL:
asm_fprintf (file, ".%LLIL" HOST_WIDE_INT_PRINT_DEC,
INTVAL (XVECEXP (x, 0, 0)));
break;
case UNSPEC_PIC: case UNSPEC_PIC:
/* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */ /* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */
output_addr_const (file, XVECEXP (x, 0, 0)); output_addr_const (file, XVECEXP (x, 0, 0));
...@@ -634,24 +626,7 @@ mn10300_print_reg_list (FILE *file, int mask) ...@@ -634,24 +626,7 @@ mn10300_print_reg_list (FILE *file, int mask)
int int
mn10300_can_use_return_insn (void) mn10300_can_use_return_insn (void)
{ {
/* size includes the fixed stack space needed for function calls. */ return !mn10300_initial_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM);
int size = get_frame_size () + crtl->outgoing_args_size;
/* And space for the return pointer. */
size += crtl->outgoing_args_size ? 4 : 0;
return (reload_completed
&& size == 0
&& !df_regs_ever_live_p (2)
&& !df_regs_ever_live_p (3)
&& !df_regs_ever_live_p (6)
&& !df_regs_ever_live_p (7)
&& !df_regs_ever_live_p (14)
&& !df_regs_ever_live_p (15)
&& !df_regs_ever_live_p (16)
&& !df_regs_ever_live_p (17)
&& fp_regs_to_save () == 0
&& !frame_pointer_needed);
} }
/* Returns the set of live, callee-saved registers as a bitmask. The /* Returns the set of live, callee-saved registers as a bitmask. The
...@@ -760,11 +735,7 @@ mn10300_gen_multiple_store (unsigned int mask) ...@@ -760,11 +735,7 @@ mn10300_gen_multiple_store (unsigned int mask)
void void
mn10300_expand_prologue (void) mn10300_expand_prologue (void)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size = mn10300_frame_size ();
/* SIZE includes the fixed stack space needed for function calls. */
size = get_frame_size () + crtl->outgoing_args_size;
size += (crtl->outgoing_args_size ? 4 : 0);
/* If we use any of the callee-saved registers, save them now. */ /* If we use any of the callee-saved registers, save them now. */
mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ()); mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
...@@ -1017,17 +988,13 @@ mn10300_expand_prologue (void) ...@@ -1017,17 +988,13 @@ mn10300_expand_prologue (void)
GEN_INT (-size)))); GEN_INT (-size))));
if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
emit_insn (gen_GOTaddr2picreg ()); emit_insn (gen_load_pic ());
} }
void void
mn10300_expand_epilogue (void) mn10300_expand_epilogue (void)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size = mn10300_frame_size ();
/* SIZE includes the fixed stack space needed for function calls. */
size = get_frame_size () + crtl->outgoing_args_size;
size += (crtl->outgoing_args_size ? 4 : 0);
if (TARGET_AM33_2 && fp_regs_to_save ()) if (TARGET_AM33_2 && fp_regs_to_save ())
{ {
...@@ -1442,54 +1409,37 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, ...@@ -1442,54 +1409,37 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
} }
int int
mn10300_frame_size (void)
{
/* size includes the fixed stack space needed for function calls. */
int size = get_frame_size () + crtl->outgoing_args_size;
/* And space for the return pointer. */
size += crtl->outgoing_args_size ? 4 : 0;
return size;
}
int
mn10300_initial_offset (int from, int to) mn10300_initial_offset (int from, int to)
{ {
int diff = 0;
gcc_assert (from == ARG_POINTER_REGNUM || from == FRAME_POINTER_REGNUM);
gcc_assert (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
if (to == STACK_POINTER_REGNUM)
diff = mn10300_frame_size ();
/* The difference between the argument pointer and the frame pointer /* The difference between the argument pointer and the frame pointer
is the size of the callee register save area. */ is the size of the callee register save area. */
if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) if (from == ARG_POINTER_REGNUM)
{ {
if (df_regs_ever_live_p (2) || df_regs_ever_live_p (3) diff += REG_SAVE_BYTES;
|| df_regs_ever_live_p (6) || df_regs_ever_live_p (7) diff += 4 * fp_regs_to_save ();
|| df_regs_ever_live_p (14) || df_regs_ever_live_p (15)
|| df_regs_ever_live_p (16) || df_regs_ever_live_p (17)
|| fp_regs_to_save ()
|| frame_pointer_needed)
return REG_SAVE_BYTES
+ 4 * fp_regs_to_save ();
else
return 0;
} }
/* The difference between the argument pointer and the stack pointer is return diff;
the sum of the size of this function's frame, the callee register save
area, and the fixed stack space needed for function calls (if any). */
if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
{
if (df_regs_ever_live_p (2) || df_regs_ever_live_p (3)
|| df_regs_ever_live_p (6) || df_regs_ever_live_p (7)
|| df_regs_ever_live_p (14) || df_regs_ever_live_p (15)
|| df_regs_ever_live_p (16) || df_regs_ever_live_p (17)
|| fp_regs_to_save ()
|| frame_pointer_needed)
return (get_frame_size () + REG_SAVE_BYTES
+ 4 * fp_regs_to_save ()
+ (crtl->outgoing_args_size
? crtl->outgoing_args_size + 4 : 0));
else
return (get_frame_size ()
+ (crtl->outgoing_args_size
? crtl->outgoing_args_size + 4 : 0));
}
/* The difference between the frame pointer and stack pointer is the sum
of the size of this function's frame and the fixed stack space needed
for function calls (if any). */
if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
return (get_frame_size ()
+ (crtl->outgoing_args_size
? crtl->outgoing_args_size + 4 : 0));
gcc_unreachable ();
} }
/* Worker function for TARGET_RETURN_IN_MEMORY. */ /* Worker function for TARGET_RETURN_IN_MEMORY. */
...@@ -2087,7 +2037,6 @@ mn10300_legitimate_constant_p (rtx x) ...@@ -2087,7 +2037,6 @@ mn10300_legitimate_constant_p (rtx x)
{ {
switch (XINT (x, 1)) switch (XINT (x, 1))
{ {
case UNSPEC_INT_LABEL:
case UNSPEC_PIC: case UNSPEC_PIC:
case UNSPEC_GOT: case UNSPEC_GOT:
case UNSPEC_GOTOFF: case UNSPEC_GOTOFF:
......
...@@ -53,8 +53,6 @@ ...@@ -53,8 +53,6 @@
} \ } \
while (0) while (0)
extern GTY(()) int mn10300_unspec_int_label_counter;
enum processor_type enum processor_type
{ {
PROCESSOR_MN10300, PROCESSOR_MN10300,
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
(MDR_REG 50) (MDR_REG 50)
(CC_REG 51) (CC_REG 51)
(UNSPEC_INT_LABEL 0)
(UNSPEC_PIC 1) (UNSPEC_PIC 1)
(UNSPEC_GOT 2) (UNSPEC_GOT 2)
(UNSPEC_GOTOFF 3) (UNSPEC_GOTOFF 3)
...@@ -294,7 +293,6 @@ ...@@ -294,7 +293,6 @@
(match_operand:SI 1 "impossible_plus_operand" "")) (match_operand:SI 1 "impossible_plus_operand" ""))
(clobber (match_operand:SI 2 "register_operand" "=&A"))] (clobber (match_operand:SI 2 "register_operand" "=&A"))]
"" ""
"
{ {
rtx dest, scratch, other; rtx dest, scratch, other;
...@@ -336,16 +334,7 @@ ...@@ -336,16 +334,7 @@
emit_move_insn (dest, scratch); emit_move_insn (dest, scratch);
} }
DONE; DONE;
}") })
(define_insn "pop_pic_reg"
[(set (reg:SI PIC_REG)
(mem:SI (post_inc:SI (reg:SI SP_REG))))]
"reload_completed"
"movm (sp),[a2]"
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 44) (const_int 33)))]
)
(define_expand "movsi" (define_expand "movsi"
[(set (match_operand:SI 0 "nonimmediate_operand") [(set (match_operand:SI 0 "nonimmediate_operand")
...@@ -1141,13 +1130,10 @@ ...@@ -1141,13 +1130,10 @@
(define_expand "builtin_setjmp_receiver" (define_expand "builtin_setjmp_receiver"
[(match_operand 0 "" "")] [(match_operand 0 "" "")]
"flag_pic" "flag_pic"
"
{ {
if (flag_pic) emit_insn (gen_load_pic ());
emit_insn (gen_GOTaddr2picreg ());
DONE; DONE;
}") })
(define_expand "casesi" (define_expand "casesi"
[(match_operand:SI 0 "register_operand") [(match_operand:SI 0 "register_operand")
...@@ -1612,16 +1598,14 @@ ...@@ -1612,16 +1598,14 @@
(define_expand "prologue" (define_expand "prologue"
[(const_int 0)] [(const_int 0)]
"" ""
"mn10300_expand_prologue (); DONE;") { mn10300_expand_prologue (); DONE; }
)
(define_expand "epilogue" (define_expand "epilogue"
[(return)] [(return)]
"" ""
" { mn10300_expand_epilogue (); DONE; }
{ )
mn10300_expand_epilogue ();
DONE;
}")
(define_insn "return_internal" (define_insn "return_internal"
[(const_int 2) [(const_int 2)
...@@ -1638,13 +1622,12 @@ ...@@ -1638,13 +1622,12 @@
(match_operand:SI 0 "const_int_operand" "i") (match_operand:SI 0 "const_int_operand" "i")
(return)] (return)]
"" ""
"* {
{ fputs ("\tret ", asm_out_file);
fputs (\"\\tret \", asm_out_file); mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ()); fprintf (asm_out_file, ",%d\n", (int) INTVAL (operands[0]));
fprintf (asm_out_file, \",%d\\n\", (int) INTVAL (operands[0])); return "";
return \"\"; }
}"
;; Assumes that there will be no more than 8 regs to pop ;; Assumes that there will be no more than 8 regs to pop
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 1414) (const_int 1313)))] (const_int 1414) (const_int 1313)))]
...@@ -1655,15 +1638,14 @@ ...@@ -1655,15 +1638,14 @@
[(match_parallel 0 "mn10300_store_multiple_operation" [(match_parallel 0 "mn10300_store_multiple_operation"
[(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand 1 "" "")))])] [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand 1 "" "")))])]
"" ""
"* {
{ fputs ("\tmovm ", asm_out_file);
fputs (\"\\tmovm \", asm_out_file); mn10300_print_reg_list (asm_out_file,
mn10300_print_reg_list (asm_out_file, mn10300_store_multiple_operation (operands[0],
mn10300_store_multiple_operation (operands[0], VOIDmode));
VOIDmode)); fprintf (asm_out_file, ",(sp)\n");
fprintf (asm_out_file, \",(sp)\\n\"); return "";
return \"\"; }
}"
;; Assume that no more than 8 registers will be pushed. ;; Assume that no more than 8 registers will be pushed.
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 99) (const_int 88)))] (const_int 99) (const_int 88)))]
...@@ -1672,116 +1654,67 @@ ...@@ -1672,116 +1654,67 @@
(define_insn "return" (define_insn "return"
[(return)] [(return)]
"mn10300_can_use_return_insn ()" "mn10300_can_use_return_insn ()"
"* "rets"
{
rtx next = next_active_insn (insn);
if (next
&& JUMP_P (next)
&& GET_CODE (PATTERN (next)) == RETURN)
return \"\";
else
return \"rets\";
}"
[(set_attr "timings" "66")] [(set_attr "timings" "66")]
) )
(define_expand "int_label" (define_expand "load_pic"
[(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)] [(const_int 0)]
"" "") "flag_pic"
(define_expand "GOTaddr2picreg"
[(match_dup 0)]
"" "
{ {
/* It would be nice to be able to have int_label keep track of the
counter and all, but if we add C code to it, we'll get an insn
back, and we just want the pattern. */
operands[0] = gen_int_label (GEN_INT (mn10300_unspec_int_label_counter++));
if (TARGET_AM33) if (TARGET_AM33)
emit_insn (gen_am33_loadPC (operands[0])); emit_insn (gen_am33_load_pic (pic_offset_table_rtx));
else if (mn10300_frame_size () == 0)
emit_insn (gen_mn10300_load_pic0 (pic_offset_table_rtx));
else else
emit_insn (gen_mn10300_loadPC (operands[0])); emit_insn (gen_mn10300_load_pic1 (pic_offset_table_rtx));
emit_insn (gen_add_GOT_to_pic_reg (copy_rtx (operands[0])));
DONE; DONE;
} })
")
(define_insn "am33_loadPC" (define_insn "am33_load_pic"
[(parallel [(set (match_operand:SI 0 "register_operand" "=a")
[(set (reg:SI PIC_REG) (pc)) (unspec:SI [(const_int 0)] UNSPEC_GOT))
(use (match_operand 0 "" ""))])] (clobber (reg:CC CC_REG))]
"TARGET_AM33" "TARGET_AM33"
"%0:\;mov pc,a2" {
operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
return ".LPIC%=:\;mov pc,%0\;add %1-(.LPIC%=-.),%0";
}
[(set_attr "timings" "33")]
) )
(define_insn_and_split "mn10300_loadPC" ;; Load pic register with push/pop of stack.
[(parallel (define_insn "mn10300_load_pic0"
[(set (reg:SI PIC_REG) (pc)) [(set (match_operand:SI 0 "register_operand" "=a")
(use (match_operand 0 "" ""))])] (unspec:SI [(const_int 0)] UNSPEC_GOT))
"! TARGET_AM33" (clobber (reg:SI MDR_REG))
"#" (clobber (reg:CC CC_REG))]
"&& reload_completed" ""
[(match_operand 0 "" "")] {
{ operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
rtx sp_reg = gen_rtx_REG (SImode, SP_REG); return ("add -4,sp\;"
int need_stack_space = (get_frame_size () == 0 "calls .LPIC%=\n"
&& crtl->outgoing_args_size == 0); ".LPIC%=:\;"
"movm (sp),[%0]\;"
if (need_stack_space) "add %1-(.LPIC%=-.),%0");
emit_insn (gen_addsi3 (sp_reg, sp_reg, GEN_INT (-4))); }
[(set_attr "timings" "88")]
emit_insn (gen_call_next_insn (operands[0]));
if (need_stack_space)
emit_insn (gen_pop_pic_reg ());
else
emit_move_insn (pic_offset_table_rtx, gen_rtx_MEM (SImode, sp_reg));
DONE;
}
) )
(define_insn "call_next_insn" ;; Load pic register re-using existing stack space.
[(parallel (define_insn "mn10300_load_pic1"
[(set (mem:SI (reg:SI SP_REG)) (pc)) [(set (match_operand:SI 0 "register_operand" "=a")
(use (match_operand 0 "" ""))])] (unspec:SI [(const_int 0)] UNSPEC_GOT))
"reload_completed" (clobber (mem:SI (reg:SI SP_REG)))
"calls %0\;%0:" (clobber (reg:SI MDR_REG))
[(set_attr "timings" "44")] (clobber (reg:CC CC_REG))]
)
(define_expand "add_GOT_to_pic_reg"
[(parallel [(set (reg:SI PIC_REG)
(plus:SI
(reg:SI PIC_REG)
(const:SI
(unspec:SI [(minus:SI
(match_dup 1)
(const (minus:SI
(const (match_operand:SI 0 "" ""))
(pc))))
] UNSPEC_PIC))))
(clobber (reg:CC CC_REG))
])
]
""
"operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);"
)
(define_expand "add_GOT_to_any_reg"
[(parallel [(set (match_operand:SI 0 "" "")
(plus:SI
(match_operand:SI 1 "" "")
(const
(unspec [(minus:SI
(match_dup 3)
(const (minus:SI
(const (match_operand:SI 2 "" ""))
(pc))))
] UNSPEC_PIC))))
(clobber (reg:CC CC_REG))
])
]
"" ""
"operands[3] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);" {
operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
return ("calls .LPIC%=\n"
".LPIC%=:\;"
"mov (sp),%0\;"
"add %1-(.LPIC%=-.),%0");
}
[(set_attr "timings" "66")]
) )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment