From: Steve Chamberlain Date: Fri, 22 Jul 1994 06:12:36 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8e87e1611c6cb4598c35a139432f069653f4adad;p=gcc.git *** empty log message *** From-SVN: r7790 --- diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5999f8a0137..28d0d4b5e69 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -65,12 +65,12 @@ rtx sh_compare_op1; 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 @@ -104,12 +104,12 @@ enum reg_class reg_class_from_letter[] = 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 @@ -120,9 +120,9 @@ static int lf = 100; /* Number of bytes pushed for anonymous args, used to pass information between expand_prologue and expand_epilogue. */ static int extra_push; - + void push (rn) int rn; @@ -132,6 +132,7 @@ push (rn) void pop (rn) + int rn; { emit_insn (gen_pop (gen_rtx (REG, SImode, rn))); } @@ -299,7 +300,6 @@ print_operand_address (stream, x) default: debug_rtx (x); - abort (); } } @@ -354,9 +354,9 @@ print_operand (stream, x, code) 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 */ @@ -405,7 +405,9 @@ print_operand (stream, x, code) } +static int sextb (x) + int x; { x &= 0xff; if (x > 127) @@ -420,7 +422,7 @@ sextb (x) /* 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 @@ -442,7 +444,7 @@ sextb (x) 00000000 00000000 11111111 1NNNNNNNN load and zero extend word -*/ +*/ static int synth_constant (operands, mode) @@ -452,7 +454,7 @@ 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) @@ -460,11 +462,11 @@ synth_constant (operands, mode) if (mode != SImode) { - if (reload_in_progress) + if (reload_in_progress) return 0; dst = gen_reg_rtx (SImode); } - else + else { dst = operands[0]; } @@ -592,10 +594,8 @@ expand_block_move (operands) } 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); @@ -670,7 +670,7 @@ prepare_move_operands (operands, mode) /* 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); @@ -740,6 +740,7 @@ prepare_move_operands (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) @@ -863,6 +864,10 @@ output_movedouble (insn, operands, mode) { 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 (); @@ -1022,11 +1027,6 @@ output_far_jump (insn, op) { 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 @@ -1041,7 +1041,8 @@ output_far_jump (insn, op) 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; } @@ -1072,9 +1073,8 @@ output_branch (logic, insn) { 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)) { @@ -1245,7 +1245,7 @@ add_constant (x, mode) /* Dump out interesting debug info */ -rtx +void final_prescan_insn (insn, opvec, noperands) rtx insn; rtx *opvec; @@ -1258,9 +1258,9 @@ final_prescan_insn (insn, opvec, noperands) insn_addresses[INSN_UID (insn)]); } } + - /* Stuff taken from m88k.c */ @@ -1365,7 +1365,7 @@ output_file_start (file, f_options, f_len, W_options, W_len) 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"); } @@ -1393,7 +1393,7 @@ shiftcosts (RTX) return 1; } -int +int andcosts (RTX) rtx RTX; { @@ -1410,28 +1410,33 @@ andcosts (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; } @@ -1442,14 +1447,14 @@ multcosts (RTX) 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) @@ -1458,7 +1463,7 @@ multcosts (RTX) 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; @@ -1467,7 +1472,7 @@ multcosts (RTX) /* 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; @@ -1627,7 +1632,6 @@ dump_table (scan) rtx scan; { int i; - int pass; int need_align = 1; @@ -1706,6 +1710,10 @@ fixit (src, mode) { return 1; } + if (GET_CODE (src) == LABEL_REF) + { + return 1; + } if (GET_CODE (src) == CONST_INT) { /* All QI insns are ok */ @@ -1740,17 +1748,18 @@ hi_const (src) /* 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) @@ -1786,11 +1795,14 @@ find_barrier (from) 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); } @@ -1836,7 +1848,6 @@ machine_dependent_reorg (first) rtx first; { rtx insn; - int limit; for (insn = first; insn; insn = NEXT_INSN (insn)) { if (broken_move (insn)) @@ -1895,7 +1906,7 @@ machine_dependent_reorg (first) /* Called from the md file, set up the operands of a compare instruction */ -int +void from_compare (operands, code) rtx *operands; int code; @@ -1905,7 +1916,7 @@ from_compare (operands, 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; @@ -1923,33 +1934,67 @@ equality_operator (x, mode) } -/* 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 @@ -1957,7 +2002,7 @@ sh_expand_prologue () { 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 @@ -1984,6 +2029,12 @@ sh_expand_prologue () { emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); } + if (TARGET_BSR) + { + add_function (IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); + } + + } void @@ -2027,11 +2078,14 @@ sh_expand_epilogue () 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) @@ -2074,12 +2128,12 @@ handle_pragma (file) 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); } @@ -2088,7 +2142,7 @@ handle_pragma (file) /* 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 */ @@ -2103,29 +2157,29 @@ expand_acall (isa_retval, operands) 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); @@ -2134,7 +2188,7 @@ expand_acall (isa_retval, operands) 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))))); } @@ -2156,10 +2210,18 @@ general_movsrc_operand (op, mode) 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) @@ -2185,12 +2247,18 @@ general_movdst_operand (op, mode) 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); } @@ -2200,11 +2268,19 @@ general_movdst_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; } @@ -2329,7 +2405,7 @@ mac_operand (op, mode) 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 @@ -2349,27 +2425,27 @@ mac_operand (op, mode) 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; } @@ -2387,18 +2463,17 @@ sh_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED) 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; } - diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 23259cbfac7..aafa931eeb4 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1,4 +1,5 @@ -/* 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) @@ -83,6 +84,7 @@ extern int target_flags; #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) @@ -141,11 +143,14 @@ extern int target_flags; /* 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) }, \ @@ -170,10 +175,11 @@ extern int target_flags; {"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 \ @@ -206,7 +212,7 @@ do { \ 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) @@ -264,9 +270,6 @@ do { \ /* 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 \ @@ -279,6 +282,11 @@ do { \ && 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 @@ -305,9 +313,7 @@ do { \ 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 @@ -867,7 +873,7 @@ extern int current_function_anonymous_args; /* 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 @@ -877,9 +883,9 @@ extern int current_function_anonymous_args; 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 @@ -896,7 +902,7 @@ extern int current_function_anonymous_args; (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. */ @@ -908,7 +914,7 @@ extern int current_function_anonymous_args; 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 */ @@ -1039,7 +1045,7 @@ extern int current_function_anonymous_args; /* 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 @@ -1053,6 +1059,9 @@ extern int current_function_anonymous_args; /* 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*/ @@ -1195,13 +1204,14 @@ extern int current_function_anonymous_args; /* 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() \ @@ -1220,6 +1230,15 @@ dtors_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. @@ -1462,7 +1481,7 @@ extern char *output_far_jump(); #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. */ diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 794fe457f1d..397fc0fb507 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -158,11 +158,14 @@ (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"))) + ;; ------------------------------------------------------------------------- ;; SImode signed integer comparisons @@ -259,18 +262,21 @@ ;; 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" "") @@ -278,17 +284,20 @@ "" " { - 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; }") @@ -314,16 +323,37 @@ ;; 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") @@ -504,14 +534,7 @@ (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) @@ -769,7 +792,7 @@ (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" @@ -788,7 +811,7 @@ (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" @@ -806,7 +829,7 @@ (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" @@ -826,15 +849,35 @@ ;; 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")))] @@ -982,32 +1025,19 @@ [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,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" "") @@ -1042,27 +1072,15 @@ [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,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")]) @@ -1089,6 +1107,43 @@ [(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" @@ -1114,6 +1169,45 @@ [(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" ""))] @@ -1443,12 +1537,15 @@ (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))] "" " @@ -1456,7 +1553,7 @@ 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" @@ -1470,7 +1567,7 @@ "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"