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:
parent
2094e97d2f
commit
68ee6df68a
4 changed files with 265 additions and 162 deletions
|
@ -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,
|
||||
|
|
|
@ -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 *));
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue