h8300-protos.h: Add prototypes for the new functions defined below.

* 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.

From-SVN: r60882
This commit is contained in:
Kazu Hirata 2003-01-04 17:46:24 +00:00 committed by Kazu Hirata
parent 2094e97d2f
commit 68ee6df68a
4 changed files with 265 additions and 162 deletions

View file

@ -1,3 +1,33 @@
2003-01-04 Kazu Hirata <kazu@cs.umass.edu>
* 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 <dalej@apple.com>
* config/darwin.h: (EXTRA_SECTIONS): Add machopic_symbol_stub1,

View file

@ -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 *));

View file

@ -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)
<saved registers> <- 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. */
static void
h8300_output_function_epilogue (file, size)
FILE *file;
HOST_WIDE_INT size;
int
h8300_can_use_return_insn_p ()
{
int fsize = round_frame_size (size);
return (reload_completed
&& !frame_pointer_needed
&& get_frame_size () == 0
&& compute_saved_regs () == 0);
}
/* Generate RTL code for the function epilogue. */
void
h8300_expand_epilogue ()
{
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);
if (h8300_current_function_interrupt_function_p ())
fprintf (file, "\trte\n");
else
fprintf (file, "\trts\n");
out:
pragma_saveall = 0;
pop (FRAME_POINTER_REGNUM);
}
/* Output assembly language code for the function epilogue. */
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. */

View file

@ -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