aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSteve Chamberlain <sac@gnu.org>1993-05-04 15:21:44 +0000
committerSteve Chamberlain <sac@gnu.org>1993-05-04 15:21:44 +0000
commita9f71ad8db46abada800399889b8e5fc9e024026 (patch)
treea7daca333f0ab02f24256339debcf701e2918771 /gcc
parentbc1ebe6373abe535f0d64cb2b17692fa16c285e0 (diff)
downloadgcc-a9f71ad8db46abada800399889b8e5fc9e024026.zip
gcc-a9f71ad8db46abada800399889b8e5fc9e024026.tar.gz
gcc-a9f71ad8db46abada800399889b8e5fc9e024026.tar.bz2
> (arith_reg_operand): New constraint.
> (arith_reg_operand): New constraint. (dump_constants): Force out a constant table if necessary. From-SVN: r4321
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/sh/sh.c111
1 files changed, 96 insertions, 15 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 2e3634c..07c8257 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -39,7 +39,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
static int add_constant ();
-static void dump_constants ();
+static int dump_constants ();
int current_function_anonymous_args;
extern int current_function_pretend_args_size;
@@ -83,12 +83,13 @@ enum reg_class reg_class_from_letter[] =
/* Local label counter, used for constants in the pool and inside
pattern branches. */
-static int lf;
+static int lf = 100;
/* Used to work out sizes of instructions */
static int first_pc;
static int pc;
-
+#define MAYBE_DUMP_LEVEL 900
+#define MUST_DUMP_LEVEL 1000
static int dumpnext;
/* Functions for generating procedure prologue and epilogue code */
@@ -389,9 +390,27 @@ output_epilogue (f, frame_size)
int live_regs_mask = 0;
int d;
int i;
-
+ rtx delay_insn;
+
live_regs_mask = calc_live_regs (&d);
+
+ /* See if the delay insn is really ok for the slot. */
+ if (current_function_epilogue_delay_list) {
+ delay_insn = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
+
+ if (GET_CODE (delay_insn) == SET
+ && SET_DEST (delay_insn) == stack_pointer_rtx)
+ {
+ /* Can not use this instruction in the delay slot because
+ it changes the stack pointer, so emit it now. */
+ final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
+ asm_out_file, 1, 0, 1);
+ current_function_epilogue_delay_list = 0;
+ }
+ }
+
+
/* Reclaim the room for the automatics. */
output_stack_adjust (f, 1, frame_size);
@@ -443,7 +462,7 @@ output_epilogue (f, frame_size)
output_epilogue_vec ();
- dump_constants ();
+ dump_constants (0);
current_function_anonymous_args = 0;
}
@@ -530,7 +549,7 @@ print_operand (stream, x, code)
fprintf (stream, "LF%d", lf);
break;
case '!':
- dump_constants();
+ dump_constants (0);
break;
case '^':
lf++;
@@ -674,7 +693,14 @@ output_movedouble (operands, mode)
{
if (REGNO (operands[1]) == MACH_REG)
return "sts mach,%0\n\tsts macl,%R0";
- return "mov %1,%0\n\tmov %R1,%R0";
+ if (REGNO (operands[1]) > REGNO (operands[0]))
+ {
+ return "mov %1,%0\n\tmov %R1,%R0";
+ }
+ else
+ {
+ return "mov %R1,%R0\n\tmov %1,%0";
+ }
}
if (GET_CODE (operands[1]) == CONST_INT)
@@ -780,8 +806,8 @@ output_branch (logic, insn)
fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
output_asm_insn ("bra %l0 ! 12 bit cond ", recog_operand);
fprintf (asm_out_file, "\tor r0,r0\n");
+ label = dump_constants (label);
fprintf (asm_out_file, "LF%d:\n", label);
- lf++;
return "";
case 8:
@@ -800,6 +826,23 @@ output_branch (logic, insn)
/* Predicates used by the templates */
+/* Nonzero if OP is a normal arithmetic register. */
+
+int
+arith_reg_operand(op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (register_operand (op, mode))
+ {
+ if (GET_CODE (op) == REG)
+ return REGNO (op) != T_REG;
+ return 1;
+ }
+ return 0;
+}
+
+
/* Nonzero if OP is a valid source operand for an arithmetic insn. */
int
@@ -1054,7 +1097,7 @@ adjust_insn_length (insn, insn_lengths)
instruction than it can reach, so we'll stop accumulating
from that one and start fresh. */
target_pc = current_pc;
- target_insn_range = current_pc + 1000;
+ target_insn_range = current_pc + MAYBE_DUMP_LEVEL;
}
else
{
@@ -1087,18 +1130,25 @@ adjust_insn_length (insn, insn_lengths)
}
-/* Dump out the pending constant pool. */
+/* Dump out the pending constant pool.
+ If label provided then insert an branch in the middle of the table
+ */
-static void
-dump_constants ()
+static int
+dump_constants (label)
{
int i;
+ int rlabel = label;
+ int size = 0;
+
for (i = 0; i < pool_size; i++)
{
pool_node *p = pool_vector + i;
fprintf (asm_out_file, "\n\t! constants - waited %d\n", pc - first_pc);
fprintf (asm_out_file, "\t.align\t2\n");
fprintf (asm_out_file, "LK%d:", p->number);
+ size += GET_MODE_SIZE (p->mode);
+
switch (GET_MODE_CLASS (p->mode))
{
case MODE_INT:
@@ -1112,12 +1162,23 @@ dump_constants ()
assemble_real (u.d, p->mode);
}
}
-
+
+ /* After 200 bytes of table, stick in another branch */
+ if (label && size > 200)
+ {
+ rlabel = lf ++;
+ fprintf (asm_out_file,"LF%d:\tbra LF%d\n", label, rlabel);
+ fprintf (asm_out_file,"\tor r0,r0\n");
+ label = 0;
+ }
+
fprintf (asm_out_file, "\n");
}
pool_size = 0;
current_pc = 0;
target_insn_range = 0;
+ return rlabel;
+
}
@@ -1151,7 +1212,7 @@ output_movepcrel (insn, operands, mode)
fprintf (asm_out_file, "\t!constant table start\n");
fprintf (asm_out_file, "\tbra LF%d\n", lf);
fprintf (asm_out_file, "\tor r0,r0 ! wasted slot\n");
- dump_constants ();
+ dump_constants (0);
fprintf (asm_out_file, "LF%d:\n", lf++);
fprintf (asm_out_file, "\t!constant table end\n");
}
@@ -1182,7 +1243,27 @@ final_prescan_insn (insn, opvec, noperands)
if (TARGET_DUMP_RTL)
print_rtl (asm_out_file, body);
- pc += get_attr_length (insn);
+
}
+
+ pc += get_attr_length (insn);
+
+ if (pool_size && pc - first_pc > MUST_DUMP_LEVEL)
+ {
+ /* For some reason we have not dumped out a constant table, and
+ we have emitted a lot of code. This can happen if the think
+ which wants the table is a long conditional branch (which has no
+ room for a constant table), and there has not been a move
+ constant anywhere. */
+ int label = lf++;
+ fprintf (asm_out_file, "\t!forced constant table\n");
+ fprintf (asm_out_file, "\tbra LF%d\n", label);
+ fprintf (asm_out_file, "\tor r0,r0 ! wasted slot\n");
+ label = dump_constants (label);
+ fprintf (asm_out_file, "LF%d:\n", label);
+ fprintf (asm_out_file, "\t!constant table end\n");
+ }
+
}
+