int regno_reg_class[FIRST_PSEUDO_REGISTER] =
{
- R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+ R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
- GENERAL_REGS, PR_REGS, T_REGS, NO_REGS,
- MAC_REGS, MAC_REGS,
+ GENERAL_REGS, PR_REGS, T_REGS, NO_REGS,
+ MAC_REGS, MAC_REGS,
};
/* Provide reg_class from a letter such as appears in the machine
int hard_regno_mode_ok[] =
{
- REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
- REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
- REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
- REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
- REG, 0, SI_ONLY, SI_ONLY,
- SI_ONLY, SI_ONLY
+ REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
+ REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
+ REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
+ REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
+ REG, 0, SI_ONLY, SI_ONLY,
+ SI_ONLY, SI_ONLY
};
/* Local label counter, used for constants in the pool and inside
/* Number of bytes pushed for anonymous args, used to pass information
between expand_prologue and expand_epilogue. */
static int extra_push;
-
\f
+
void
push (rn)
int rn;
void
pop (rn)
+ int rn;
{
emit_insn (gen_pop (gen_rtx (REG, SImode, rn)));
}
default:
debug_rtx (x);
-
abort ();
}
}
break;
case '@':
if (pragma_interrupt)
- fprintf (stream,"rte");
+ fprintf (stream, "rte");
else
- fprintf (stream,"rts");
+ fprintf (stream, "rts");
break;
case '#':
/* Output a nop if there's nothing in the delay slot */
}
\f
+static int
sextb (x)
+ int x;
{
x &= 0xff;
if (x > 127)
/* Take a move with integer constant source in OPERANDS, see if it can be generated by
devious shifting. If so, generate the instruction sequence and return 1, otherwise
return 0.
-
+
OPERANDS[0] Destination register
OPERANDS[1] Source constant
00000000 00000000 11111111 1NNNNNNNN load and zero extend word
-*/
+*/
static int
synth_constant (operands, mode)
rtx dst;
int i = INTVAL (operands[1]) & 0xffffffff;
- if (CONST_OK_FOR_I (i))
+ if (CONST_OK_FOR_I (i))
return 0;
if (TARGET_CLEN0 && mode != QImode)
if (mode != SImode)
{
- if (reload_in_progress)
+ if (reload_in_progress)
return 0;
dst = gen_reg_rtx (SImode);
}
- else
+ else
{
dst = operands[0];
}
}
if (mode == SImode && constp && (bytes % 4 == 0))
{
- char entry[30];
tree entry_name;
rtx func_addr_rtx;
- int groups;
rtx r4 = gen_rtx (REG, SImode, 4);
rtx r5 = gen_rtx (REG, SImode, 5);
rtx r6 = gen_rtx (REG, SImode, 6);
/* copy the source to a register */
operands[1] = copy_to_mode_reg (mode, operands[1]);
}
- if ((mode == DImode || mode == SImode || mode == HImode || mode == QImode)
+ if ((mode == DImode || mode == SImode || mode == HImode || mode == QImode)
&& GET_CODE (operands[1]) == CONST_INT)
{
return synth_constant (operands, mode);
compare has been done. */
rtx
prepare_scc_operands (code)
+ int code;
{
if (GET_CODE (sh_compare_op0) != REG
|| REGNO (sh_compare_op0) != T_REG)
{
return "mov.l %1,%0\n\tmov.l %1+4,%R0";
}
+ else if (GET_CODE (inside) == POST_INC)
+ {
+ return "mov.l %1,%0\n\tmov.l %1,%R0 !mdi\n";
+ }
else
abort ();
{
rtx thislab = gen_label_rtx ();
- /* See if we can grab a reg from the prev insn */
- rtx gotone = 0;
- rtx prev = PREV_INSN (insn);
- rtx link;
-
if (dbr_sequence_length ())
{
/* Something to go in what would have been the delay
for (i = 0; i < 8; i++)
{
vec[1] = gen_rtx (REG, SImode, i);
- if (!reg_referenced_p (vec[1], PATTERN (XVECEXP (final_sequence, 0, 1))))
+ if (!reg_referenced_p (vec[1],
+ PATTERN (XVECEXP (final_sequence, 0, 1))))
break;
}
{
extern rtx recog_operand[];
int label = lf++;
- int rn = -1;
- int need_save;
-/* fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);*/
+
+ /* fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);*/
switch (get_attr_length (insn))
{
/* Dump out interesting debug info */
-rtx
+void
final_prescan_insn (insn, opvec, noperands)
rtx insn;
rtx *opvec;
insn_addresses[INSN_UID (insn)]);
}
}
+\f
-\f
/* Stuff taken from m88k.c */
data_section ();
- pos = fprintf (file, "\n! Hitachi SH cc1 (%s) (release D-1) arguments:", version_string);
+ pos = fprintf (file, "\n! Hitachi SH cc1 (%s) (release E-2) arguments:", version_string);
output_options (file, f_options, f_len, W_options, W_len,
pos, 75, " ", "\n! ", "\n\n");
}
return 1;
}
-int
+int
andcosts (RTX)
rtx RTX;
{
return 5;
}
-int howshift (i)
-int i;
+int
+howshift (i)
+ int i;
{
int total = 0;
while (i > 0)
{
- if (i >= 16) {
- total++;
- i -= 16;
- }
- else if (i >= 8) {
- total++;
- i -= 8;
- }
- else if (i >= 2) {
- total++;
- i -= 2;
- }
- else if (i>=1) {
- total++;
- i--;
- }
+ if (i >= 16)
+ {
+ total++;
+ i -= 16;
+ }
+ else if (i >= 8)
+ {
+ total++;
+ i -= 8;
+ }
+ else if (i >= 2)
+ {
+ total++;
+ i -= 2;
+ }
+ else if (i >= 1)
+ {
+ total++;
+ i--;
+ }
}
return total;
}
rtx RTX;
{
/* If mult by a power of 2 then work out how we'd shift to make it */
- int insn_cost;
-
+ int insn_cost = 0;
+
if (GET_CODE (XEXP (RTX, 1)) == CONST_INT)
{
int i = exact_log2 (INTVAL (XEXP (RTX, 1)));
- if (i >= 0)
+ if (i >= 0)
insn_cost = howshift (i);
- else
+ else
insn_cost = 100000;
}
if (TARGET_SH2)
read of the mac reg, but count more because of the latency and extra reg
usage */
if (TARGET_SMALLCODE)
- return 2;
+ return 2;
if (insn_cost > 5)
return 5;
return insn_cost;
/* If we we're aiming at small code, then just count the number of
insns in a multiply call sequence */
- if (TARGET_SMALLCODE)
+ if (TARGET_SMALLCODE)
{
if (insn_cost > 6)
return 6;
rtx scan;
{
int i;
- int pass;
int need_align = 1;
{
return 1;
}
+ if (GET_CODE (src) == LABEL_REF)
+ {
+ return 1;
+ }
if (GET_CODE (src) == CONST_INT)
{
/* All QI insns are ok */
/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one.
If an HI move is found, then make sure that MAX_COUNT_HI isn't broken from that one. */
+static rtx from;
static
rtx
-find_barrier (from)
- rtx from;
+find_barrier (from_)
+ rtx from_;
{
int count_si = 0;
int count_hi = 0;
int found_hi = 0;
int found_si = 0;
rtx found_barrier = 0;
-
+from = from_;
while (from
&& count_si < max_count_si
&& count_hi < max_count_hi)
if (!found_barrier)
{
- /* Insert a jump around the barrier here */
+ /* We didn't find a barrier in time to
+ dump our stuff, so we'll make one */
rtx label = gen_label_rtx ();
/* Walk back to be just before any jump */
+ from = PREV_INSN (from);
while (GET_CODE (from) == JUMP_INSN
- || GET_CODE (from) == NOTE)
+ || GET_CODE (from) == NOTE
+ || GET_CODE (from) == CODE_LABEL)
{
from = PREV_INSN (from);
}
rtx first;
{
rtx insn;
- int limit;
for (insn = first; insn; insn = NEXT_INSN (insn))
{
if (broken_move (insn))
/* Called from the md file, set up the operands of a compare instruction */
-int
+void
from_compare (operands, code)
rtx *operands;
int code;
/* Force args into regs, since we can't use constants here */
sh_compare_op0 = force_reg (SImode, sh_compare_op0);
if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (SImode, sh_compare_op1);
+ sh_compare_op1 = force_reg (SImode, sh_compare_op1);
}
operands[1] = sh_compare_op0;
operands[2] = sh_compare_op1;
}
-/* Framefull frame looks like:
-
- arg-5
- arg-4
- [ if current_function_anonymous_args
- arg-3
- arg-2
- arg-1
- arg-0 ]
- saved-fp
- saved-r10
- saved-r11
- saved-r12
- saved-pr
- local-n
- ..
- local-1
- local-0 <- fp points here
+/* Add this function to the list of ones seen - temporary
+ gross hack to try out bsrs. */
+struct flist
+{
+ char *name;
+ struct flist *next;
+};
+struct flist *head;
+static void
+add_function (name)
+ char *name;
+{
+ struct flist *n = (struct flist *) xmalloc (sizeof (struct flist));
+ int l = strlen (name) + 1;
+ n->name = xmalloc (l);
+ memcpy (n->name, name, l);
+ n->next = head;
+ head = n;
+}
- If TARGET_SMALLCALL, then the preserved registers are pushed by a
- wrapper before the routine is entered, so the regs are always pushed
- and there are two pr's on the stack - the caller and the wrapper.
- */
+static int
+seen_function (name)
+ char *name;
+{
+ struct flist *p = head;
+ for (p = head; p; p = p->next)
+ {
+ if (strcmp (p->name, name) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+ /* Framefull frame looks like:
+
+ arg-5
+ arg-4
+ [ if current_function_anonymous_args
+ arg-3
+ arg-2
+ arg-1
+ arg-0 ]
+ saved-fp
+ saved-r10
+ saved-r11
+ saved-r12
+ saved-pr
+ local-n
+ ..
+ local-1
+ local-0 <- fp points here
-/* Code to generate prologue and epilogue sequences */
+ If TARGET_SMALLCALL, then the preserved registers are pushed by a
+ wrapper before the routine is entered, so the regs are always pushed
+ and there are two pr's on the stack - the caller and the wrapper.
+ */
+
+
+ /* Code to generate prologue and epilogue sequences */
void
{
int live_regs_mask;
int d;
-
+ extern tree current_function_decl;
live_regs_mask = calc_live_regs (&d);
/* We have pretend args if we had an object sent partially in registers
{
emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
}
+ if (TARGET_BSR)
+ {
+ add_function (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+ }
+
+
}
void
int
initial_elimination_offset (from, to)
+ int from;
+ int to;
{
int regs_saved;
- int regs_saved_mask = calc_live_regs (®s_saved);
int total_saved_regs_space;
int total_auto_space = get_frame_size ();
+
+ calc_live_regs (®s_saved);
total_saved_regs_space = (regs_saved) * 4;
if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
if (psize == 9 && strncmp (pbuf, "interrupt", 9) == 0)
{
pragma_interrupt = 1;
- return;
+ return c;
}
if (psize == 5 && strncmp (pbuf, "trapa", 5) == 0)
{
pragma_interrupt = pragma_trapa = 1;
- return;
+ return c;
}
c = getc (file);
}
\f
/* insn expand helpers */
-/* Emit insns to perform a call.
+/* Emit insns to perform a call.
If TARGET_SHORTADDR then use a bsr. If TARGET_SMALLCALL, then load the
target address into r1 and call __saveargs, otherwise
perform the standard call sequence */
rtx call_target = operands[isa_retval + 0];
rtx numargs = operands[isa_retval + 1];
- if (TARGET_BSR)
+ if (TARGET_BSR && bsr_operand (call_target, VOIDmode))
{
call = gen_rtx (CALL, VOIDmode, call_target, numargs);
}
- else {
-
- if (GET_CODE (call_target) == MEM)
- {
- call_target = force_reg (Pmode,
- XEXP (call_target, 0));
- }
- if (TARGET_SMALLCALL)
- {
- rtx tmp = gen_reg_rtx (SImode);
- rtx r1 = gen_rtx (REG, SImode, 1);
- emit_move_insn (tmp, gen_rtx (SYMBOL_REF, SImode, "__saveargs"));
- emit_move_insn (r1, call_target);
- emit_insn (gen_rtx (USE, VOIDmode, r1));
- call_target = tmp;
- }
+ else
+ {
+ if (GET_CODE (call_target) == MEM)
+ {
+ call_target = force_reg (Pmode,
+ XEXP (call_target, 0));
+ }
+ if (TARGET_SMALLCALL)
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ rtx r1 = gen_rtx (REG, SImode, 1);
+ emit_move_insn (tmp, gen_rtx (SYMBOL_REF, SImode, "__saveargs"));
+ emit_move_insn (r1, call_target);
+ emit_insn (gen_rtx (USE, VOIDmode, r1));
+ call_target = tmp;
+ }
- call = gen_rtx (CALL, VOIDmode, gen_rtx (MEM, SImode, call_target), numargs);
- }
+ call = gen_rtx (CALL, VOIDmode, gen_rtx (MEM, SImode, call_target), numargs);
+ }
if (isa_retval)
{
call = gen_rtx (SET, VOIDmode, ret, call);
emit_call_insn (gen_rtx (PARALLEL, VOIDmode,
gen_rtvec (2,
call,
- gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 17)))));
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 17)))));
}
\f
GET_CODE (XEXP (op, 0)) == LABEL_REF)
return 1;
- /* No predec allowed */
+ /* No post inc allowed */
if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == PRE_DEC)
+ && (GET_CODE (XEXP (op, 0)) == POST_DEC
+ || GET_CODE (XEXP (op, 0)) == PRE_INC
+ || GET_CODE (XEXP (op, 0)) == PRE_DEC))
+ return 0;
+
+ /* Can't do that with large modes */
+ if (GET_CODE (op) == MEM
+ && GET_CODE (XEXP (op, 0)) == POST_INC
+ && GET_MODE_SIZE (mode) > 4)
return 0;
if ((mode == QImode || mode == HImode)
rtx op;
enum machine_mode mode;
{
+ /* No pre dec allowed */
if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
return 0;
+ if (GET_CODE (op) == MEM
+ && GET_CODE (XEXP (op, 0)) == PRE_DEC
+ && GET_MODE_SIZE (mode) > 4)
+ return 0;
+
return general_operand (op, mode);
}
int
bsr_operand (op, mode)
-rtx op;
-enum machine_mode mode;
+ rtx op;
+ enum machine_mode mode;
{
- if (GET_CODE (op) == SYMBOL_REF)
- return 1;
+ if (TARGET_BSR)
+ {
+ if (GET_CODE (op) == SYMBOL_REF)
+ {
+ if (!strcmp (XSTR (op, 0),
+ IDENTIFIER_POINTER (DECL_NAME (current_function_decl))))
+ return 1;
+ return (seen_function (XSTR (op, 0)));
+ }
+ }
return 0;
}
if (arith_reg_operand (op, mode))
return 1;
#if 0
- Turned off till mac is understood
+ Turned off till mac is understood
if (GET_CODE (op) == MEM)
return 1;
#endif
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
-rtx
+rtx
sh_function_arg (cum, mode, type, named)
-CUMULATIVE_ARGS cum;
-enum machine_mode mode;
-tree type;
-int named;
+ CUMULATIVE_ARGS cum;
+ enum machine_mode mode;
+ tree type;
+ int named;
{
if (named)
{
- int rr = (ROUND_REG ((cum), (mode)));
+ int rr = (ROUND_REG ((cum), (mode)));
if (rr < NPARM_REGS)
{
- return ((((mode) != BLKmode
- && ((type)==0 || ! TREE_ADDRESSABLE ((tree)(type)))
- && ((type)==0 || (mode) != BLKmode
- || (TYPE_ALIGN ((type)) % PARM_BOUNDARY == 0))
- ? gen_rtx (REG, (mode),
- (FIRST_PARM_REG + rr)): 0)));
+ return ((((mode) != BLKmode
+ && ((type) == 0 || !TREE_ADDRESSABLE ((tree) (type)))
+ && ((type) == 0 || (mode) != BLKmode
+ || (TYPE_ALIGN ((type)) % PARM_BOUNDARY == 0))
+ ? gen_rtx (REG, (mode),
+ (FIRST_PARM_REG + rr)) : 0)));
- }
+ }
}
return 0;
}
tree TYPE;
int NAMED;
{
- if ((CUM) < NPARM_REGS)
- {
- if (((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE)))
- && ((TYPE)==0 || (MODE) != BLKmode
- || (TYPE_ALIGN ((TYPE)) % PARM_BOUNDARY == 0))
- && ((CUM) + ((MODE) == BLKmode
- ? ROUND_ADVANCE (int_size_in_bytes (TYPE))
- : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - NPARM_REGS > 0))
+ if ((CUM) < NPARM_REGS)
+ {
+ if (((TYPE) == 0 || !TREE_ADDRESSABLE ((tree) (TYPE)))
+ && ((TYPE) == 0 || (MODE) != BLKmode
+ || (TYPE_ALIGN ((TYPE)) % PARM_BOUNDARY == 0))
+ && ((CUM) + ((MODE) == BLKmode
+ ? ROUND_ADVANCE (int_size_in_bytes (TYPE))
+ : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - NPARM_REGS > 0))
{
return NPARM_REGS - CUM;
}
}
return 0;
}
-
-/* Definitions of target machine for GNU compiler, for Hitachi Super-H.
+/* Definitions of target machine for GNU compiler,
+ for Hitachi Super-H.
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com)
#define CONSTLEN_0_BIT (1<<25)
#define BSR_BIT (1<<26)
#define SHORTADDR_BIT (1<<27)
+#define PACKSTRUCT_BIT (1<<28)
/* Nonzero if we should generate code using type 0 insns */
#define TARGET_SH0 (target_flags & SH0_BIT)
/* Nonzero if using Hitachi's calling convention */
#define TARGET_HITACHI (target_flags & HITACHI_BIT)
+
#define TARGET_PARANOID (target_flags & PARANOID_BIT)
#define TARGET_RETR2 (target_flags & RETR2_BIT)
#define TARGET_SHORTADDR (target_flags & SHORTADDR_BIT)
#define TARGET_BSR (target_flags & BSR_BIT)
+/* Nonzero if packing structures as small as they'll go (incompatible with Hitachi's compiler) */
+#define TARGET_PACKSTRUCT (target_flags & PACKSTRUCT_BIT)
#define TARGET_SWITCHES \
{ {"isize", ( ISIZE_BIT) }, \
{"r2", ( RETR2_BIT) }, \
{"shortaddr", ( SHORTADDR_BIT) }, \
{"bsr", ( BSR_BIT) }, \
+ {"packstruct",( PACKSTRUCT_BIT) }, \
{"", TARGET_DEFAULT} \
}
-#define TARGET_DEFAULT (FAST_BIT)
+#define TARGET_DEFAULT (FAST_BIT | BIGTABLE_BIT)
/* Macro to define table for command options with values. */
#define TARGET_OPTIONS \
if (max_hi) \
max_count_hi = atoi (max_hi); \
else \
- max_count_hi = 505; \
+ max_count_hi = 500; \
if (TARGET_BSR) \
flag_no_function_cse = 1; \
} while (0)
/* The best alignment to use in cases where we have a choice. */
#define FASTEST_ALIGNMENT 32
-/* Every structures size must be a multiple of 32 bits. */
-#define STRUCTURE_SIZE_BOUNDARY 32
-
/* Make strings word-aligned so strcpy from constants will be faster. */
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
((TREE_CODE (EXP) == STRING_CST \
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
&& (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
+/* Number of bits which any structure or union's size must be a
+ multiple of. Each structure or union's size is rounded up to a
+ multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY (TARGET_PACKSTRUCT ? 8 : 32)
+
/* Set this nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
The hardware registers are assigned numbers for the compiler
from 0 to just below FIRST_PSEUDO_REGISTER.
All registers that the compiler knows about must be given numbers,
- even those that are not normally considered general registers.
-
-*/
+ even those that are not normally considered general registers. */
#define AP_REG 16
#define PR_REG 17
/* Nonzero if the constant value X is a legitimate general operand. */
#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE(X) != CONST_DOUBLE && GET_CODE(X) != LABEL_REF)
+ (GET_CODE(X) != CONST_DOUBLE /*&& GET_CODE(X) != LABEL_REF*/)
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
them unless they have been allocated suitable hard regs.
The symbol REG_OK_STRICT causes the latter definition to be used. */
-#define MODE_DISP_OK_4(X,MODE) ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<64))
-#define MODE_DISP_OK_8(X,MODE) ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60))
-#define MODE_DISP_OK_2(X,MODE) ((GET_MODE_SIZE(MODE)==2) && ((unsigned)INTVAL(X)<32) && TARGET_TRYR0)
+#define MODE_DISP_OK_4(X,MODE) ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<64) && (!(INTVAL(X) &3)))
+#define MODE_DISP_OK_8(X,MODE) ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) && (!(INTVAL(X) &3)))
+#define MODE_DISP_OK_2(X,MODE) ((GET_MODE_SIZE(MODE)==2) && ((unsigned)INTVAL(X)<32) && TARGET_TRYR0 && (!INTVAL(X) &1))
#define MODE_DISP_OK_1(X,MODE) ((GET_MODE_SIZE(MODE)==1) && ((unsigned)INTVAL(X)<16) && TARGET_TRYR0)
#ifndef REG_OK_STRICT
(REGNO (X) == 0 || REGNO(X) >= FIRST_PSEUDO_REGISTER)
#define REG_OK_FOR_PRE_POST_P(X) \
- (REG_OK_FOR_INDEX_P (X))
+ (REG_OK_FOR_BASE_P (X))
#else
/* Nonzero if X is a hard reg that can be used as a base reg. */
REGNO_OK_FOR_INDEX_P (REGNO (X))
#define REG_OK_FOR_PRE_POST_P(X) \
- (REGNO_OK_FOR_INDEX_P (REGNO (X)))
+ (REGNO_OK_FOR_BASE_P (REGNO (X)))
#endif
/* The Q is a pc relative load operand */
/* Define this if the tablejump instruction expects the table
to contain offsets from the address of the table.
Do not define this if the table should contain absolute addresses. */
-#define CASE_VECTOR_PC_RELATIVE
+/*#define CASE_VECTOR_PC_RELATIVE */
/* Specify the tree operation to be used to convert reals to integers. */
#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
/* The type of size_t unsigned int. */
#define SIZE_TYPE "unsigned int"
+#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE_SIZE 16
+
/* Don't cse the address of the function being compiled. */
/*#define NO_RECURSIVE_FUNCTION_CSE 1*/
/* How to change between sections. */
-#define TEXT_SECTION_ASM_OP "\t.text"
-#define DATA_SECTION_ASM_OP "\t.data"
-#define CTORS_SECTION_ASM_OP "\t.section\t.ctors\n"
-#define DTORS_SECTION_ASM_OP "\t.section\t.dtors\n"
-#define INIT_SECTION_ASM_OP "\t.section\t.init\n"
-#define EXTRA_SECTIONS in_ctors, in_dtors
-
+#define TEXT_SECTION_ASM_OP "\t.text"
+#define DATA_SECTION_ASM_OP "\t.data"
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rdata\n"
+#define CTORS_SECTION_ASM_OP "\t.section\t.ctors\n"
+#define DTORS_SECTION_ASM_OP "\t.section\t.dtors\n"
+#define INIT_SECTION_ASM_OP "\t.section\t.init\n"
+#define EXTRA_SECTIONS in_ctors, in_dtors, in_rdata
+#define READONLY_DATA_SECTION rdata_section
#define EXTRA_SECTION_FUNCTIONS \
void \
ctors_section() \
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
in_section = in_dtors; \
} \
+} \
+void \
+rdata_section() \
+{ \
+ if (in_section != in_rdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \
+ in_section = in_rdata; \
+ } \
}
/* Assemble generic sections.
#define TARGET_MEM_FUNCTIONS
-#define HANDLE_PRAGMA(finput) handle_pragma (finput)
+#define HANDLE_PRAGMA(finput) return handle_pragma (finput)
/* Set when processing a function with pragma interrupt turned on. */
(cond [(eq_attr "type" "cbranch") (const_string "no")
(eq_attr "type" "jump") (const_string "no")
(eq_attr "type" "pload") (const_string "no")
+ (eq_attr "type" "pcloadsi") (const_string "no")
+ (eq_attr "type" "pcloadhi") (const_string "no")
(eq_attr "type" "return") (const_string "no")
(eq_attr "length" "2") (const_string "yes")
(eq_attr "length" "4,6,8,10,12") (const_string "no")
] (const_string "yes")))
+
\f
;; -------------------------------------------------------------------------
;; SImode signed integer comparisons
;; Addition instructions
;; -------------------------------------------------------------------------
-(define_insn "addc"
- [(set (match_operand:SI 0 "arith_reg_operand" "=r")
- (plus:SI (reg:SI 18)
- (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
- (match_operand:SI 2 "arith_reg_operand" "r"))))
- (set (reg:SI 18) (gt:SI (match_dup 1) (match_dup 0)))]
- ""
- "addc %2,%0")
;; this should be a define split.
+
+
+(define_insn "addc"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (plus:SI (match_dup 0)
+ (plus:SI (match_operand:SI 1 "arith_reg_operand" "r")
+ (reg:SI 18))))
+ (clobber (reg:SI 18))]
+ ""
+ "addc %1,%0")
+
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
""
"
{
- rtx low_a = gen_rtx (SUBREG, SImode, operands[1], 1);
- rtx low_b = gen_rtx (SUBREG, SImode, operands[2], 1);
- rtx low_s = gen_rtx (SUBREG, SImode, operands[0], 1);
+ rtx low_a = operand_subword (operands[1], 1, 1, DImode);
+ rtx low_b = operand_subword (operands[2], 1, 1, DImode);
+ rtx low_s = operand_subword (operands[0], 1, 1, DImode);
- rtx high_a = gen_rtx (SUBREG, SImode, operands[1], 0);
- rtx high_b = gen_rtx (SUBREG, SImode, operands[2], 0);
- rtx high_s = gen_rtx (SUBREG, SImode, operands[0], 0);
+ rtx high_a = operand_subword (operands[1], 0, 1, DImode);
+ rtx high_b = operand_subword (operands[2], 0, 1, DImode);
+ rtx high_s = operand_subword (operands[0], 0, 1, DImode);
emit_insn (gen_clrt ());
- emit_insn (gen_addc (low_s, low_a, low_b));
- emit_insn (gen_addc (high_s, high_a, high_b));
+
+ emit_move_insn (low_s, low_a);
+ emit_insn (gen_addc (low_s, low_b));
+ emit_move_insn (high_s, high_a);
+ emit_insn (gen_addc (high_s, high_b));
DONE;
}")
;; Subtraction instructions
;; -------------------------------------------------------------------------
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "arith_reg_operand" "=r")
- (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
- (match_operand:DI 2 "arith_reg_operand" "r")))
+
+(define_insn "subc"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (minus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
+ (plus:SI (match_operand:SI 2 "arith_reg_operand" "r")
+ (reg:SI 18))))
(clobber (reg:SI 18))]
""
- "clrt\;subc %R2,%R0\;subc %2,%0"
- [(set_attr "length" "6")
- (set_attr "in_delay_slot" "no")
- (set_attr "type" "arith")])
+ "subc %2,%0")
+
+(define_expand "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))]
+ ""
+ "
+{
+ rtx low_a = operand_subword (operands[1], 1, 1, DImode);
+ rtx low_b = operand_subword (operands[2], 1, 1, DImode);
+ rtx low_s = operand_subword (operands[0], 1, 1, DImode);
+
+ rtx high_a = operand_subword (operands[1], 0, 1, DImode);
+ rtx high_b = operand_subword (operands[2], 0, 1, DImode);
+ rtx high_s = operand_subword (operands[0], 0, 1, DImode);
+
+ emit_insn (gen_clrt ());
+ emit_insn (gen_subc (low_s, low_a, low_b));
+ emit_insn (gen_subc (high_s, high_a, high_b));
+
+ DONE;
+}")
(define_insn "subsi3"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(set (match_operand:SI 0 "arith_reg_operand" "=r")
(reg:SI 21))]
"TARGET_SH2"
- "
-{
- if (!TARGET_SH2)
- {
- emit_insn (gen_mulsi3_call (operands[0], operands[1], operands[2]));
- DONE;
- }
-}")
+ "")
(define_insn ""
[(set (reg:DI 20)
(define_insn "ashldi3_k"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
(ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
- (match_operand:DI 2 "immediate_operand" "I")))
+ (const_int 1)))
(clobber (reg:SI 18))]
""
"shll %R0\;rotcl %0"
(define_insn "lshrdi3_k"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
- (match_operand:DI 2 "immediate_operand" "I")))
+ (const_int 1)))
(clobber (reg:SI 18))]
""
"shlr %0\;rotcr %R0"
(define_insn "ashrdi3_k"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
- (match_operand:DI 2 "immediate_operand" "")))
+ (const_int 1)))
(clobber (reg:SI 18))]
""
"shar %0\;rotcr %R0"
;; Unary arithmetic
;; -------------------------------------------------------------------------
-(define_insn "negdi2"
- [(set (match_operand:DI 0 "arith_reg_operand" "=&r")
- (neg:DI (match_operand:DI 1 "arith_reg_operand" "0")))
- (clobber (reg:SI 18))]
+
+(define_insn "negc"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (neg:SI (plus:SI (reg:SI 18) (match_operand:SI 1 "arith_reg_operand" "r"))))]
""
- "clrt\;negc %R1,%R0\;negc %1,%0"
- [(set_attr "length" "6")
+ "negc %1,%0"
+ [(set_attr "length" "2")
(set_attr "type" "arith")])
+(define_expand "negdi2"
+ [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+ (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))
+ (clobber (reg:SI 18))]
+ ""
+ "{
+ rtx low_src = operand_subword (operands[1], 1, 0, DImode);
+ rtx high_src = operand_subword (operands[1], 0, 0, DImode);
+
+ rtx low_dst = operand_subword (operands[0], 1, 1, DImode);
+ rtx high_dst = operand_subword (operands[0], 0, 1, DImode);
+
+ emit_insn (gen_clrt ());
+ emit_insn (gen_negc (low_dst, low_src));
+ emit_insn (gen_negc (high_dst, high_src));
+ DONE;
+ }
+ ")
+
+
(define_insn "negsi2"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
[(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,<m,<,xl,xl,t,r")
(match_operand:SI 1 "general_movsrc_operand" "Q,rI,>m,xl,t,r,xl,r,>,r,i"))]
""
- "*
-{
- switch (which_alternative)
- {
- case 0:
- switch (get_attr_length(insn))
- {
- case 2:
- return \"mov.l %1,%0\";
- case 12:
- return \"mov.l TA%*,%0\;bra TB%*\;mov.l @%0,%0\;.align 2\;TA%*: .long %1\;TB%*:%^\";
- }
- case 1: return \"mov %1,%0\";
- case 2: return \"mov.l %1,%0\";
- case 3: return \"sts %1,%0\";
- case 4: return \"movt %0\";
- case 5: return \"mov.l %1,%0\";
- case 6: return \"sts.l %1,%0\";
- case 7: return \"lds %1,%0\";
- case 8: return \"lds.l %1,%0\";
- case 9: return \"tst %1,%1\;bt T%*\;bra F%*\;sett\;T%*:clrt\;F%*:%^\";
- case 10: return \"fake %1,%0\";
- }
-}"
- [(set_attr "length" "*,2,2,2,2,2,2,2,2,6,2")
- (set_attr "type" "pcloadsi,move,load,move,store,store,move,load,move,move,move")])
+ "@
+ mov.l %1,%0
+ mov %1,%0
+ mov.l %1,%0
+ sts %1,%0
+ movt %0
+ mov.l %1,%0
+ sts.l %1,%0
+ lds %1,%0
+ lds.l %1,%0
+ tst %1,%1\;bt T%*\;bra F%*\;sett\;T%*:clrt\;F%*:%^
+ fake %1,%0"
+ [(set_attr "type" "pcloadsi,move,load,move,store,store,move,load,move,move,move")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_movdst_operand" "")
[(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,<m,r,r,l")
(match_operand:HI 1 "general_movsrc_operand" "Q,rI,>m,t,r,i,l,r"))]
""
- "*
-{
- switch (which_alternative)
- {
- case 0:
- switch (get_attr_length(insn))
- {
- case 2:
- return \"mov.w %1,%0\";
- case 12:
- return \"mov.l TA%*,%0\;bra TB%*\;mov.w @%0,%0\;.align 2\;TA%*: .long %1\;TB%*:%^\";
- }
- case 1: return \"mov %1,%0\";
- case 2: return \"mov.w %1,%0\";
- case 3: return \"movt %0\";
- case 4: return \"mov.w %1,%0\";
- case 5: return \"fake %1,%0\";
- case 6: return \"sts %1,%0\";
- case 7: return \"lds %1,%0\";
- }
-}"
+ "@
+ mov.w %1,%0
+ mov %1,%0
+ mov.w %1,%0
+ movt %0
+ mov.w %1,%0
+ fake %1,%0
+ sts %1,%0
+ lds %1,%0"
[(set_attr "length" "*,2,2,2,2,2,2,2")
(set_attr "type" "pcloadhi,move,load,move,store,move,move,move")])
[(set_attr "length" "*,4,4,4,4")
(set_attr "type" "pcloadsi,move,load,store,move")])
+;; If the output is a register and the input is memory, we have to be careful
+;; and see which word needs to be loaded first.
+;;
+(define_split
+ [(set (match_operand:DI 0 "general_movdst_operand" "")
+ (match_operand:DI 1 "general_movsrc_operand" ""))]
+ "! (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
+ && ! (GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+ && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
+ && ! reload_completed
+ && reg_overlap_mentioned_p (operands[0], operands[1]))"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 5))]
+ "
+{ if (GET_CODE (operands[0]) != REG
+ || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+ operands[1], 0))
+ {
+ operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[1], 0, 0, DImode);
+ operands[4] = operand_subword (operands[0], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);
+ }
+ else
+ {
+ operands[2] = operand_subword (operands[0], 1, 0, DImode);
+ operands[3] = operand_subword (operands[1], 1, 0, DImode);
+ operands[4] = operand_subword (operands[0], 0, 0, DImode);
+ operands[5] = operand_subword (operands[1], 0, 0, DImode);
+ }
+
+ if (operands[2] == 0 || operands[3] == 0
+ || operands[4] == 0 || operands[5] == 0)
+ FAIL;
+}")
(define_expand "movdi"
[(set_attr "length" "4")
(set_attr "type" "move,load,store")])
+;; If the output is a register and the input is memory, we have to be careful
+;; and see which word needs to be loaded first.
+;;
+(define_split
+ [(set (match_operand:DF 0 "general_movdst_operand" "")
+ (match_operand:DF 1 "general_movsrc_operand" ""))]
+ "! (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
+ && ! (GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+ && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
+ && ! reload_completed
+ && reg_overlap_mentioned_p (operands[0], operands[1]))"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 5))]
+ "
+{ if (GET_CODE (operands[0]) != REG
+ || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+ operands[1], 0))
+ {
+ operands[2] = operand_subword (operands[0], 0, 0, DFmode);
+ operands[3] = operand_subword (operands[1], 0, 0, DFmode);
+ operands[4] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[5] = operand_subword (operands[1], 1, 0, DFmode);
+ }
+ else
+ {
+ operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[3] = operand_subword (operands[1], 1, 0, DFmode);
+ operands[4] = operand_subword (operands[0], 0, 0, DFmode);
+ operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+ }
+
+ if (operands[2] == 0 || operands[3] == 0
+ || operands[4] == 0 || operands[5] == 0)
+ FAIL;
+}")
+
+
(define_expand "movdf"
[(set (match_operand:DF 0 "general_movdst_operand" "")
(match_operand:DF 1 "general_movsrc_operand" ""))]
(const_int 1))
(label_ref (match_operand 4 "" ""))
(pc)))
- (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 5)))
+ (parallel[(set (match_dup 5) (ashift:SI (match_dup 5) (const_int 2)))
+ (clobber (reg:SI 18))])
(set (reg:SI 0) (label_ref (match_operand 3 "" "")))
- (parallel[(set (reg:SI 0) (plus:SI (reg:SI 0)
- (mem:HI (plus:SI (reg:SI 0)
- (match_dup 6)))))
- (set (match_dup 6) (mem:HI (plus:SI (reg:SI 0) (match_dup 6))))])
+ (set (reg:SI 0) (mem:SI (plus:SI (reg:SI 0) (match_dup 5))))
+
+;; (parallel[(set (reg:SI 0) (plus:SI (reg:SI 0)
+;; (mem:HI (plus:SI (reg:SI 0)
+;; (match_dup 5)))))
+;; (set (match_dup 6) (mem:HI (plus:SI (reg:SI 0) (match_dup 6))))])
(set (pc) (reg:SI 0))]
""
"
operands[1] = copy_to_mode_reg (SImode, operands[1]);
operands[2] = copy_to_mode_reg (SImode, operands[2]);
operands[5] = gen_reg_rtx (SImode);
- operands[6] = gen_reg_rtx (SImode);
+
}")
(define_insn "casesi_worker"
"mov.w @(r0,%0),%0\;add %0,r0"
[(set_attr "needs_delay_slot" "no")
(set_attr "in_delay_slot" "no")
- (set_attr "length" "6")])
+ (set_attr "length" "4")])
(define_insn "return"