]> gcc.gnu.org Git - gcc.git/commitdiff
rtl.h (addr_diff_vec_flags): New typedef.
authorJoern Rennecke <amylaar@gcc.gnu.org>
Fri, 6 Mar 1998 14:54:07 +0000 (14:54 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Fri, 6 Mar 1998 14:54:07 +0000 (14:54 +0000)
* rtl.h (addr_diff_vec_flags): New typedef.
(union rtunion_def): New member rt_addr_diff_vec_flags.
(ADDR_DIFF_VEC_FLAGS): New macro.
* sh.c (output_branch): Fix offset overflow problems.
* final.c (shorten_branches): Implement CASE_VECTOR_SHORTEN_MODE.
(final_scan_insn): New argument BODY for ASM_OUTPUT_ADDR_DIFF_ELT.
* rtl.def (ADDR_DIFF_VEC): Three new fields (min, max and flags).
* stmt.c (expand_end_case): Supply new arguments to
gen_rtx_ADDR_DIFF_VEC.
* 1750a.h (ASM_OUTPUT_ADDR_DIFF_ELT): New argument BODY.
* alpha.h, arc.h, clipper.h, convex.h : Likewise.
* dsp16xx.h, elxsi.h, fx80.h, gmicro.h, h8300.h : Likewise.
* i370.h, i386.h, i860.h, i960.h, m32r.h, m68k.h, m88k.h : Likewise.
* mips.h, mn10200.h, mn10300.h, ns32k.h, pa.h, pyr.h : Likewise.
* rs6000.h, sh.h, sparc.h, spur.h, tahoe.h, v850.h : Likewise.
* vax.h, we32k.h, alpha/vms.h, arm/aof.h, arm/aout.h : Likewise.
* i386/386bsd.h, i386/freebsd-elf.h : Likewise.
* i386/freebsd.h, i386/linux.h : Likewise.
* i386/netbsd.h, i386/osfrose.h, i386/ptx4-i.h, i386/sco5.h : Likewise.
* i386/sysv4.h, m68k/3b1.h, m68k/dpx2.h, m68k/hp320.h : Likewise.
* m68k/mot3300.h, m68k/sgs.h : Likewise.
* m68k/tower-as.h, ns32k/encore.h, sparc/pbd.h : Likewise.
* sh.h (INSN_ALIGN, INSN_LENGTH_ALIGNMENT): Define.
(CASE_VECTOR_SHORTEN_MODE): Define.
(short_cbranch_p, align_length, addr_diff_vec_adjust): Don't declare.
(med_branch_p, braf_branch_p): Don't declare.
(mdep_reorg_phase, barrier_align): Declare.
(ADJUST_INSN_LENGTH): Remove alignment handling.
* sh.c (uid_align, uid_align_max): Deleted.
(max_uid_before_fixup_addr_diff_vecs, branch_offset): Deleted.
(short_cbranch_p, med_branch_p, braf_branch_p, align_length): Deleted.
(cache_align_p, fixup_aligns, addr_diff_vec_adjust): Deleted.
(output_far_jump): Don't use braf_branch_p.
(output_branchy_insn): Don't use branch_offset.
(find_barrier): Remove checks for max_uid_before_fixup_addr_diff_vecs.
Remove paired barrier stuff.
Don't use cache_align_p.
Take alignment insns into account.
(fixup_addr_diff_vecs): Reduce to only fixing up the base label of
the addr_diff_vec.
(barrier_align, branch_dest): New function.
(machine_dependent_reorg, split_branches): Remove infrastructure
for branch shortening that is now provided in the backend.
* sh.md (short_cbranch_p, med_branch_p, med_cbranch_p): New attributes.
(braf_branch_p, braf_cbranch_p): Likewise.
(attribute length): Use new attributes.
(casesi_worker): Get mode and unsignednedd from ADDR_DIFF_VEC.
(addr_diff_vec_adjust): Delete.
(align_2): Now a define_expand.
(align_log): Now length 0.

From-SVN: r18433

60 files changed:
gcc/ChangeLog
gcc/config/1750a/1750a.h
gcc/config/alpha/alpha.h
gcc/config/alpha/vms.h
gcc/config/arc/arc.h
gcc/config/arm/aof.h
gcc/config/arm/aout.h
gcc/config/clipper/clipper.h
gcc/config/convex/convex.h
gcc/config/dsp16xx/dsp16xx.h
gcc/config/elxsi/elxsi.h
gcc/config/fx80/fx80.h
gcc/config/gmicro/gmicro.h
gcc/config/h8300/h8300.h
gcc/config/i370/i370.h
gcc/config/i386/386bsd.h
gcc/config/i386/freebsd-elf.h
gcc/config/i386/freebsd.h
gcc/config/i386/i386.h
gcc/config/i386/linux.h
gcc/config/i386/netbsd.h
gcc/config/i386/osfrose.h
gcc/config/i386/ptx4-i.h
gcc/config/i386/sco5.h
gcc/config/i386/sysv4.h
gcc/config/i860/i860.h
gcc/config/i960/i960.h
gcc/config/m32r/m32r.h
gcc/config/m68k/3b1.h
gcc/config/m68k/dpx2.h
gcc/config/m68k/hp320.h
gcc/config/m68k/m68k.h
gcc/config/m68k/mot3300.h
gcc/config/m68k/sgs.h
gcc/config/m68k/tower-as.h
gcc/config/m88k/m88k.h
gcc/config/mips/mips.h
gcc/config/mn10200/mn10200.h
gcc/config/mn10300/mn10300.h
gcc/config/ns32k/encore.h
gcc/config/ns32k/ns32k.h
gcc/config/pa/pa.h
gcc/config/pyr/pyr.h
gcc/config/rs6000/rs6000.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sh/sh.md
gcc/config/sparc/pbd.h
gcc/config/sparc/sparc.h
gcc/config/spur/spur.h
gcc/config/tahoe/tahoe.h
gcc/config/v850/v850.h
gcc/config/vax/vax.h
gcc/config/we32k/we32k.h
gcc/final.c
gcc/rtl.def
gcc/rtl.h
gcc/rtl.texi
gcc/stmt.c
gcc/tm.texi

index 0912af57b8f74bab64a4d3e0bd5f54dc670ae007..00f842f9c4ddd0293fbddf67410590bcc653730e 100644 (file)
@@ -1,3 +1,58 @@
+Fri Mar  6 21:28:45 1998  J"orn Rennecke <amylaar@cygnus.co.uk>
+
+       * rtl.h (addr_diff_vec_flags): New typedef.
+       (union rtunion_def): New member rt_addr_diff_vec_flags.
+       (ADDR_DIFF_VEC_FLAGS): New macro.
+
+       * sh.c (output_branch): Fix offset overflow problems.
+
+       * final.c (shorten_branches): Implement CASE_VECTOR_SHORTEN_MODE.
+       (final_scan_insn): New argument BODY for ASM_OUTPUT_ADDR_DIFF_ELT.
+       * rtl.def (ADDR_DIFF_VEC): Three new fields (min, max and flags).
+       * stmt.c (expand_end_case): Supply new arguments to
+       gen_rtx_ADDR_DIFF_VEC.
+       * 1750a.h (ASM_OUTPUT_ADDR_DIFF_ELT): New argument BODY.
+       * alpha.h, arc.h, clipper.h, convex.h : Likewise.
+       * dsp16xx.h, elxsi.h, fx80.h, gmicro.h, h8300.h : Likewise.
+       * i370.h, i386.h, i860.h, i960.h, m32r.h, m68k.h, m88k.h : Likewise.
+       * mips.h, mn10200.h, mn10300.h, ns32k.h, pa.h, pyr.h : Likewise.
+       * rs6000.h, sh.h, sparc.h, spur.h, tahoe.h, v850.h : Likewise.
+       * vax.h, we32k.h, alpha/vms.h, arm/aof.h, arm/aout.h : Likewise.
+       * i386/386bsd.h, i386/freebsd-elf.h : Likewise.
+       * i386/freebsd.h, i386/linux.h : Likewise.
+       * i386/netbsd.h, i386/osfrose.h, i386/ptx4-i.h, i386/sco5.h : Likewise.
+       * i386/sysv4.h, m68k/3b1.h, m68k/dpx2.h, m68k/hp320.h : Likewise.
+       * m68k/mot3300.h, m68k/sgs.h : Likewise.
+       * m68k/tower-as.h, ns32k/encore.h, sparc/pbd.h : Likewise.
+       * sh.h (INSN_ALIGN, INSN_LENGTH_ALIGNMENT): Define.
+       (CASE_VECTOR_SHORTEN_MODE): Define.
+       (short_cbranch_p, align_length, addr_diff_vec_adjust): Don't declare.
+       (med_branch_p, braf_branch_p): Don't declare.
+       (mdep_reorg_phase, barrier_align): Declare.
+       (ADJUST_INSN_LENGTH): Remove alignment handling.
+       * sh.c (uid_align, uid_align_max): Deleted.
+       (max_uid_before_fixup_addr_diff_vecs, branch_offset): Deleted.
+       (short_cbranch_p, med_branch_p, braf_branch_p, align_length): Deleted.
+       (cache_align_p, fixup_aligns, addr_diff_vec_adjust): Deleted.
+       (output_far_jump): Don't use braf_branch_p.
+       (output_branchy_insn): Don't use branch_offset.
+       (find_barrier): Remove checks for max_uid_before_fixup_addr_diff_vecs.
+       Remove paired barrier stuff.
+       Don't use cache_align_p.
+       Take alignment insns into account.
+       (fixup_addr_diff_vecs): Reduce to only fixing up the base label of
+       the addr_diff_vec.
+       (barrier_align, branch_dest): New function.
+       (machine_dependent_reorg, split_branches): Remove infrastructure
+       for branch shortening that is now provided in the backend.
+       * sh.md (short_cbranch_p, med_branch_p, med_cbranch_p): New attributes.
+       (braf_branch_p, braf_cbranch_p): Likewise.
+       (attribute length): Use new attributes.
+       (casesi_worker): Get mode and unsignednedd from ADDR_DIFF_VEC.
+       (addr_diff_vec_adjust): Delete.
+       (align_2): Now a define_expand.
+       (align_log): Now length 0.
+
 Fri Mar  6 14:41:33 1998  Michael Meissner  <meissner@cygnus.com>
 
        * m32r.md (right): Correctly check for length == 2, not 1.
@@ -2670,7 +2725,7 @@ Fri Dec 19 17:31:11 1997  Ian Lance Taylor  <ian@cygnus.com>
        * stmt.c (expand_end_case): Likewise.
        * alpha.h (CASE_VECTOR_PC_RELATIVE): Update.
        * fx80.h, gmicro.h, m68k.h, m88k.h, ns32k.h: Likewise.
-       * rs6000.h, sh.h, tahoe.h, v850.h vax.h z8k.h: Likewise.
+       * rs6000.h, sh.h, tahoe.h, v850.h, vax.h: Likewise.
 
 Tue Dec 16 15:14:09 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
 
index 1ed9072fe95e0ba5de4c02f07094d139aabeaf4c..ad6c4be9c2e684515e8072d0472ba663009c9f61 100644 (file)
@@ -1265,7 +1265,7 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
        fprintf (FILE, "\tdata\tL%d-L%d ;addr_diff_elt\n", VALUE,REL)
 
 /* This is how to output an assembler line
index 0e02a640801f6fee56ede1d669a7ac07d80ef3ef..3e52db740ad1e9ee96d6a98a8377ac1fe22b93d2 100644 (file)
@@ -1984,7 +1984,7 @@ literal_section ()                                                \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.%s $L%d\n", TARGET_WINDOWS_NT ? "long" : "gprel32", \
           (VALUE))
 
index 2ef5de1ada16d6830c85f59c5a2b849373b27095..d43a60d67a2e00ae734aa43f2e2494035da0fbcb 100644 (file)
@@ -324,7 +324,7 @@ literals_section ()                                         \
 }
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort ()
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) abort ()
 
 #undef ASM_OUTPUT_ADDR_VEC_ELT
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
index 98b39e20ff577b010d38d2697083a67f33ac813c..3d7f2b2910f5823477ac2c9f1a5264c0fd4b7b24 100644 (file)
@@ -1492,7 +1492,7 @@ do {                                                      \
 } while (0)
 
 /* This is how to output an element of a case-vector that is relative.  */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
 do {                                                   \
   char label[30];                                      \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);     \
index ab9093d068c97b98816fbe9a89b42334bd4404d8..6c2185007f92d7738ca671e9388d84b12c4e6d18 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler, for Advanced RISC Machines
    ARM compilation, AOF Assembler.
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rearnsha@armltd.co.uk)
 
 This file is part of GNU CC.
@@ -60,12 +60,13 @@ char *aof_text_section ();
 char *aof_data_section ();
 #define DATA_SECTION_ASM_OP aof_data_section ()
 
-#define EXTRA_SECTIONS in_zero_init, in_ctor, in_dtor
+#define EXTRA_SECTIONS in_zero_init, in_ctor, in_dtor, in_common
 
 #define EXTRA_SECTION_FUNCTIONS        \
 ZERO_INIT_SECTION              \
 CTOR_SECTION                   \
-DTOR_SECTION
+DTOR_SECTION                   \
+COMMON_SECTION
 
 #define ZERO_INIT_SECTION                                      \
 void                                                           \
@@ -118,6 +119,18 @@ dtor_section ()                                                            \
     }                                                                  \
 }
 
+/* Used by ASM_OUTPUT_COMMON (below) to tell varasm.c that we've
+   changed areas.  */
+#define COMMON_SECTION                                         \
+void                                                           \
+common_section ()                                              \
+{                                                              \
+  static int common_count = 1;                                 \
+  if (in_section != in_common)                                 \
+    {                                                          \
+      in_section = in_common;                                  \
+    }                                                          \
+}
 #define CTOR_LIST_BEGIN                                        \
 asm (CTORS_SECTION_ASM_OP);                            \
 extern func_ptr __CTOR_END__[1];                       \
@@ -194,7 +207,7 @@ do {                                        \
 /* Some systems use __main in a way incompatible with its use in gcc, in these
    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
    give the same symbol without quotes for an alternative entry point.  You
-   must define both, or niether. */
+   must define both, or neither. */
 #define NAME__MAIN "__gccmain"
 #define SYMBOL__MAIN __gccmain
 
@@ -277,7 +290,8 @@ do {                                                        \
 /* Output of Uninitialized Variables */
 
 #define ASM_OUTPUT_COMMON(STREAM,NAME,SIZE,ROUNDED)            \
-  (fprintf ((STREAM), "\tAREA "),                              \
+  (common_section (),                                          \
+   fprintf ((STREAM), "\tAREA "),                              \
    assemble_name ((STREAM), (NAME)),                           \
    fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \
            (ROUNDED), ASM_COMMENT_START, SIZE))
@@ -302,7 +316,7 @@ do {                                                        \
     arm_main_function = 1;                             \
 } while (0)
 
-#define ARM_OUTPUT_LABEL(STREAM,NAME)  \
+#define ASM_OUTPUT_LABEL(STREAM,NAME)  \
 do {                                   \
   assemble_name (STREAM,NAME);         \
   fputs ("\n", STREAM);                        \
@@ -408,7 +422,7 @@ do {                                                \
 
 /* Output of Dispatch Tables */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL)             \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL)                \
   fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE))
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)  \
index 7bddb1f5242c146ebf37264f5d61d1d01833cb76..5d3d78959be8bb9f86f3fe6dd09a9fd32a523b1b 100644 (file)
@@ -114,7 +114,7 @@ do {                                                                        \
 #define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
     ASM_OUTPUT_LABEL(STREAM, NAME)
 
-#define ARM_OUTPUT_LABEL(STREAM,NAME)  \
+#define ASM_OUTPUT_LABEL(STREAM,NAME)  \
 do {                                   \
   assemble_name (STREAM,NAME);         \
   fputs (":\n", STREAM);               \
@@ -143,7 +143,7 @@ do {                                        \
 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)  \
    fprintf (STREAM, "\t.word\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL)  \
    fprintf (STREAM, "\tb\t%sL%d\n", LOCAL_LABEL_PREFIX, (VALUE))
 
 /* Output various types of constants.  For real numbers we output hex, with
@@ -224,10 +224,15 @@ do { char dstr[30];                                                       \
    assemble_name ((STREAM), (NAME)),                                   \
    fprintf(STREAM, ", %d\t%s %d\n", ROUNDED, ASM_COMMENT_START, SIZE))
 
-/* Output a local common block.  /bin/as can't do this, so hack a `.space' into
-   the bss segment.  Note that this is *bad* practice.  */
-#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM,NAME,SIZE,ALIGN)  \
-  output_lcomm_directive (STREAM, NAME, SIZE, ALIGN)
+/* Output a local common block.  /bin/as can't do this, so hack a
+   `.space' into the bss segment.  Note that this is *bad* practice.  */
+#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM,NAME,SIZE,ALIGN)               \
+  do {                                                                 \
+    bss_section ();                                                    \
+    ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT));     \
+    ASM_OUTPUT_LABEL (STREAM, NAME);                                   \
+    fprintf (STREAM, "\t.space\t%d\n", SIZE);                          \
+  } while (0)
 
 /* Output a zero-initialized block.  */
 #define ASM_OUTPUT_ALIGNED_BSS(STREAM,DECL,NAME,SIZE,ALIGN) \
index 17982c993d33cab91b8c7e436419ffd83deb0965..407caa2345fc2232964dac14218bd87a82b2a22c 100644 (file)
@@ -1045,7 +1045,7 @@ do                                                                              \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 7538c1e345580db309b47e7b081a20a50245352b..42aec68d6fe2630e21b06ec9b774e1c34cd3ab14 100644 (file)
@@ -1402,7 +1402,7 @@ extern double atof();
 /* This is how to output an element of a case-vector that is relative.  
    (not used on Convex) */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\tds.w L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 138696530db586f690ef5bc5cc76ab9213e8eff2..1c0f4dd53085aacbdad099cd1d3f40311aba16e6 100644 (file)
@@ -1880,7 +1880,7 @@ const_section ()                                                   \
 
 /* This macro should be provided on machines where the addresses in a dispatch
    table are relative to the table's own address. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\tint L%d-L%d\n", VALUE, REL)
 
 /* This macro should be provided on machines where the addresses in a dispatch
index dd0a5f9b68838845d86581d4f080359130871b37..5d35acef74f9e756aaa0e04fe4c81bf4505d5786 100644 (file)
@@ -875,7 +875,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.data .L%d-.L%d{32}\n", VALUE, REL)
 
 /* This is how to output an assembler line
index d1f3694703ac5a129d68d597ceb969718378540b..0826236b6442ac62a7194157ad2cfa77aabb338f 100644 (file)
@@ -1153,7 +1153,7 @@ do { int i; unsigned char *pp = (unsigned char *) (PTR);  \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 4a920239843034f65dccda07bc73c807ce918f03..2c44dd03aff18a1500c3a48f36fe691c58611f11 100644 (file)
@@ -1444,7 +1444,7 @@ do { union { float f; long l;} tem;                       \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.data.w L%d-L%d\n", VALUE, REL)
 
 
index 92e1d9a0dd7b137e7baaff19885aa48b8de12c2d..6315684577a0e9823ee4a85a0b98953ac98fb308 100644 (file)
@@ -1273,7 +1273,7 @@ do { char dstr[30];                                       \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t%s .L%d-.L%d\n", ASM_WORD_OP, VALUE, REL)
 
 /* This is how to output an assembler line
index 28279b24dfaf3105b5febd58a337d2a0c3b681f1..8f7658f7cb943ca25f6175d75b9cd98ef156de86 100644 (file)
@@ -1029,7 +1029,7 @@ enum reg_class
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)                     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)               \
   mvs_check_page (FILE, 4, 0);                                         \
   fprintf (FILE, "\tDC\tA(L%d-L%d)\n", VALUE, REL)
 
index c93279ffb00b411049b113e344fb116c96d8d2e1..25994376aea2c1043c4dcf622f0c7cea23ca6cb1 100644 (file)
@@ -63,7 +63,7 @@
    i386.md for an explanation of the expression this outputs. */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index 55bf23c0c6363b2f7841473d26b25dceae390ef5..b0abdf262fcc5064f3727ff1633040a542b1e8e4 100644 (file)
@@ -2,7 +2,7 @@
    Copyright (C) 1996 Free Software Foundation, Inc.
    Contributed by Eric Youngdale.
    Modified for stabs-in-ELF by H.J. Lu.
-   Adapted from Linux version by John Polstra.
+   Adapted from GNU/Linux version by John Polstra.
 
 This file is part of GNU CC.
 
@@ -33,7 +33,7 @@ Boston, MA 02111-1307, USA.  */
    This is only used for PIC code.  See comments by the `casesi' insn in
    i386.md for an explanation of the expression this outputs. */
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index 892c69f2d05bd4c41530da3588f4fcbb8d9d31cf..1156f19ea917735a44ca0a7975b22fb721f0def4 100644 (file)
@@ -75,7 +75,7 @@ Boston, MA 02111-1307, USA.  */
    i386.md for an explanation of the expression this outputs. */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index 1765ce1cd4cdd6ce95fc3116ed872bd0e2b73b7b..fad11838780c76cbd5e0445ea18a92360e9e2ce9 100644 (file)
@@ -2484,7 +2484,7 @@ do { long l;                                              \
    forward reference the differences.  
  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.word %s%d-%s%d\n",LPREFIX, VALUE,LPREFIX, REL)
 
 /* Define the parentheses used to group arithmetic operations
index 8f0671d1faaf8e2b6f3969735e9641aca32f1864..4b23b91bf2cebb4bf3a2554d4df7e99b80b72dc6 100644 (file)
@@ -41,7 +41,7 @@ Boston, MA 02111-1307, USA.  */
    This is only used for PIC code.  See comments by the `casesi' insn in
    i386.md for an explanation of the expression this outputs. */
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index 3442aeadb872d1a8a4f720d5f17de40ffe85b365..1c3353e9045534c7281b04a27e09696270159bb5 100644 (file)
@@ -44,7 +44,7 @@
    i386.md for an explanation of the expression this outputs. */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index c0c0f3f1a29867c9f3927c80d87ca69f0b1efe38..e2e6231ed877e37fe97c34a1f5a1bfd98993fdbe 100644 (file)
@@ -381,7 +381,7 @@ while (0)
    i386.md for an explanation of the expression this outputs. */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Output a definition */
index fdf21a471f17d4bafaff26d01083cee58c02ddd9..8ac98bedde2ca526909e6438e4ff08a8c320945a 100644 (file)
@@ -238,7 +238,7 @@ do { long value[3];                                                 \
    i386.md for an explanation of the expression this outputs. */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index 7785fc40b092e01b88b86133c87a7dacdbe9d531..70d1bdd66c279cfad4c7ca60d8b62ef3608e642a 100644 (file)
@@ -243,7 +243,7 @@ do {                                                                        \
 } while (0)
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
 do {                                                                   \
   if (TARGET_ELF)                                                      \
     fprintf (FILE, "%s _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", ASM_LONG, LPREFIX, VALUE); \
index 3f69827fd54273df0e264f92a31364baf1a4275d..d05280a76fdf3ff0400c15be52426f8155322f8c 100644 (file)
@@ -236,7 +236,7 @@ do { long value[3];                                                 \
    i386.md for an explanation of the expression this outputs. */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
 
 /* Indicate that jump tables go in the text section.  This is
index 5f10b4611ad3fd3b56948423aa1dff156c2fcaa2..8486d8d656dfca783390f0a875228559beda4114 100644 (file)
@@ -1146,7 +1146,7 @@ do { ASM_OUTPUT_ALIGN ((FILE), 2);                                        \
    (The i860 does not use such vectors,
    but we must define this macro anyway.)  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index caf2530e348451d59821cf49cac0dec2122f2862..556c755ea721698af01474a515a22829ce9c45c9 100644 (file)
@@ -1348,7 +1348,7 @@ extern struct rtx_def *gen_compare_reg ();
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line that says to advance the
index 510bac091fedfdd9e0c6a5ead9d830c62b51fb62..79233e5d56054db8c7a61ee266085b2a810090fd 100644 (file)
@@ -1661,7 +1661,7 @@ do {                                                      \
 } while (0)
 
 /* This is how to output an element of a case-vector that is relative.  */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
 do {                                                   \
   char label[30];                                      \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);     \
index 5f9ec4c73017e33039c55df5ef25c2d258af8335..2b6611ae814fc23e62386d5f8b6a07713b42a42a 100644 (file)
@@ -364,7 +364,7 @@ do { long l;                                        \
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)   \
     fprintf (FILE, "\tlong L%%%d\n", (VALUE))
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)       \
     fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
 
 /* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
index 14f0606b8aad0c7faea302197b7cb218e7b483cb..b3779743532176f1bbd9280720b420702c672f36 100644 (file)
@@ -605,7 +605,7 @@ do { long l;                                                \
 
 /* This is how to output an element of a case-vector that is relative.  */
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL)
 
 /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
index 1388e0262b23daa64a9803f84359a43cb4881c59..98165029962b7e584461973d7bbca4b0d4bba110 100644 (file)
@@ -316,7 +316,7 @@ do { long l[3];                                                             \
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
   fprintf (FILE, "\tlong L%d\n", VALUE)
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\tshort L%d-L%d\n", VALUE, REL)
 
 #define ASM_OUTPUT_ALIGN(FILE,LOG)     \
index 10284a320b680f79863dc443753b078fa2bfd6cb..600fab430c7a56eabbd2e736e04860b4f6d47c0e 100644 (file)
@@ -1920,7 +1920,7 @@ do { long l;                                              \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   asm_fprintf (FILE, "\t.word %LL%d-%LL%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 65c2f4760439994387ccb46ff430fe9c69b113d3..e1b4060080844a9df0ec87530f0902653d0a5f0c 100644 (file)
@@ -547,7 +547,7 @@ do { long l;                                        \
 /* This is how to output an element of a case-vector that is relative.  */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)       \
     asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n", ASM_SHORT, (VALUE), (REL))
 
 #ifndef USE_GAS
index 447ca6ec5cca565d38c4f5d71a70d86f854a4622..62d2336fc580ec9880018b4f510671a05e2abb59 100644 (file)
@@ -427,7 +427,7 @@ extern int switch_table_difference_label_flag;
 /* This is how to output an element of a case-vector that is relative.  */
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)       \
   asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n", WORD_ASM_OP, VALUE, REL)
 
 /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
index 46aa30a7478a32cc154e643c2ec780afc37f7fa0..7b5771a1ef45d3e23015f1d77fce140f97e76314 100644 (file)
@@ -315,7 +315,7 @@ do { long l;                                        \
   fprintf (FILE, "\tlong L%%%d\n", (VALUE))
 
 #undef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
 
 #undef ASM_OUTPUT_ALIGN
index b748a224069f2bab63c3c2e881c9ec0f6b8c6cf2..e35b87e70d77a10e35ad4279e67cfb1404a8726d 100644 (file)
@@ -198,13 +198,13 @@ extern char * reg_names[];
    Redefined in sysv4.h, and luna.h.  */
 #define VERSION_INFO1  "m88k, "
 #ifndef VERSION_INFO2
-#define VERSION_INFO2   "$Revision: 1.4 $"
+#define VERSION_INFO2   "$Revision: 1.11 $"
 #endif
 
 #ifndef VERSION_STRING
 #define VERSION_STRING  version_string
 #ifdef __STDC__
-#define TM_RCS_ID      "@(#)" __FILE__ " $Revision: 1.4 $ " __DATE__
+#define TM_RCS_ID      "@(#)" __FILE__ " $Revision: 1.11 $ " __DATE__
 #else
 #define TM_RCS_ID      "$What: <@(#) m88k.h,v  1.1.1.2.2.2> $"
 #endif  /* __STDC__ */
@@ -2199,7 +2199,7 @@ do {                                                                       \
   } while (0)
 
 /* This is how to output an element of a case-vector that is relative.  */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   ASM_OUTPUT_ADDR_VEC_ELT (FILE, VALUE)
 
 /* This is how to output an assembler line
index d91501533585ac5b168eed8395ab4052f2ddbb33..92368f65eb4ca44f911e3cf8ec6f3f3c9e62aa1b 100644 (file)
@@ -4154,7 +4154,7 @@ do {                                                                      \
    This is used for pc-relative code (e.g. when TARGET_ABICALLS or
    TARGET_EMBEDDED_PIC).  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, VALUE, REL)                   \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)             \
 do {                                                                   \
   if (TARGET_MIPS16)                                                   \
     fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n",                         \
index 2c51843f5742eb346cf88434d6ce38e124e24350..20db8a5ad0955b1fdade31edc6b9c21c71747571 100644 (file)
@@ -946,7 +946,7 @@ do { char dstr[30];                                 \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
 
 #define ASM_OUTPUT_ALIGN(FILE,LOG)     \
index f244990cc09136df5e661bcd80065e6d91b58e1c..ac1fe2e025afa3d5cec1bb7a65f8d1921e207c52 100644 (file)
@@ -929,7 +929,7 @@ do { char dstr[30];                                 \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
 
 #define ASM_OUTPUT_ALIGN(FILE,LOG)     \
index f388453dc23b4126e144292a692312d9e4d934a1..31e28946e4f69b2e5f72b3e61ada5d128ba3d604 100644 (file)
@@ -90,7 +90,7 @@ output_file_directive ((FILE), main_input_filename)
        sprintf (LABEL, "*.%s%d", PREFIX, NUM)
 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)                     \
        fprintf (FILE, ".%s%d:\n", PREFIX, NUM)
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)                     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)               \
        fprintf (FILE, "\t.double .L%d-.LI%d\n", VALUE, REL)
 
 /*
index 47a1d84f69b51345d1839d9f83ad18197704f0a0..7c138a4d18b3605deadc286ddf98fc9285688660 100644 (file)
@@ -1396,7 +1396,7 @@ do {                                                                      \
 
 /* This is how to output an element of a case-vector that is relative.  */
 /* ** Notice that the second element is LI format! */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.long L%d-LI%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 4fd25f8ff73ab358fc828e90a9d861665dd989be..4a0b43cb333efa90cf7f9bd7e5b0409ea4ad1195 100644 (file)
@@ -2269,7 +2269,7 @@ DTORS_SECTION_FUNCTION
    on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions
    rather than a table of absolute addresses.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   if (TARGET_BIG_SWITCH)                                       \
     fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'L$%04d(%%r19),%%r1\n\tbv 0(%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE);                         \
   else                                                         \
index cf292903b4f85123ec853f210a65cf7b7effedbe..a6194851599e214db0839c312ac6bf3d9b3b1d8c 100644 (file)
@@ -1258,7 +1258,7 @@ extern int swap_operands;
 /* This is how to output an element of a case-vector that is relative.  */
 
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index ebf293f03202fa01d9c843c5d2d5d88252b5e330..0982a641fbaeb2a26cd29989ee778ce6ea19de6b 100644 (file)
@@ -2957,7 +2957,7 @@ do {                                                                      \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)\
   do { char buf[100];                                  \
        fputs ((TARGET_32BIT) ? "\t.long " : "\t.llong ", FILE);        \
        ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE);  \
index 7f12528a877e7849980b05d3cf15b92776894a21..ee97013208ae7435bedd2fadcb0bbc7cc66bf80e 100644 (file)
@@ -87,8 +87,6 @@ rtx sh_compare_op0;
 rtx sh_compare_op1;
 
 enum machine_mode sh_addr_diff_vec_mode;
-rtx *uid_align;
-int uid_align_max;
 
 /* Provides the class number of the smallest class containing
    reg number.  */
@@ -550,10 +548,11 @@ output_far_jump (insn, op)
   struct { rtx lab, reg, op; } this;
   char *jump;
   int far;
+  int offset = branch_dest (insn) - insn_addresses[INSN_UID (insn)];
 
   this.lab = gen_label_rtx ();
 
-  if (braf_branch_p (insn, 0))
+  if (offset >= -32764 && offset - get_attr_length (insn) <= 32766)
     {
       far = 0;
       jump = "mov.w    %O0,%1;braf     %1";
@@ -606,57 +605,52 @@ output_branch (logic, insn, operands)
      rtx insn;
      rtx *operands;
 {
-  int offset
-    = (insn_addresses[INSN_UID (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0))]
-       - insn_addresses[INSN_UID (insn)]);
-
-  if (offset == 260
-      && final_sequence
-      && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
-    {
-      /* The filling of the delay slot has caused a forward branch to exceed
-        its range.
-         Just emit the insn from the delay slot in front of the branch.  */
-      /* The call to print_slot will clobber the operands.  */
-      rtx op0 = operands[0];
-      print_slot (final_sequence);
-      operands[0] = op0;
-    }
-  else if (offset < -252 || offset > 258)
+  switch (get_attr_length (insn))
     {
-      /* This can happen when other condbranches hoist delay slot insn
+    case 6:
+      /* This can happen if filling the delay slot has caused a forward
+        branch to exceed its range (we could reverse it, but only
+        when we know we won't overextend other branches; this should
+        best be handled by relaxation).
+        It can also happen when other condbranches hoist delay slot insn
         from their destination, thus leading to code size increase.
         But the branch will still be in the range -4092..+4098 bytes.  */
 
-      int label = lf++;
-      /* The call to print_slot will clobber the operands.  */
-      rtx op0 = operands[0];
-
-      /* If the instruction in the delay slot is annulled (true), then
-        there is no delay slot where we can put it now.  The only safe
-        place for it is after the label.  final will do that by default.  */
-
-      if (final_sequence
-         && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
+      if (! TARGET_RELAX)
        {
-         asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",
-                      ASSEMBLER_DIALECT ? "/" : ".", label);
-         print_slot (final_sequence);
+         int label = lf++;
+         /* The call to print_slot will clobber the operands.  */
+         rtx op0 = operands[0];
+    
+         /* If the instruction in the delay slot is annulled (true), then
+            there is no delay slot where we can put it now.  The only safe
+            place for it is after the label.  final will do that by default.  */
+    
+         if (final_sequence
+             && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
+           {
+             asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",
+                          ASSEMBLER_DIALECT ? "/" : ".", label);
+             print_slot (final_sequence);
+           }
+         else
+           asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);
+    
+         output_asm_insn ("bra\t%l0", &op0);
+         fprintf (asm_out_file, "\tnop\n");
+         ASM_OUTPUT_INTERNAL_LABEL(asm_out_file, "LF", label);
+    
+         return "";
        }
-      else
-       asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);
-
-      output_asm_insn ("bra\t%l0", &op0);
-      fprintf (asm_out_file, "\tnop\n");
-      ASM_OUTPUT_INTERNAL_LABEL(asm_out_file, "LF", label);
-
-      return "";
+      /* When relaxing, handle this like a short branch.  The linker
+        will fix it up if it still doesn't fit after relaxation.  */
+    case 2:
+      return logic ? "bt%.\t%l0" : "bf%.\t%l0";
+    default:
+      abort ();
     }
-  return logic ? "bt%.\t%l0" : "bf%.\t%l0";
 }
 
-int branch_offset ();
-
 char *
 output_branchy_insn (code, template, insn, operands)
      char *template;
@@ -679,8 +673,9 @@ output_branchy_insn (code, template, insn, operands)
        }
       else
        {
-         int offset = branch_offset (next_insn) + 4;
-         if (offset >= -252 && offset <= 256)
+         int offset = (branch_dest (next_insn)
+                       - insn_addresses[INSN_UID (next_insn)] + 4);
+         if (offset >= -252 && offset <= 258)
            {
              if (GET_CODE (src) == IF_THEN_ELSE)
                /* branch_true */
@@ -1694,8 +1689,6 @@ typedef struct
 static pool_node pool_vector[MAX_POOL_SIZE];
 static int pool_size;
 
-static int max_uid_before_fixup_addr_diff_vecs;
-
 /* ??? If we need a constant in HImode which is the truncated value of a
    constant we need in SImode, we could combine the two entries thus saving
    two bytes.  Is this common enough to be worth the effort of implementing
@@ -1860,24 +1853,6 @@ broken_move (insn)
   return 0;
 }
 
-int
-cache_align_p (insn)
-     rtx insn;
-{
-  rtx pat;
-
-  if (! insn)
-    return 1;
-
-  if (GET_CODE (insn) != INSN)
-    return 0;
-
-  pat = PATTERN (insn);
-  return (GET_CODE (pat) == UNSPEC_VOLATILE
-         && XINT (pat, 1) == 1
-         && INTVAL (XVECEXP (pat, 0, 0)) == CACHE_LOG);
-}
-
 static int
 mova_p (insn)
      rtx insn;
@@ -1901,6 +1876,8 @@ find_barrier (num_mova, mova, from)
   int count_hi = 0;
   int found_hi = 0;
   int found_si = 0;
+  int hi_align = 2;
+  int si_align = 2;
   int leading_mova = num_mova;
   rtx barrier_before_mova, found_barrier = 0, good_barrier = 0;
   int si_limit;
@@ -1927,21 +1904,21 @@ find_barrier (num_mova, mova, from)
 
   while (from && count_si < si_limit && count_hi < hi_limit)
     {
-      int inc = 0;
+      int inc = get_attr_length (from);
+      int new_align = 1;
 
-      /* The instructions created by fixup_addr_diff_vecs have no valid length
-       info yet.  They should be considered to have zero at this point.  */
-      if (INSN_UID (from) < max_uid_before_fixup_addr_diff_vecs)
-       inc = get_attr_length (from);
+      if (GET_CODE (from) == CODE_LABEL)
+       new_align = optimize ? 1 << label_to_alignment (from) : 1;
 
       if (GET_CODE (from) == BARRIER)
        {
+
          found_barrier = from;
+
          /* If we are at the end of the function, or in front of an alignment
             instruction, we need not insert an extra alignment.  We prefer
             this kind of barrier.  */
-       
-         if (cache_align_p (next_real_insn (found_barrier)))
+         if (barrier_align (from) > 2)
            good_barrier = from;
        }
 
@@ -1971,6 +1948,8 @@ find_barrier (num_mova, mova, from)
            }
          else
            {
+             while (si_align > 2 && found_si + si_align - 2 > count_si)
+               si_align >>= 1;
              if (found_si > count_si)
                count_si = found_si;
              found_si += GET_MODE_SIZE (mode);
@@ -1979,10 +1958,7 @@ find_barrier (num_mova, mova, from)
            }
        }
 
-      if (GET_CODE (from) == INSN
-         && GET_CODE (PATTERN (from)) == SET
-         && GET_CODE (SET_SRC (PATTERN (from))) == UNSPEC
-         && XINT (SET_SRC (PATTERN (from)), 1) == 1)
+      if (mova_p (from))
        {
          if (! num_mova++)
            {
@@ -1999,7 +1975,7 @@ find_barrier (num_mova, mova, from)
        {
          if (num_mova)
            num_mova--;
-         if (cache_align_p (NEXT_INSN (next_nonnote_insn (from))))
+         if (found_barrier == good_barrier)
            {
              /* We have just passed the barrier in front front of the
                 ADDR_DIFF_VEC.  Since the ADDR_DIFF_VEC is accessed
@@ -2008,15 +1984,32 @@ find_barrier (num_mova, mova, from)
                 If we waited any longer, we could end up at a barrier in
                 front of code, which gives worse cache usage for separated
                 instruction / data caches.  */
-             good_barrier = found_barrier;
              break;
            }
        }
 
       if (found_si)
-       count_si += inc;
+       {
+         if (new_align > si_align)
+           {
+             count_si = count_si + new_align - 1 & -si_align;
+             si_align = new_align;
+           }
+         else
+           count_si = count_si + new_align - 1 & -new_align;
+         count_si += inc;
+       }
       if (found_hi)
-       count_hi += inc;
+       {
+         if (new_align > hi_align)
+           {
+             count_hi = count_hi + new_align - 1 & -hi_align;
+             hi_align = new_align;
+           }
+         else
+           count_hi = count_hi + new_align - 1 & -new_align;
+         count_hi += inc;
+       }
       from = NEXT_INSN (from);
     }
 
@@ -2039,21 +2032,8 @@ find_barrier (num_mova, mova, from)
 
   if (found_barrier)
     {
-      /* We have before prepared barriers to come in pairs, with an
-        alignment instruction in-between.  We want to use the first
-        barrier, so that the alignment applies to the code.
-        If we are compiling for SH3 or newer, there are some exceptions
-        when the second barrier and the alignment doesn't exist yet, so
-        we have to add it.  */
-      if (good_barrier)
+      if (good_barrier && next_real_insn (found_barrier))
        found_barrier = good_barrier;
-      else if (! TARGET_SMALLCODE)
-       {
-         found_barrier
-           = emit_insn_before (gen_align_log (GEN_INT (CACHE_LOG)),
-                               found_barrier);
-         found_barrier = emit_barrier_before (found_barrier);
-       }
     }
   else
     {
@@ -2083,11 +2063,6 @@ find_barrier (num_mova, mova, from)
       LABEL_NUSES (label) = 1;
       found_barrier = emit_barrier_after (from);
       emit_label_after (label, found_barrier);
-      if (! TARGET_SMALLCODE)
-       {
-         emit_barrier_after (found_barrier);
-         emit_insn_after (gen_align_log (GEN_INT (CACHE_LOG)), found_barrier);
-       }
     }
 
   return found_barrier;
@@ -2470,227 +2445,116 @@ gen_far_branch (bp)
   gen_block_redirect (jump, bp->address += 2, 2);
 }
 
-static void
-fixup_aligns ()
-{
-  rtx insn = get_last_insn ();
-  rtx align_tab[MAX_BITS_PER_WORD];
-  int i;
-
-  for (i = CACHE_LOG; i >= 0; i--)
-    align_tab[i] = insn;
-  bzero ((char *) uid_align, uid_align_max * sizeof *uid_align);
-  for (; insn; insn = PREV_INSN (insn))
-    {
-      int uid = INSN_UID (insn);
-      if (uid < uid_align_max)
-       uid_align[uid] = align_tab[1];
-      if (GET_CODE (insn) == INSN)
-       {
-         rtx pat = PATTERN (insn);
-         if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == 1)
-           {
-             /* Found an alignment instruction.  */
-             int log = INTVAL (XVECEXP (pat, 0, 0));
-             uid_align[uid] = align_tab[log];
-             for (i = log - 1; i >= 0; i--)
-               align_tab[i] = insn;
-           }
-       }
-      else if (GET_CODE (insn) == JUMP_INSN
-              && GET_CODE (PATTERN (insn)) == SET)
-       {
-         rtx dest = SET_SRC (PATTERN (insn));
-         if (GET_CODE (dest) == IF_THEN_ELSE)
-           dest = XEXP (dest, 1);
-         if (GET_CODE (dest) == LABEL_REF)
-           {
-             dest = XEXP (dest, 0);
-             if (! uid_align[INSN_UID (dest)])
-               /* Mark backward branch.  */
-               uid_align[uid] = 0;
-           }
-       }
-    }
-}
-
 /* Fix up ADDR_DIFF_VECs.  */
 void
 fixup_addr_diff_vecs (first)
      rtx first;
 {
   rtx insn;
-  int max_address;
-  int need_fixup_aligns = 0;
-  
-  if (optimize)
-    max_address = insn_addresses[INSN_UID (get_last_insn ())] + 2;
+
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
-      rtx vec_lab, rel_lab, pat, min_lab, max_lab, adj;
-      int len, i, min, max, size;
+      rtx vec_lab, pat, prev, prevpat, x;
 
       if (GET_CODE (insn) != JUMP_INSN
          || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
        continue;
       pat = PATTERN (insn);
-      rel_lab = vec_lab = XEXP (XEXP (pat, 0), 0);
-      if (TARGET_SH2)
-       {
-         rtx prev, prevpat, x;
+      vec_lab = XEXP (XEXP (pat, 0), 0);
 
-         /* Search the matching casesi_jump_2.  */
-         for (prev = vec_lab; ; prev = PREV_INSN (prev))
-           {
-             if (GET_CODE (prev) != JUMP_INSN)
-               continue;
-             prevpat = PATTERN (prev);
-             if (GET_CODE (prevpat) != PARALLEL || XVECLEN (prevpat, 0) != 2)
-               continue;
-             x = XVECEXP (prevpat, 0, 1);
-             if (GET_CODE (x) != USE)
-               continue;
-             x = XEXP (x, 0);
-             if (GET_CODE (x) == LABEL_REF && XEXP (x, 0) == vec_lab)
-               break;
-           }
-         /* Fix up the ADDR_DIF_VEC to be relative
-            to the reference address of the braf.  */
-         XEXP (XEXP (pat, 0), 0)
-           = rel_lab = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
-       }
-      if (! optimize)
-       continue;
-      len = XVECLEN (pat, 1);
-      if (len <= 0)
-       abort ();
-      for (min = max_address, max = 0, i = len - 1; i >= 0; i--)
-       {
-         rtx lab = XEXP (XVECEXP (pat, 1, i), 0);
-         int addr = insn_addresses[INSN_UID (lab)];
-         if (addr < min)
-           {
-             min = addr;
-             min_lab = lab;
-           }
-         if (addr > max)
-           {
-             max = addr;
-             max_lab = lab;
-           }
-       }
-      adj
-       = emit_insn_before (gen_addr_diff_vec_adjust (min_lab, max_lab, rel_lab,
-                                                     GEN_INT (len)), vec_lab);
-      size = (XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
-             - addr_diff_vec_adjust (adj, 0));
-      /* If this is a very small table, we want to remove the alignment after
-        the table.  */
-      if (! TARGET_SMALLCODE && size <= 1 << (CACHE_LOG - 2))
+      /* Search the matching casesi_jump_2.  */
+      for (prev = vec_lab; ; prev = PREV_INSN (prev))
        {
-         rtx align = NEXT_INSN (next_nonnote_insn (insn));
-         PUT_CODE (align, NOTE);
-         NOTE_LINE_NUMBER (align) = NOTE_INSN_DELETED;
-         NOTE_SOURCE_FILE (align) = 0;
-         need_fixup_aligns = 1;
+         if (GET_CODE (prev) != JUMP_INSN)
+           continue;
+         prevpat = PATTERN (prev);
+         if (GET_CODE (prevpat) != PARALLEL || XVECLEN (prevpat, 0) != 2)
+           continue;
+         x = XVECEXP (prevpat, 0, 1);
+         if (GET_CODE (x) != USE)
+           continue;
+         x = XEXP (x, 0);
+         if (GET_CODE (x) == LABEL_REF && XEXP (x, 0) == vec_lab)
+           break;
        }
+      /* Fix up the ADDR_DIF_VEC to be relative
+        to the reference address of the braf.  */
+      XEXP (XEXP (pat, 0), 0)
+       = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
     }
-  if (need_fixup_aligns)
-    fixup_aligns ();
 }
 
-/* Say how much the ADDR_DIFF_VEC following INSN can be shortened.
-   If FIRST_PASS is nonzero, all addresses and length of following
-   insns are still uninitialized.  */
+/* BARRIER_OR_LABEL is either a BARRIER or a CODE_LABEL immediately following
+   a barrier.  Return the base 2 logarithm of the desired alignment.  */
 int
-addr_diff_vec_adjust (insn, first_pass)
-     rtx insn;
-     int first_pass;
+barrier_align (barrier_or_label)
+     rtx barrier_or_label;
 {
-  rtx pat = PATTERN (insn);
-  rtx min_lab = XEXP (XVECEXP (pat, 0, 0), 0);
-  rtx max_lab = XEXP (XVECEXP (pat, 0, 1), 0);
-  rtx rel_lab = XEXP (XVECEXP (pat, 0, 2), 0);
-  int len = INTVAL (XVECEXP (pat, 0, 3));
-  int addr, min_addr, max_addr, saving, prev_saving = 0, offset;
-  rtx align_insn = uid_align[INSN_UID (rel_lab)];
-  int standard_size = TARGET_BIGTABLE ? 4 : 2;
-  int last_size = GET_MODE_SIZE ( GET_MODE(pat));
-  int align_fuzz = 0;
-
-  if (! insn_addresses)
+  rtx next = next_real_insn (barrier_or_label), pat, prev;
+  int slot, credit;
+  if (! next)
     return 0;
-  if (first_pass)
-    /* If optimizing, we may start off with an optimistic guess.  */
-    return optimize ? len & ~1 : 0;
-  addr = insn_addresses[INSN_UID (rel_lab)];
-  min_addr = insn_addresses[INSN_UID (min_lab)];
-  max_addr = insn_addresses[INSN_UID (max_lab)];
-  if (! last_size)
-    last_size = standard_size;
-  if (TARGET_SH2)
-    prev_saving = ((standard_size - last_size) * len) & ~1;
 
-  /* The savings are linear to the vector length.  However, if we have an
-     odd saving, we need one byte again to reinstate 16 bit alignment.  */
-  saving = ((standard_size - 1) * len) & ~1;
-  offset = prev_saving - saving;
+  pat = PATTERN (next);
 
-  if ((insn_addresses[INSN_UID (align_insn)] < max_addr
-       || (insn_addresses[INSN_UID (align_insn)] == max_addr
-           && next_real_insn (max_lab) != align_insn))
-      && GET_CODE (align_insn) == INSN)
-    {
-      int align = 1 << INTVAL (XVECEXP (PATTERN (align_insn), 0, 0));
-      int align_addr = insn_addresses[INSN_UID (align_insn)];
-      if (align_addr > insn_addresses[INSN_UID (insn)])
-       {
-         int old_offset = offset;
-         offset = (align_addr - 1 & align - 1) + offset & -align;
-         align_addr += old_offset;
-       }
-      align_fuzz += (align_addr - 1)  & (align - 2);
-      align_insn = uid_align[INSN_UID (align_insn)];
-      if (insn_addresses[INSN_UID (align_insn)] <= max_addr
-          && GET_CODE (align_insn) == INSN)
-        {
-          int align2 = 1 << INTVAL (XVECEXP (PATTERN (align_insn), 0, 0));
-          align_addr = insn_addresses[INSN_UID (align_insn)];
-         if (align_addr > insn_addresses[INSN_UID (insn)])
-           {
-             int old_offset = offset;
-             offset = (align_addr - 1 & align2 - 1) + offset & -align2;
-             align_addr += old_offset;
-           }
-          align_fuzz += (align_addr - 1)  & (align2 - align);
-        }
-    }
+  if (GET_CODE (pat) == ADDR_DIFF_VEC)
+    return 2;
+
+  if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == 1)
+    /* This is a barrier in front of a constant table.  */
+    return 0;
 
-  if (min_addr >= addr
-      && max_addr + offset - addr + align_fuzz <= 255)
+  prev = prev_real_insn (barrier_or_label);
+  if (GET_CODE (PATTERN (prev)) == ADDR_DIFF_VEC)
     {
-      PUT_MODE (pat, QImode);
-      return saving;
+      pat = PATTERN (prev);
+      /* If this is a very small table, we want to keep the alignment after
+        the table to the minimum for proper code alignment.  */
+      return ((TARGET_SMALLCODE
+              || (XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
+                  <= 1 << (CACHE_LOG - 2)))
+             ? 1 : CACHE_LOG);
     }
-  saving = 2 * len;
-/* Since alignment might play a role in min_addr if it is smaller than addr,
-   we may not use it without exact alignment compensation; a 'worst case'
-   estimate is not good enough, because it won't prevent infinite oscillation
-   of shorten_branches.
-   ??? We should fix that eventually, but the code to deal with alignments
-   should go in a new function.  */
-#if 0
-  if (TARGET_BIGTABLE && min_addr - ((1 << CACHE_LOG) - 2) - addr >= -32768
-#else
-  if (TARGET_BIGTABLE && (min_addr >= addr || addr <= 32768)
-#endif
-      && max_addr - addr <= 32767 + saving - prev_saving)
+
+  if (TARGET_SMALLCODE)
+    return 0;
+
+  if (! TARGET_SH3 || ! optimize)
+    return CACHE_LOG;
+
+  /* Check if there is an immediately preceding branch to the insn beyond
+     the barrier.  We must weight the cost of discarding useful information
+     from the current cache line when executing this branch and there is
+     an alignment, against that of fetching unneeded insn in front of the
+     branch target when there is no alignment.  */
+
+  /* PREV is presumed to be the JUMP_INSN for the barrier under
+     investigation.  Skip to the insn before it.  */
+  prev = prev_real_insn (prev);
+
+  for (slot = 2, credit = 1 << (CACHE_LOG - 2) + 2;
+       credit >= 0 && prev && GET_CODE (prev) == INSN;
+       prev = prev_real_insn (prev))
     {
-      PUT_MODE (pat, HImode);
-      return saving;
-    }
-  PUT_MODE (pat, TARGET_BIGTABLE ? SImode : HImode);
-  return 0;
+      if (GET_CODE (PATTERN (prev)) == USE
+          || GET_CODE (PATTERN (prev)) == CLOBBER)
+        continue;
+      if (GET_CODE (PATTERN (prev)) == SEQUENCE)
+       prev = XVECEXP (PATTERN (prev), 0, 1);
+      if (slot &&
+          get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
+        slot = 0;
+      credit -= get_attr_length (prev);
+    }
+  if (prev
+      && GET_CODE (prev) == JUMP_INSN
+      && JUMP_LABEL (prev)
+      && next_real_insn (JUMP_LABEL (prev)) == next_real_insn (barrier_or_label)
+      && (credit - slot >= (GET_CODE (SET_SRC (PATTERN (prev))) == PC ? 2 : 0)))
+    return 0;
+
+  return CACHE_LOG;
 }
 
 /* Exported to toplev.c.
@@ -2935,118 +2799,14 @@ machine_dependent_reorg (first)
        }
     }
 
-  /* The following processing passes need length information.
-     addr_diff_vec_adjust needs to know if insn_addresses is valid.  */
-  insn_addresses = 0;
-
-  /* If not optimizing for space, we want extra alignment for code after
-     a barrier, so that it starts on a word / cache line boundary.
-     We used to emit the alignment for the barrier itself and associate the
-     instruction length with the following instruction, but that had two
-     problems:
-     i) A code label that follows directly after a barrier gets too low an
-     address.  When there is a forward branch to it, the incorrect distance
-     calculation can lead to out of range branches.  That happened with
-     compile/920625-2 -O -fomit-frame-pointer in copyQueryResult.
-     ii) barriers before constant tables get the extra alignment too.
-     That is just a waste of space.
-
-     So what we do now is to insert align_* instructions after the
-     barriers.  By doing that before literal tables are generated, we
-     don't have to care about these.  */
-  /* We also want alignment in front of ADDR_DIFF_VECs; this is done already
-     by ASM_OUTPUT_CASE_LABEL, but when optimizing, we have to make it
-     explicit in the RTL in order to correctly shorten branches.  */
-    
-  if (optimize)
-    for (insn = first; insn; insn = NEXT_INSN (insn))
-      {
-       rtx addr_diff_vec;
-
-       if (GET_CODE (insn) == BARRIER
-           && (addr_diff_vec = next_real_insn (insn)))
-         if (GET_CODE (PATTERN (addr_diff_vec)) == ADDR_DIFF_VEC)
-           emit_insn_before (gen_align_4 (),
-                             XEXP (XEXP (PATTERN (addr_diff_vec), 0), 0));
-         else if (TARGET_SMALLCODE)
-           continue;
-         else if (TARGET_SH3)
-           {
-             /* We align for an entire cache line.  If there is a immediately
-                preceding branch to the insn beyond the barrier, it does not
-                make sense to insert the align, because we are more likely
-                to discard useful information from the current cache line
-                when doing the align than to fetch unneeded insns when not.  */
-             rtx prev = prev_real_insn (prev_real_insn (insn));
-             int slot, credit;
-
-             for (slot = 2, credit = 1 << (CACHE_LOG - 2) + 2;
-                  credit >= 0 && prev && GET_CODE (prev) == INSN;
-                  prev = prev_real_insn (prev))
-               {
-                 if (GET_CODE (PATTERN (prev)) == USE
-                     || GET_CODE (PATTERN (prev)) == CLOBBER)
-                   continue;
-                 if (slot &&
-                     get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
-                   slot = 0;
-                 credit -= get_attr_length (prev);
-               }
-             if (! prev || GET_CODE (prev) != JUMP_INSN
-                 || (next_real_insn (JUMP_LABEL (prev))
-                     != next_real_insn (insn))
-                 || (credit - slot
-                     < (GET_CODE (SET_SRC (PATTERN (prev))) == PC ? 2 : 0)))
-               {
-                 insn = emit_insn_after (gen_align_log (GEN_INT (CACHE_LOG)),
-                                         insn);
-                 insn = emit_barrier_after (insn);
-               }
-           }
-         else
-           {
-             insn = emit_insn_after (gen_align_4 (), insn);
-             insn = emit_barrier_after (insn);
-           }
-       else if (TARGET_SMALLCODE)
-         continue;
-       else if (GET_CODE (insn) == NOTE
-                && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-         {
-           rtx next = next_nonnote_insn (insn);
-            if (next && GET_CODE (next) == CODE_LABEL)
-             emit_insn_after (gen_align_4 (), insn);
-         }
-      }
-
-  /* If TARGET_IEEE, we might have to split some branches before fixup_align.
-     If optimizing, the double call to shorten_branches will split insns twice,
-     unless we split now all that is to split and delete the original insn.  */
-  if (TARGET_IEEE || optimize)
-    for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
-      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' && ! INSN_DELETED_P (insn))
-       {
-         rtx old = insn;
-         insn = try_split (PATTERN (insn), insn, 1);
-         if (INSN_DELETED_P (old))
-           {
-             PUT_CODE (old, NOTE);
-             NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (old) = 0;
-           }
-       }
-
-  max_uid_before_fixup_addr_diff_vecs = get_max_uid ();
+  if (TARGET_SH2)
+    fixup_addr_diff_vecs (first);
 
   if (optimize)
     {
-      uid_align_max = get_max_uid ();
-      uid_align = (rtx *) alloca (uid_align_max * sizeof *uid_align);
-      fixup_aligns ();
       mdep_reorg_phase = SH_SHORTEN_BRANCHES0;
       shorten_branches (first);
     }
-  fixup_addr_diff_vecs (first);
   /* Scan the function looking for move instructions which have to be
      changed to pc-relative loads and insert the literal tables.  */
 
@@ -3070,8 +2830,7 @@ machine_dependent_reorg (first)
          /* Some code might have been inserted between the mova and
             its ADDR_DIFF_VEC.  Check if the mova is still in range.  */
          for (scan = mova, total = 0; scan != insn; scan = NEXT_INSN (scan))
-           if (INSN_UID (scan) < max_uid_before_fixup_addr_diff_vecs)
-             total += get_attr_length (scan);
+           total += get_attr_length (scan);
 
          /* range of mova is 1020, add 4 because pc counts from address of
             second instruction after this one, subtract 2 in case pc is 2
@@ -3234,9 +2993,6 @@ split_branches (first)
   int max_uid = get_max_uid ();
 
   /* Find out which branches are out of range.  */
-  uid_align_max = get_max_uid ();
-  uid_align = (rtx *) alloca (uid_align_max * sizeof *uid_align);
-  fixup_aligns ();
   shorten_branches (first);
 
   uid_branch = (struct far_branch **) alloca (max_uid * sizeof *uid_branch);
@@ -3335,13 +3091,15 @@ split_branches (first)
                   is too far away.  */
                /* We can't use JUMP_LABEL here because it might be undefined
                   when not optimizing.  */
+               /* A syntax error might cause beyond to be NULL_RTX.  */
                beyond
                  = next_active_insn (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1),
                                            0));
        
-               if ((GET_CODE (beyond) == JUMP_INSN
-                    || (GET_CODE (beyond = next_active_insn (beyond))
-                        == JUMP_INSN))
+               if (beyond
+                   && (GET_CODE (beyond) == JUMP_INSN
+                       || (GET_CODE (beyond = next_active_insn (beyond))
+                           == JUMP_INSN))
                    && GET_CODE (PATTERN (beyond)) == SET
                    && recog_memoized (beyond) == CODE_FOR_jump
                    && ((insn_addresses[INSN_UID (XEXP (SET_SRC (PATTERN (beyond)), 0))]
@@ -3432,9 +3190,6 @@ split_branches (first)
        delete_insn (far_branch_list->far_label);
       far_branch_list = far_branch_list->prev;
     }
-  uid_align_max = get_max_uid ();
-  uid_align = (rtx *) oballoc (uid_align_max * sizeof *uid_align);
-  fixup_aligns ();
 }
 
 /* Dump out instruction addresses, which is useful for debugging the
@@ -4193,180 +3948,20 @@ braf_label_ref_operand(op, mode)
     return 0;
 }
 \f
-/* Return the offset of a branch.  Offsets for backward branches are
-   reported relative to the branch instruction, while offsets for forward
-   branches are reported relative to the following instruction.  */
+/* Return the destination address of a branch.  */
    
 int
-branch_offset (branch)
+branch_dest (branch)
      rtx branch;
 {
-  rtx dest = SET_SRC (PATTERN (branch)), dest_next;
-  int branch_uid = INSN_UID (branch);
-  int dest_uid, dest_addr;
-  rtx branch_align = uid_align[branch_uid];
+  rtx dest = SET_SRC (PATTERN (branch));
+  int dest_uid;
 
   if (GET_CODE (dest) == IF_THEN_ELSE)
     dest = XEXP (dest, 1);
   dest = XEXP (dest, 0);
   dest_uid = INSN_UID (dest);
-  dest_addr = insn_addresses[dest_uid];
-  if (branch_align)
-    {
-      /* Forward branch. */
-      /* If branch is in a sequence, get the successor of the sequence.  */
-      rtx next = NEXT_INSN (NEXT_INSN (PREV_INSN (branch)));
-      int next_addr = insn_addresses[INSN_UID (next)];
-      int diff;
-
-      /* If NEXT has been hoisted in a sequence further on, it address has
-        been clobbered in the previous pass.  However, if that is the case,
-        we know that it is exactly 2 bytes long (because it fits in a delay
-        slot), and that there is a following label (the destination of the
-        instruction that filled its delay slot with NEXT).  The address of
-        this label is reliable.  */
-      if (NEXT_INSN (next))
-       {
-         int next_next_addr = insn_addresses[INSN_UID (NEXT_INSN (next))];
-         if (next_addr > next_next_addr)
-           next_addr = next_next_addr - 2;
-       }
-      diff = dest_addr - next_addr;
-      /* If BRANCH_ALIGN has been the last insn, it might be a barrier or
-        a note.  */
-      if ((insn_addresses[INSN_UID (branch_align)] < dest_addr
-          || (insn_addresses[INSN_UID (branch_align)] == dest_addr
-              && next_real_insn (dest) != branch_align))
-         && GET_CODE (branch_align) == INSN)
-       {
-         int align = 1 << INTVAL (XVECEXP (PATTERN (branch_align), 0, 0));
-         int align_addr = insn_addresses[INSN_UID (branch_align)];
-         diff += (align_addr - 1)  & (align - 2);
-         branch_align = uid_align[INSN_UID (branch_align)];
-         if (insn_addresses[INSN_UID (branch_align)] <= dest_addr
-             && GET_CODE (branch_align) == INSN)
-           {
-             int align2 = 1 << INTVAL (XVECEXP (PATTERN (branch_align), 0, 0));
-             align_addr = insn_addresses[INSN_UID (branch_align)];
-             diff += (align_addr - 1)  & (align2 - align);
-           }
-       }
-      return diff;
-    }
-  else
-    {
-      /* Backward branch. */
-      int branch_addr = insn_addresses[branch_uid];
-      int diff = dest_addr - branch_addr;
-      int old_align = 2;
-
-      while (dest_uid >= uid_align_max || ! uid_align[dest_uid])
-       {
-         /* Label might be outside the insn stream, or even in a separate
-            insn stream, after a syntax error.  */
-         if (! NEXT_INSN (dest))
-           return 0;
-         dest = NEXT_INSN (dest), dest_uid = INSN_UID (dest);
-       }
-      
-      /* By searching for a known destination, we might already have
-        stumbled on the alignment instruction.  */
-      if (GET_CODE (dest) == INSN
-         && GET_CODE (PATTERN (dest)) == UNSPEC_VOLATILE
-         && XINT (PATTERN (dest), 1) == 1
-         && INTVAL (XVECEXP (PATTERN (dest), 0, 0)) > 1)
-       branch_align = dest;
-      else
-       branch_align = uid_align[dest_uid];
-      while (insn_addresses[INSN_UID (branch_align)] <= branch_addr
-            && GET_CODE (branch_align) == INSN)
-       {
-         int align = 1 << INTVAL (XVECEXP (PATTERN (branch_align), 0, 0));
-         int align_addr = insn_addresses[INSN_UID (branch_align)];
-         diff -= (align_addr - 1)  & (align - old_align);
-         old_align = align;
-         branch_align = uid_align[INSN_UID (branch_align)];
-       }
-      return diff;
-    }
-}
-
-int
-short_cbranch_p (branch)
-     rtx branch;
-{
-  int offset;
-
-  if (! insn_addresses)
-    return 0;
-  if (mdep_reorg_phase <= SH_FIXUP_PCLOAD)
-    return 0;
-  offset = branch_offset (branch);
-  return (offset >= -252
-         && offset <= (NEXT_INSN (PREV_INSN (branch)) == branch ? 256 : 254));
-}
-
-/* The maximum range used for SImode constant pool entrys is 1018.  A final
-   instruction can add 8 bytes while only being 4 bytes in size, thus we
-   can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
-   instruction around the pool table, 2 bytes of alignment before the table,
-   and 30 bytes of alignment after the table.  That gives a maximum total
-   pool size of 1058 bytes.
-   Worst case code/pool content size ratio is 1:2 (using asms).
-   Thus, in the worst case, there is one instruction in front of a maximum
-   sized pool, and then there are 1052 bytes of pool for every 508 bytes of
-   code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
-   If we have a forward branch, the initial table will be put after the
-   unconditional branch.
-
-   ??? We could do much better by keeping track of the actual pcloads within
-   the branch range and in the pcload range in front of the branch range.  */
-
-int
-med_branch_p (branch, condlen)
-     rtx branch;
-     int condlen;
-{
-  int offset;
-
-  if (! insn_addresses)
-    return 0;
-  offset = branch_offset (branch);
-  if (mdep_reorg_phase <= SH_FIXUP_PCLOAD)
-    return offset - condlen >= -990 && offset <= 998;
-  return offset - condlen >= -4092 && offset <= 4094;
-}
-
-int
-braf_branch_p (branch, condlen)
-     rtx branch;
-     int condlen;
-{
-  int offset;
-
-  if (! insn_addresses)
-    return 0;
-  if (! TARGET_SH2)
-    return 0;
-  offset = branch_offset (branch);
-  if (mdep_reorg_phase <= SH_FIXUP_PCLOAD)
-    return offset - condlen >= -10330 && offset <= 10330;
-  return offset -condlen >= -32764 && offset <= 32766;
-}
-
-int
-align_length (insn)
-     rtx insn;
-{
-  int align = 1 << INTVAL (XVECEXP (PATTERN (insn), 0, 0));
-  if (! insn_addresses)
-    if (optimize
-       && (mdep_reorg_phase == SH_SHORTEN_BRANCHES0
-           || mdep_reorg_phase == SH_SHORTEN_BRANCHES1))
-      return 0;
-    else
-      return align - 2;
-  return align - 2 - ((insn_addresses[INSN_UID (insn)] - 2) & (align - 2));
+  return insn_addresses[dest_uid];
 }
 \f
 /* Return non-zero if REG is not used after INSN.
index 4a7f094a1e04565c74a82aba29b393fed7b1f18b..746da4fdf715c6741864f78dab7bafda2ac30ac1 100644 (file)
@@ -265,6 +265,33 @@ do {                                                               \
 /* Set this nonzero if move instructions will actually fail to work
    when given unaligned data.  */
 #define STRICT_ALIGNMENT 1
+
+/* If LABEL_AFTER_BARRIER demands an alignment, return its base 2 logarithm.  */
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL_AFTER_BARRIER) \
+  barrier_align (LABEL_AFTER_BARRIER)
+
+#define LOOP_ALIGN(A_LABEL) (TARGET_SMALLCODE ? 0 : 2)
+
+#define LABEL_ALIGN(A_LABEL) \
+(                                                                      \
+  (PREV_INSN (A_LABEL)                                                 \
+   && GET_CODE (PREV_INSN (A_LABEL)) == INSN                           \
+   && GET_CODE (PATTERN (PREV_INSN (A_LABEL))) == UNSPEC_VOLATILE      \
+   && XINT (PATTERN (PREV_INSN (A_LABEL)), 1) == 1)                    \
+   /* explicit alignment insn in constant tables. */                   \
+  ? INTVAL (XVECEXP (PATTERN (PREV_INSN (A_LABEL)), 0, 0))             \
+  : 0)
+
+/* Jump tables must be 32 bit aligned, no matter the size of the element.  */
+#define ADDR_VEC_ALIGN(ADDR_VEC) 2
+
+/* The base two logarithm of the known minimum alignment of an insn length.  */
+#define INSN_LENGTH_ALIGNMENT(A_INSN)                                  \
+  (GET_CODE (A_INSN) == INSN                                           \
+   ? 1                                                                 \
+   : GET_CODE (A_INSN) == JUMP_INSN || GET_CODE (A_INSN) == CALL_INSN  \
+   ? 1                                                                 \
+   : CACHE_LOG)
 \f
 /* Standard register usage.  */
 
@@ -1188,6 +1215,14 @@ extern struct rtx_def *sh_builtin_saveregs ();
    for the index in the tablejump instruction.  */
 #define CASE_VECTOR_MODE (TARGET_BIGTABLE ? SImode : HImode)
 
+#define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \
+((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 127 \
+ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, QImode) \
+ : (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 255 \
+ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, QImode) \
+ : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767 ? HImode \
+ : SImode)
+
 /* Define as C expression which evaluates to nonzero if the tablejump
    instruction expects the table to contain offsets from the address of the
    table.
@@ -1520,14 +1555,10 @@ dtors_section()                                                 \
   ((OUTVAR) = (char *) alloca (strlen (NAME) + 10),    \
    sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
 
-/* Jump tables must be 32 bit aligned, no matter the size of the element.  */
-#define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) \
-  fprintf ((STREAM), "\t.align 2\n%s%d:\n",  (PREFIX), (NUM));
-
 /* Output a relative address table.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL)                     \
-  switch (sh_addr_diff_vec_mode)                                       \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL)                \
+  switch (GET_MODE (BODY))                                             \
     {                                                                  \
     case SImode:                                                       \
       asm_fprintf ((STREAM), "\t.long\t%LL%d-%LL%d\n", (VALUE),(REL)); \
@@ -1672,7 +1703,9 @@ extern enum processor_type sh_cpu;
 
 extern enum machine_mode sh_addr_diff_vec_mode;
 
-extern int optimize; /* needed for gen_casesi, and addr_diff_vec_adjust.  */
+extern int optimize; /* needed for gen_casesi.  */
+
+extern short *label_align;
 
 /* Declare functions defined in sh.c and used in templates.  */
 
@@ -1695,13 +1728,11 @@ enum mdep_reorg_phase_e
   SH_AFTER_MDEP_REORG
 };
 
+extern enum mdep_reorg_phase_e mdep_reorg_phase;
+
 void machine_dependent_reorg ();
-int short_cbranch_p ();
-int med_branch_p ();
-int braf_branch_p ();
-int align_length ();
-int addr_diff_vec_adjust ();
 struct rtx_def *sfunc_uses_reg ();
+int barrier_align ();
 
 #define MACHINE_DEPENDENT_REORG(X) machine_dependent_reorg(X)
 
@@ -1736,11 +1767,7 @@ sh_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 #define MOVE_RATIO (TARGET_SMALLCODE ? 2 : 16)
 \f
 /* Instructions with unfilled delay slots take up an extra two bytes for
-   the nop in the delay slot.  Instructions at the start of loops, or
-   after unconditional branches, may take up extra room when they are
-   aligned.  ??? We would get more accurate results if we did instruction
-   alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
-   here is too conservative.  */
+   the nop in the delay slot.  */
 
 #define ADJUST_INSN_LENGTH(X, LENGTH)                          \
   if (((GET_CODE (X) == INSN                                   \
@@ -1752,25 +1779,7 @@ sh_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
           && GET_CODE (PATTERN (X)) != ADDR_VEC))              \
       && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (X)))) != SEQUENCE \
       && get_attr_needs_delay_slot (X) == NEEDS_DELAY_SLOT_YES)        \
-    (LENGTH) += 2;                                             \
-  if (GET_CODE (X) == INSN                                     \
-      && GET_CODE (PATTERN (X)) == UNSPEC_VOLATILE             \
-      && XINT (PATTERN (X), 1) == 7)                           \
-    (LENGTH) -= addr_diff_vec_adjust (X, LENGTH);              \
-  if (GET_CODE (X) == INSN                                     \
-      && GET_CODE (PATTERN (X)) == UNSPEC_VOLATILE             \
-      && XINT (PATTERN (X), 1) == 1)                           \
-    (LENGTH) = align_length (X);                               \
-  if (GET_CODE (X) == JUMP_INSN                                        \
-      && GET_CODE (PATTERN (X)) == ADDR_DIFF_VEC)              \
-    {                                                          \
-      /* The code before an ADDR_DIFF_VEC is even aligned,     \
-        thus any odd estimate is wrong.  */                    \
-      (LENGTH) &= ~1;                                          \
-      /* If not optimizing, the alignment is implicit.  */     \
-      if (! optimize)                                          \
-       (LENGTH) += 2;                                          \
-    }
+    (LENGTH) += 2;
 
 /* Enable a bug fix for the shorten_branches pass.  */
 #define SHORTEN_WITH_ADJUST_INSN_LENGTH
index e865b881d0090c17ecc4c24727235c4ff082b8b9..93a2ec8b4e49af454403697f8c60a1b846516d3b 100644 (file)
 ; In machine_dependent_reorg, we split all branches that are longer than
 ; 2 bytes.
 
+;; The maximum range used for SImode constant pool entrys is 1018.  A final
+;; instruction can add 8 bytes while only being 4 bytes in size, thus we
+;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
+;; instruction around the pool table, 2 bytes of alignment before the table,
+;; and 30 bytes of alignment after the table.  That gives a maximum total
+;; pool size of 1058 bytes.
+;; Worst case code/pool content size ratio is 1:2 (using asms).
+;; Thus, in the worst case, there is one instruction in front of a maximum
+;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
+;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
+;; If we have a forward branch, the initial table will be put after the
+;; unconditional branch.
+;;
+;; ??? We could do much better by keeping track of the actual pcloads within
+;; the branch range and in the pcload range in front of the branch range.
+
+;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
+;; inside an le.
+(define_attr "short_cbranch_p" "no,yes"
+  (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
+        (const_string "yes")
+        (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
+        (const_string "yes")
+         ] (const_string "no")))
+
+(define_attr "med_branch_p" "no,yes"
+  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
+             (const_int 1988))
+        (const_string "yes")
+        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
+             (const_int 8186))
+        (const_string "yes")
+        ] (const_string "no")))
+
+(define_attr "med_cbranch_p" "no,yes"
+  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
+             (const_int 1986))
+        (const_string "yes")
+        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
+              (const_int 8184))
+        (const_string "yes")
+        ] (const_string "no")))
+
+(define_attr "braf_branch_p" "no,yes"
+  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
+             (const_int 20660))
+        (const_string "yes")
+        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
+             (const_int 65530))
+        (const_string "yes")
+        ] (const_string "no")))
+
+(define_attr "braf_cbranch_p" "no,yes"
+  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
+             (const_int 20658))
+        (const_string "yes")
+        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (const_string "no")
+        (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
+             (const_int 65528))
+        (const_string "yes")
+        ] (const_string "no")))
+
 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
 ; For wider ranges, we need a combination of a code and a data part.
 ; If we can get a scratch register for a long range jump, the code
 
 ; All other instructions are two bytes long by default.
 
+;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
+;; but getattrtab doesn't understand this.
 (define_attr "length" ""
   (cond [(eq_attr "type" "cbranch")
-        (cond [(ne (symbol_ref "short_cbranch_p (insn)") (const_int 0))
+        (cond [(eq_attr "short_cbranch_p" "yes")
                (const_int 2)
-               (ne (symbol_ref "med_branch_p (insn, 2)") (const_int 0))
+               (eq_attr "med_cbranch_p" "yes")
                (const_int 6)
-               (ne (symbol_ref "braf_branch_p (insn, 2)") (const_int 0))
-               (const_int 10)
-               (ne (pc) (pc))
+               (eq_attr "braf_cbranch_p" "yes")
                (const_int 12)
+;; ??? using pc is not computed transitively.
+               (ne (match_dup 0) (match_dup 0))
+               (const_int 14)
                ] (const_int 16))
         (eq_attr "type" "jump")
-        (cond [(ne (symbol_ref "med_branch_p (insn, 0)") (const_int 0))
+        (cond [(eq_attr "med_branch_p" "yes")
                (const_int 2)
                (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
                         (symbol_ref "INSN"))
                     (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
                         (symbol_ref "code_for_indirect_jump_scratch")))
-               (if_then_else (ne (symbol_ref "braf_branch_p (insn, 0)")
-                                 (const_int 0))
+               (if_then_else (eq_attr "braf_branch_p" "yes")
                              (const_int 6)
                              (const_int 10))
-               (ne (symbol_ref "braf_branch_p (insn, 0)") (const_int 0))
+               (eq_attr "braf_branch_p" "yes")
                (const_int 10)
-               (ne (pc) (pc))
+;; ??? using pc is not computed transitively.
+               (ne (match_dup 0) (match_dup 0))
                (const_int 12)
                ] (const_int 14))
         ] (const_int 2)))
   ""
   "*
 {
-  enum machine_mode mode
-    = optimize
-       ? GET_MODE (PATTERN (prev_real_insn (operands[2])))
-       : sh_addr_diff_vec_mode;
-  switch (mode)
+  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
+
+  if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
+    abort ();
+
+  switch (GET_MODE (diff_vec))
     {
     case SImode:
       return \"shll2   %1\;mov.l       @(r0,%1),%0\";
     case HImode:
       return \"add     %1,%1\;mov.w    @(r0,%1),%0\";
     case QImode:
-      {
-       rtx adj = PATTERN (prev_real_insn (operands[2]));
-       if ((insn_addresses[INSN_UID (XEXP ( XVECEXP (adj, 0, 1), 0))]
-            - insn_addresses[INSN_UID (XEXP (XVECEXP (adj, 0, 2), 0))])
-           <= 126)
-         return \"mov.b        @(r0,%1),%0\";
+      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
        return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
-      }
+      return \"mov.b   @(r0,%1),%0\";
     default:
       abort ();
     }
 }"
   [(set_attr "length" "4")])
 
-;; Include ADDR_DIFF_VECS in the shorten_branches pass; we have to
-;; use a negative-length instruction to actually accomplish this.
-(define_insn "addr_diff_vec_adjust"
-  [(unspec_volatile [(label_ref (match_operand 0 "" ""))
-                    (label_ref (match_operand 1 "" ""))
-                    (label_ref (match_operand 2 "" ""))
-                    (match_operand 3 "const_int_operand" "")] 7)]
-  ""
-  "*
-{
-  /* ??? ASM_OUTPUT_ADDR_DIFF_ELT gets passed no context information, so
-     we must use a kludge with a global variable.  */
-  sh_addr_diff_vec_mode = GET_MODE (PATTERN (insn));
-  return \"\";
-}"
-;; Need a variable length for this to be processed in each shorten_branch pass.
-;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes
-;; need to be (a choice of) constants.
-;; We use the calculated length before ADJUST_INSN_LENGTH to
-;; determine if the insn_addresses array contents are valid.
-  [(set (attr "length")
-       (if_then_else (eq (pc) (const_int -1))
-                     (const_int 2) (const_int 0)))])
-
 (define_insn "return"
   [(return)]
   "reload_completed"
 
 ; align to a two byte boundary
 
-(define_insn "align_2"
+(define_expand "align_2"
  [(unspec_volatile [(const_int 1)] 1)]
  ""
- ".align 1"
- [(set_attr "length" "0")
-  (set_attr "in_delay_slot" "no")])
+ "")
 
 ; align to a four byte boundary
 ;; align_4 and align_log are instructions for the starts of loops, or
 (define_insn "align_log"
  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 1)]
  ""
- ".align %O0"
-;; Need a variable length for this to be processed in each shorten_branch pass.
-;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes
-;; need to be (a choice of) constants.
-  [(set (attr "length")
-       (if_then_else (ne (pc) (pc)) (const_int 2) (const_int 0)))
+ ""
+ [(set_attr "length" "0")
   (set_attr "in_delay_slot" "no")])
 
 ; emitted at the end of the literal table, used to emit the
index 6fb6cb621e843fb6d32a999c01834e3d93eb399b..459bffd901bc13a32d148efff6caa29a4f7f2a31 100644 (file)
@@ -133,7 +133,7 @@ Boston, MA 02111-1307, USA.  */
 /* This is how to output an element of a case-vector that is relative.  */
 
 #undef  ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL)
 
 /* This is how to output an element of a case-vector that is absolute.
index ee3fb56424d27515eb69d644d290698ea8249b03..9ec92c872a91466a807e6785ebe1c0079a348d08 100644 (file)
@@ -2969,7 +2969,7 @@ do {                                                                      \
 /* This is how to output an element of a case-vector that is relative.
    (SPARC uses such vectors only when generating PIC.)  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)                     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)               \
 do {                                                                   \
   char label[30];                                                      \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);                     \
index b485d74ac7af20f2c380f69d79467f74b6c5bf20..c75caf6f5f12e0284564ff6539e466db6bf4d904 100644 (file)
@@ -947,7 +947,7 @@ extern int current_function_pretend_args_size;
    (SPUR does not use such vectors,
    but we must define this macro anyway.)  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index e104b4e1610a3daa7a8e3b71c9d2d16ca4a236e8..29ac01392e724e6514050c68913f890c0299e510 100644 (file)
@@ -896,7 +896,7 @@ do {        register int i;                                 \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 207b661fa40fbb22bd4aece51c9a923d39750fb9..9282cba911573e0976e5b7e40cf8b65c3586b517 100644 (file)
@@ -1287,7 +1287,7 @@ do { char dstr[30];                                       \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
   fprintf (FILE, "\t%s .L%d-.L%d\n",                                   \
           (TARGET_BIG_SWITCH ? ".long" : ".short"),                    \
           VALUE, REL)
index 3a296a445c930c539596d979adf7f59c5cb1b291..ecf7ead149a8af4cfbaeae32f599ad4fdc209aca 100644 (file)
@@ -1159,7 +1159,7 @@ do { char dstr[30];                                                       \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index e7d923856c2badc850062c676d7b387e327c0dce..8d8593bc26b3307e7b54605a638ca57ea01d4d7b 100644 (file)
@@ -889,7 +889,7 @@ do {                                                        \
 
 /* This is how to output an element of a case-vector that is relative.  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
   fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL)
 
 /* This is how to output an assembler line
index 5952b1060f74f61b9069a2d72530c22be3ae21e8..99d20d14e55908b5f8054aabcfe24dc06947cc58 100644 (file)
@@ -893,6 +893,7 @@ insn_current_reference_address (branch)
        any alignment we'd encounter, so we skip the call to align_fuzz.  */
     return insn_current_address;
   dest = JUMP_LABEL (branch);
+  /* BRANCH has no proper alignment chain set, so use SEQ.  */
   if (INSN_SHUID (branch) < INSN_SHUID (dest))
     {
       /* Forward branch. */
@@ -1085,13 +1086,12 @@ shorten_branches (first)
   for (i = MAX_CODE_ALIGN; --i >= 0; )
     align_tab[i] = NULL_RTX;
   seq = get_last_insn ();
-  for (insn_current_address = 0; seq; seq = PREV_INSN (seq))
+  for (; seq; seq = PREV_INSN (seq))
     {
       int uid = INSN_UID (seq);
       int log;
       log = (GET_CODE (seq) == CODE_LABEL ? LABEL_TO_ALIGNMENT (seq) : 0);
       uid_align[uid] = align_tab[0];
-      insn_addresses[uid] = --insn_current_address;
       if (log)
        {
          /* Found an alignment label.  */
@@ -1099,14 +1099,63 @@ shorten_branches (first)
          for (i = log - 1; i >= 0; i--)
            align_tab[i] = seq;
        }
-      if (GET_CODE (seq) != INSN || GET_CODE (PATTERN (seq)) != SEQUENCE)
-       insn = seq;
-      else
+    }
+#ifdef CASE_VECTOR_SHORTEN_MODE
+  if (optimize)
+    {
+      /* Look for ADDR_DIFF_VECs, and initialize their minimum and maximum
+         label fields.  */
+
+      int min_shuid = INSN_SHUID (get_insns ()) - 1;
+      int max_shuid = INSN_SHUID (get_last_insn ()) + 1;
+      int rel;
+
+      for (insn = first; insn != 0; insn = NEXT_INSN (insn))
        {
-         insn = XVECEXP (PATTERN (seq), 0, 0);
-         uid = INSN_UID (insn);
+         rtx min_lab = NULL_RTX, max_lab = NULL_RTX, pat;
+         int len, i, min, max, insn_shuid;
+         int min_align;
+         addr_diff_vec_flags flags;
+
+         if (GET_CODE (insn) != JUMP_INSN
+             || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
+           continue;
+         pat = PATTERN (insn);
+         len = XVECLEN (pat, 1);
+         if (len <= 0)
+           abort ();
+         min_align = MAX_CODE_ALIGN;
+         for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--)
+           {
+             rtx lab = XEXP (XVECEXP (pat, 1, i), 0);
+             int shuid = INSN_SHUID (lab);
+             if (shuid < min)
+               {
+                 min = shuid;
+                 min_lab = lab;
+               }
+             if (shuid > max)
+               {
+                 max = shuid;
+                 max_lab = lab;
+               }
+             if (min_align > LABEL_TO_ALIGNMENT (lab))
+               min_align = LABEL_TO_ALIGNMENT (lab);
+           }
+         XEXP (pat, 2) = gen_rtx_LABEL_REF (VOIDmode, min_lab);
+         XEXP (pat, 3) = gen_rtx_LABEL_REF (VOIDmode, max_lab);
+         insn_shuid = INSN_SHUID (insn);
+         rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0));
+         flags.min_align = min_align;
+         flags.base_after_vec = rel > insn_shuid;
+         flags.min_after_vec  = min > insn_shuid;
+         flags.max_after_vec  = max > insn_shuid;
+         flags.min_after_base = min > rel;
+         flags.max_after_base = max > rel;
+         ADDR_DIFF_VEC_FLAGS (pat) = flags;
        }
     }
+#endif /* CASE_VECTOR_SHORTEN_MODE */
 
 
   /* Compute initial lengths, addresses, and varying flags for each insn.  */
@@ -1247,7 +1296,110 @@ shorten_branches (first)
          insn_last_address = insn_addresses[uid];
          insn_addresses[uid] = insn_current_address;
 
-         if (! varying_length[uid])
+         if (optimize && GET_CODE (insn) == JUMP_INSN
+             && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+           {
+#ifdef CASE_VECTOR_SHORTEN_MODE
+             rtx body = PATTERN (insn);
+             int old_length = insn_lengths[uid];
+             rtx rel_lab = XEXP (XEXP (body, 0), 0);
+             rtx min_lab = XEXP (XEXP (body, 2), 0);
+             rtx max_lab = XEXP (XEXP (body, 3), 0);
+             addr_diff_vec_flags flags = ADDR_DIFF_VEC_FLAGS (body);
+             int rel_addr = insn_addresses[INSN_UID (rel_lab)];
+             int min_addr = insn_addresses[INSN_UID (min_lab)];
+             int max_addr = insn_addresses[INSN_UID (max_lab)];
+             rtx prev;
+             int rel_align = 0;
+
+             /* Try to find a known alignment for rel_lab.  */
+             for (prev = rel_lab;
+                  prev
+                  && ! insn_lengths[INSN_UID (prev)]
+                  && ! (varying_length[INSN_UID (prev)] & 1);
+                  prev = PREV_INSN (prev))
+               if (varying_length[INSN_UID (prev)] & 2)
+                 {
+                   rel_align = LABEL_TO_ALIGNMENT (prev);
+                   break;
+                 }
+
+             /* See the comment on addr_diff_vec_flags in rtl.h for the
+                meaning of the flags values.  base: REL_LAB   vec: INSN  */
+             /* Anything after INSN has still addresses from the last
+                pass; adjust these so that they reflect our current
+                estimate for this pass.  */
+             if (flags.base_after_vec)
+               rel_addr += insn_current_address - insn_last_address;
+             if (flags.min_after_vec)
+               min_addr += insn_current_address - insn_last_address;
+             if (flags.max_after_vec)
+               max_addr += insn_current_address - insn_last_address;
+             /* We want to know the worst case, i.e. lowest possible value
+                for the offset of MIN_LAB.  If MIN_LAB is after REL_LAB,
+                its offset is positive, and we have to be wary of code shrink;
+                otherwise, it is negative, and we have to be vary of code
+                size increase.  */
+             if (flags.min_after_base)
+               {
+                 /* If INSN is between REL_LAB and MIN_LAB, the size
+                    changes we are about to make can change the alignment
+                    within the observed offset, therefore we have to break
+                    it up into two parts that are independent.  */
+                 if (! flags.base_after_vec && flags.min_after_vec)
+                   {
+                     min_addr -= align_fuzz (rel_lab, insn, rel_align, 0);
+                     min_addr -= align_fuzz (insn, min_lab, 0, 0);
+                   }
+                 else
+                   min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0);
+               }
+             else
+               {
+                 if (flags.base_after_vec && ! flags.min_after_vec)
+                   {
+                     min_addr -= align_fuzz (min_lab, insn, 0, ~0);
+                     min_addr -= align_fuzz (insn, rel_lab, 0, ~0);
+                   }
+                 else
+                   min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0);
+               }
+             /* Likewise, determine the highest lowest possible value
+                for the offset of MAX_LAB.  */
+             if (flags.max_after_base)
+               {
+                 if (! flags.base_after_vec && flags.max_after_vec)
+                   {
+                     max_addr += align_fuzz (rel_lab, insn, rel_align, ~0);
+                     max_addr += align_fuzz (insn, max_lab, 0, ~0);
+                   }
+                 else
+                   max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0);
+               }
+             else
+               {
+                 if (flags.base_after_vec && ! flags.max_after_vec)
+                   {
+                     max_addr += align_fuzz (max_lab, insn, 0, 0);
+                     max_addr += align_fuzz (insn, rel_lab, 0, 0);
+                   }
+                 else
+                   max_addr += align_fuzz (max_lab, rel_lab, 0, 0);
+               }
+             PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
+                                                       max_addr - rel_addr,
+                                                       body));
+#if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
+             insn_lengths[uid]
+               = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
+             insn_current_address += insn_lengths[uid];
+             if (insn_lengths[uid] != old_length)
+               something_changed = 1;
+#endif
+             continue;
+#endif /* CASE_VECTOR_SHORTEN_MODE */
+           }
+         else if (! (varying_length[uid]))
            {
              insn_current_address += insn_lengths[uid];
              continue;
@@ -2161,6 +2313,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 #ifdef ASM_OUTPUT_ADDR_DIFF_ELT
                    ASM_OUTPUT_ADDR_DIFF_ELT
                      (file,
+                      body,
                       CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
                       CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
 #else
index 9982b6c8980cf87d591b5af9961829d6a5a3b30c..c8ed3e0a6c29136c8abd49a4a86ec5c702935f70 100644 (file)
@@ -442,8 +442,27 @@ DEF_RTL_EXPR(ADDR_VEC, "addr_vec", "E", 'x')
 /* Vector of address differences X0 - BASE, X1 - BASE, ...
    First operand is BASE; the vector contains the X's.
    The machine mode of this rtx says how much space to leave
-   for each difference.  */
-DEF_RTL_EXPR(ADDR_DIFF_VEC, "addr_diff_vec", "eE", 'x')
+   for each difference and is adjusted by branch shortening if
+   CASE_VECTOR_SHORTEN_MODE is defined.
+   The third and fourth operands store the target labels with the
+   minimum and maximum addresses respectively.
+   The fifth operand stores flags for use by branch shortening.
+  Set at the start of shorten_branches:
+   min_align: the minimum alignment for any of the target labels.
+   base_after_vec: true iff BASE is after the ADDR_DIFF_VEC.
+   min_after_vec: true iff minimum addr target label is after the ADDR_DIFF_VEC.
+   max_after_vec: true iff maximum addr target label is after the ADDR_DIFF_VEC.
+   min_after_base: true iff minimum address target label is after BASE.
+   max_after_base: true iff maximum address target label is after BASE.
+  Set by the actual branch shortening process:
+   offset_unsigned: true iff offsets have to be treated as unsigned.
+   scale: scaling that is necessary to make offsets fit into the mode.
+
+   The third, fourth and fifth operands are only valid when
+   CASE_VECTOR_SHORTEN_MODE is defined, and only in an optimizing
+   compilations.  */
+     
+DEF_RTL_EXPR(ADDR_DIFF_VEC, "addr_diff_vec", "eEeei", 'x')
 
 /* ----------------------------------------------------------------------
    At the top level of an instruction (perhaps under PARALLEL).
index 7f7b40f2b2f86dc4dafd945cc290c5ee2c1a6a33..c78b9478258abd864c69842c6555f7071729f950 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -60,6 +60,24 @@ extern char *rtx_format[];
 extern char rtx_class[];
 #define GET_RTX_CLASS(CODE)            (rtx_class[(int) (CODE)])
 \f
+/* The flags and bitfields of an ADDR_DIFF_VEC.  BASE is the base label
+   relative to which the offsets are calculated, as explained in rtl.def.  */
+typedef struct
+{
+  /* Set at the start of shorten_branches - ONLY WHEN OPTIMIZING - : */
+  unsigned min_align: 8;
+  /* Flags: */
+  unsigned base_after_vec: 1; /* BASE is after the ADDR_DIFF_VEC.  */
+  unsigned min_after_vec: 1;  /* minimum address target label is after the ADDR_DIFF_VEC.  */
+  unsigned max_after_vec: 1;  /* maximum address target label is after the ADDR_DIFF_VEC.  */
+  unsigned min_after_base: 1; /* minimum address target label is after BASE.  */
+  unsigned max_after_base: 1; /* maximum address target label is after BASE.  */
+  /* Set by the actual branch shortening process - ONLY WHEN OPTIMIZING - : */
+  unsigned offset_unsigned: 1; /* offsets have to be treated as unsigned.  */
+  unsigned : 2;
+  unsigned scale : 8;
+} addr_diff_vec_flags;
+
 /* Common union for an element of an rtx.  */
 
 typedef union rtunion_def
@@ -70,6 +88,7 @@ typedef union rtunion_def
   struct rtx_def *rtx;
   struct rtvec_def *rtvec;
   enum machine_mode rttype;
+  addr_diff_vec_flags rt_addr_diff_vec_flags;
 } rtunion;
 
 /* RTL expression ("rtx").  */
@@ -318,6 +337,8 @@ typedef struct rtvec_def{
 
 #define REG_NOTES(INSN)        ((INSN)->fld[6].rtx)
 
+#define ADDR_DIFF_VEC_FLAGS(RTX) ((RTX)->fld[4].rt_addr_diff_vec_flags)
+
 /* Don't forget to change reg_note_name in rtl.c.  */
 enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
                REG_EQUAL = 5, REG_RETVAL = 6, REG_LIBCALL = 7,
index c8d51d121e14eae7e23f18aec6c8ab1d265981f8..6d9cf7f95e111d64817d59f1c061ebd8f8851542 100644 (file)
@@ -2004,11 +2004,15 @@ how much space is given to each address; normally @var{m} would be
 @code{Pmode}.
 
 @findex addr_diff_vec
-@item (addr_diff_vec:@var{m} @var{base} [@var{lr0} @var{lr1} @dots{}])
+@item (addr_diff_vec:@var{m} @var{base} [@var{lr0} @var{lr1} @dots{}] @var{min} @var{max} @var{flags})
 Represents a table of jump addresses expressed as offsets from
 @var{base}.  The vector elements @var{lr0}, etc., are @code{label_ref}
 expressions and so is @var{base}.  The mode @var{m} specifies how much
-space is given to each address-difference.@refill
+space is given to each address-difference.  @var{min} and @var{max}
+are set up by branch shortening and hold a label with a minimum and a
+maximum address, respectively.  @var{flags} indicates the relative
+position of @var{base}, @var{min} and @var{max} to the cointaining insn
+and of @var{min} and @var{max} to @var{base}.  See rtl.def for details.@refill
 @end table
 
 @node Incdec, Assembler, Side Effects, RTL
index 20140b3e57bb197056d630fd0c9a83b06be4dac0..8d5d73ec7e838eb6300d08670774738a7e32a704 100644 (file)
@@ -4937,7 +4937,8 @@ expand_end_case (orig_index)
          if (CASE_VECTOR_PC_RELATIVE || flag_pic)
            emit_jump_insn (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
                                                   gen_rtx_LABEL_REF (Pmode, table_label),
-                                                  gen_rtvec_v (ncases, labelvec)));
+                                                  gen_rtvec_v (ncases, labelvec),
+                                                   const0_rtx, const0_rtx, 0));
          else
            emit_jump_insn (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE,
                                              gen_rtvec_v (ncases, labelvec)));
index 95ef9a6ca03cfc12b962c9a8b1a9d3227888d859..e0e31fda7721160971782af68c07440cf4919e81 100644 (file)
@@ -6004,7 +6004,7 @@ This concerns dispatch tables.
 @table @code
 @cindex dispatch table
 @findex ASM_OUTPUT_ADDR_DIFF_ELT
-@item ASM_OUTPUT_ADDR_DIFF_ELT (@var{stream}, @var{value}, @var{rel})
+@item ASM_OUTPUT_ADDR_DIFF_ELT (@var{stream}, @var{body}, @var{value}, @var{rel})
 A C statement to output to the stdio stream @var{stream} an assembler
 pseudo-instruction to generate a difference between two labels.
 @var{value} and @var{rel} are the numbers of two internal labels.  The
@@ -6020,6 +6020,8 @@ fprintf (@var{stream}, "\t.word L%d-L%d\n",
 You must provide this macro on machines where the addresses in a
 dispatch table are relative to the table's own address.  If defined, GNU
 CC will also use this macro on all machines when producing PIC.
+@var{body} is the body of the ADDR_DIFF_VEC; it is provided so that the
+mode and flags can be read.
 
 @findex ASM_OUTPUT_ADDR_VEC_ELT
 @item ASM_OUTPUT_ADDR_VEC_ELT (@var{stream}, @var{value})
@@ -6857,6 +6859,16 @@ patterns.
 An alias for a machine mode name.  This is the machine mode that
 elements of a jump-table should have.
 
+@findex CASE_VECTOR_SHORTEN_MODE
+@item CASE_VECTOR_SHORTEN_MODE (@var{min_offset}, @var{max_offset}, @var{body})
+Optional: return the preferred mode for an @code{addr_diff_vec}
+when the minimum and maximum offset are known.  If you define this,
+it enables extra code in branch shortening to deal with @code{addr_diff_vec}.
+To make this work, you also have to define INSN_ALIGN and 
+make the alignment for @code{addr_diff_vec} explicit.
+The @var{body} argument is provided so that teh offset_unsigned and scale
+flags can be updated.
+
 @findex CASE_VECTOR_PC_RELATIVE
 @item CASE_VECTOR_PC_RELATIVE
 Define this macro to be a C expression to indicate when jump-tables
This page took 0.180628 seconds and 5 git commands to generate.