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.c (CC_FLAG_Z): New.
(CC_FLAG_N, CC_FLAG_C, CC_FLAG_V): New.
#include "target-def.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
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
{
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:
/* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */
output_addr_const (file, XVECEXP (x, 0, 0));
int
mn10300_can_use_return_insn (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 (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);
+ return !mn10300_initial_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM);
}
/* Returns the set of live, callee-saved registers as a bitmask. The
void
mn10300_expand_prologue (void)
{
- HOST_WIDE_INT 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);
+ HOST_WIDE_INT size = mn10300_frame_size ();
/* If we use any of the callee-saved registers, save them now. */
mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
GEN_INT (-size))));
if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
- emit_insn (gen_GOTaddr2picreg ());
+ emit_insn (gen_load_pic ());
}
void
mn10300_expand_epilogue (void)
{
- HOST_WIDE_INT 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);
+ HOST_WIDE_INT size = mn10300_frame_size ();
if (TARGET_AM33_2 && fp_regs_to_save ())
{
}
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)
{
+ 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
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)
- || 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 REG_SAVE_BYTES
- + 4 * fp_regs_to_save ();
- else
- return 0;
+ diff += REG_SAVE_BYTES;
+ diff += 4 * fp_regs_to_save ();
}
- /* The difference between the argument pointer and the stack pointer is
- 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 ();
+ return diff;
}
/* Worker function for TARGET_RETURN_IN_MEMORY. */
{
switch (XINT (x, 1))
{
- case UNSPEC_INT_LABEL:
case UNSPEC_PIC:
case UNSPEC_GOT:
case UNSPEC_GOTOFF:
(MDR_REG 50)
(CC_REG 51)
- (UNSPEC_INT_LABEL 0)
(UNSPEC_PIC 1)
(UNSPEC_GOT 2)
(UNSPEC_GOTOFF 3)
(match_operand:SI 1 "impossible_plus_operand" ""))
(clobber (match_operand:SI 2 "register_operand" "=&A"))]
""
- "
{
rtx dest, scratch, other;
emit_move_insn (dest, scratch);
}
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"
[(set (match_operand:SI 0 "nonimmediate_operand")
(define_expand "builtin_setjmp_receiver"
[(match_operand 0 "" "")]
"flag_pic"
- "
{
- if (flag_pic)
- emit_insn (gen_GOTaddr2picreg ());
-
+ emit_insn (gen_load_pic ());
DONE;
-}")
+})
(define_expand "casesi"
[(match_operand:SI 0 "register_operand")
(define_expand "prologue"
[(const_int 0)]
""
- "mn10300_expand_prologue (); DONE;")
+ { mn10300_expand_prologue (); DONE; }
+)
(define_expand "epilogue"
[(return)]
""
- "
- {
- mn10300_expand_epilogue ();
- DONE;
- }")
+ { mn10300_expand_epilogue (); DONE; }
+)
(define_insn "return_internal"
[(const_int 2)
(match_operand:SI 0 "const_int_operand" "i")
(return)]
""
- "*
- {
- fputs (\"\\tret \", asm_out_file);
- mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
- fprintf (asm_out_file, \",%d\\n\", (int) INTVAL (operands[0]));
- return \"\";
- }"
+{
+ fputs ("\tret ", asm_out_file);
+ mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
+ fprintf (asm_out_file, ",%d\n", (int) INTVAL (operands[0]));
+ return "";
+}
;; Assumes that there will be no more than 8 regs to pop
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 1414) (const_int 1313)))]
[(match_parallel 0 "mn10300_store_multiple_operation"
[(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand 1 "" "")))])]
""
- "*
- {
- fputs (\"\\tmovm \", asm_out_file);
- mn10300_print_reg_list (asm_out_file,
- mn10300_store_multiple_operation (operands[0],
- VOIDmode));
- fprintf (asm_out_file, \",(sp)\\n\");
- return \"\";
- }"
+{
+ fputs ("\tmovm ", asm_out_file);
+ mn10300_print_reg_list (asm_out_file,
+ mn10300_store_multiple_operation (operands[0],
+ VOIDmode));
+ fprintf (asm_out_file, ",(sp)\n");
+ return "";
+}
;; Assume that no more than 8 registers will be pushed.
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 99) (const_int 88)))]
(define_insn "return"
[(return)]
"mn10300_can_use_return_insn ()"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && JUMP_P (next)
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- else
- return \"rets\";
-}"
+ "rets"
[(set_attr "timings" "66")]
)
-(define_expand "int_label"
- [(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)]
- "" "")
-
-(define_expand "GOTaddr2picreg"
- [(match_dup 0)]
- "" "
+(define_expand "load_pic"
+ [(const_int 0)]
+ "flag_pic"
{
- /* 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)
- 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
- emit_insn (gen_mn10300_loadPC (operands[0]));
- emit_insn (gen_add_GOT_to_pic_reg (copy_rtx (operands[0])));
+ emit_insn (gen_mn10300_load_pic1 (pic_offset_table_rtx));
DONE;
-}
-")
+})
-(define_insn "am33_loadPC"
- [(parallel
- [(set (reg:SI PIC_REG) (pc))
- (use (match_operand 0 "" ""))])]
+(define_insn "am33_load_pic"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(const_int 0)] UNSPEC_GOT))
+ (clobber (reg:CC CC_REG))]
"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"
- [(parallel
- [(set (reg:SI PIC_REG) (pc))
- (use (match_operand 0 "" ""))])]
- "! TARGET_AM33"
- "#"
- "&& reload_completed"
- [(match_operand 0 "" "")]
- {
- rtx sp_reg = gen_rtx_REG (SImode, SP_REG);
- int need_stack_space = (get_frame_size () == 0
- && crtl->outgoing_args_size == 0);
-
- if (need_stack_space)
- emit_insn (gen_addsi3 (sp_reg, sp_reg, GEN_INT (-4)));
-
- 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;
- }
+;; Load pic register with push/pop of stack.
+(define_insn "mn10300_load_pic0"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(const_int 0)] UNSPEC_GOT))
+ (clobber (reg:SI MDR_REG))
+ (clobber (reg:CC CC_REG))]
+ ""
+{
+ operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+ return ("add -4,sp\;"
+ "calls .LPIC%=\n"
+ ".LPIC%=:\;"
+ "movm (sp),[%0]\;"
+ "add %1-(.LPIC%=-.),%0");
+}
+ [(set_attr "timings" "88")]
)
-(define_insn "call_next_insn"
- [(parallel
- [(set (mem:SI (reg:SI SP_REG)) (pc))
- (use (match_operand 0 "" ""))])]
- "reload_completed"
- "calls %0\;%0:"
- [(set_attr "timings" "44")]
-)
-
-(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))
- ])
- ]
+;; Load pic register re-using existing stack space.
+(define_insn "mn10300_load_pic1"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(const_int 0)] UNSPEC_GOT))
+ (clobber (mem:SI (reg:SI SP_REG)))
+ (clobber (reg:SI MDR_REG))
+ (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")]
)