OSDN Git Service

h
authordlindsay <dlindsay@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Jun 1999 15:09:47 +0000 (15:09 +0000)
committerdlindsay <dlindsay@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Jun 1999 15:09:47 +0000 (15:09 +0000)
Added -mpcrel flag, and underlying support for PC-relative addressing
on m68k. Patch is tested, and approved by Jim Wilson.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27576 138bc75d-0d04-0410-961f-82ee72b054a4

ChangeLog
gcc/config/m68k/hp320.h
gcc/config/m68k/linux.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md
gcc/config/m68k/m68kelf.h
gcc/config/m68k/m68kv4.h

index a9fa0f9..b277359 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+Thu Jun 17 15:06:10 PDT 1999 Don Lindsay  <dlindsay@cygnus.com>
+
+        * added support for -mpcrel (PC relative addressing for m68k) 
+       based on code done by Michael Tiemann  <tiemann@axon.cygnus.com>.
+       * invoke.texi (m68000 options): Add documentation for -mpcrel flag.
+       * m68k.c (print_operand_address): Handle 32-bit PIC case.
+       (comments for general_src_operand): Add some explanation
+       about EXTRA_CONSTRAINTS.
+       (OVERRIDE_OPTIONS): Enable -fPIC in combination with -mpcrel.
+       * m68kelf.h (OVERRIDE_OPTIONS): Ditto.
+       (LEGITIMATE_PIC_OPERAND_P): Fix typo.
+       (LEGITIMATE_PIC_OPERAND_P): Re-derive from m68k.h case.
+       * m68k.h (LEGITIMATE_PIC_OPERAND_P): Fix delete-o.
+       (INDIRECTABLE_1_ADDRESS): Delete spurious '/' at end of macro.
+       (OVERRIDE_OPTIONS): Change behavior so that -mpcrel implies -fpic
+       if not already set.
+       (OVERRIDE_OPTIONS): Merge in changes from m68k.h.
+       * m68k.h (TARGET_PCREL): New target flag.
+       (TARGET_SWITCHES): Add "pcrel" as a recognized switch.
+       (OVERRIDE_OPTIONS): Add checks for -mpcrel.
+       (LEGITIMATE_PIC_OPERAND_P): Don't normally accept anything that
+       contains a SYMBOL_REF.  Relax this constraint during reload, since
+       we want to use the predicates, not reload's built-in concept of a
+       valid memory address, to control what insns need reloading.
+       (EXTRA_CONSTRAINT): Define constraints to accept pc-relative
+       operands (essentially 'g', 'm', and 's' under normal circumstances).
+       * m68k.c (print_operand): Cause printing of pc-relative addresses
+       to include pc register.
+       (print_operand_address): Ditto.
+       (general_src_operand): Accept operands that are not only
+       general_operands, but are also valid when used as a pc-relative
+       source.
+       (nonimmediate_src_operand): Similar, for nonimmediate_operands.
+       (memory_src_operand): Similar, for memory_operands.
+       (pcrel_address): New predicate to accept the special case of a
+       pc-relative address.
+       * m68k.md (many patterns): Rewrite common SImode, HImode, and
+       QImode insns to accept *_src_operand instead of *_operand where
+       pc-relative operands can fit.  For example, a pc-relative operand
+       can be used as a memory source operand for addsi3, but not as a
+       memory destination.
+       * hp320.h linux.h m68kv4.h (LEGITIMATE_PIC_OPERAND_P) as in m68k.h.
+
 Sun May 30 16:03:16 1999  Cort Dougan  <cort@cs.nmt.edu>
 
        * config.guess (ppc-*-linux-gnu): Also use ld emul elf32ppclinux.
index 9816502..977812e 100644 (file)
@@ -635,7 +635,8 @@ do { register int i;                        \
     && ! (GET_CODE (X) == CONST_DOUBLE && CONST_DOUBLE_MEM (X) \
          && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM             \
          && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0), VOIDmode))) \
-   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
+   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X))       \
+   || PCREL_GENERAL_OPERAND_OK)
 
 /* hpux8 and later have C++ compatible include files, so do not
    pretend they are `extern "C"'.  */
index 0df0bd8..a1a4fff 100644 (file)
@@ -310,7 +310,8 @@ do {                                                                        \
     && ! (GET_CODE (X) == CONST_DOUBLE && CONST_DOUBLE_MEM (X) \
          && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM             \
          && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0), VOIDmode))) \
-   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
+   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X))       \
+   || PCREL_GENERAL_OPERAND_OK)
 
 /* Turn off function cse if we are doing PIC. We always want function
    call to be done as `bsr foo@PLTPC', so it will force the assembler
index 98f5197..2d2028b 100644 (file)
@@ -54,6 +54,7 @@ int switch_table_difference_label_flag;
 
 static rtx find_addr_reg ();
 rtx legitimize_pic_address ();
+void print_operand_address ();
 \f
 
 /* Alignment to use for loops and jumps */
@@ -2717,6 +2718,8 @@ standard_sun_fpa_constant_p (x)
    'b' for byte insn (no effect, on the Sun; this is for the ISI).
    'd' to force memory addressing to be absolute, not relative.
    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+   'o' for operands to go directly to output_operand_address (bypassing
+       print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
        than directly).  Second part of 'y' below.
    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
@@ -2793,6 +2796,14 @@ print_operand (file, op, letter)
     {
       asm_fprintf (file, "%R");
     }
+  else if (letter == 'o')
+    {
+      /* This is only for direct addresses with TARGET_PCREL */
+      if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+          || !TARGET_PCREL) 
+       abort ();
+      output_addr_const (file, XEXP (op, 0));
+    }
   else if (GET_CODE (op) == REG)
     {
 #ifdef SUPPORT_SUN_FPA
@@ -2858,7 +2869,14 @@ print_operand (file, op, letter)
     }
   else
     {
-      asm_fprintf (file, "%0I"); output_addr_const (file, op);
+      /* Use `print_operand_address' instead of `output_addr_const'
+        to ensure that we print relevant PIC stuff.  */
+      asm_fprintf (file, "%0I");
+      if (TARGET_PCREL
+         && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
+       print_operand_address (file, op);
+      else
+       output_addr_const (file, op);
     }
 }
 
@@ -3159,7 +3177,7 @@ print_operand_address (file, addr)
            fprintf (file, "l)");
            break;
          }
-       /* FALL-THROUGH (is this really what we want? */
+       /* FALL-THROUGH (is this really what we want? */
       default:
         if (GET_CODE (addr) == CONST_INT
            && INTVAL (addr) < 0x8000
@@ -3176,6 +3194,25 @@ print_operand_address (file, addr)
            fprintf (file, "%d:w", INTVAL (addr));
 #endif
          }
+       else if (GET_CODE (addr) == CONST_INT)
+         {
+           fprintf (file,
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+                    "%d",
+#else
+                    "%ld",
+#endif
+                    INTVAL (addr));
+         }
+       else if (TARGET_PCREL)
+         {
+           fputc ('(', file);
+           output_addr_const (file, addr);
+           if (flag_pic == 1)
+             asm_fprintf (file, ":w,%Rpc)");
+           else
+             asm_fprintf (file, ":l,%Rpc)");
+         }
        else
          {
            /* Special case for SYMBOL_REF if the symbol name ends in
@@ -3288,6 +3325,128 @@ const_sint32_operand (op, mode)
          && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
 }
 
+/* Operand predicates for implementing asymmetric pc-relative addressing
+   on m68k.  The m68k supports pc-relative addressing (mode 7, register 2)
+   when used as a source operand, but not as a destintation operand.
+
+   We model this by restricting the meaning of the basic predicates
+   (general_operand, memory_operand, etc) to forbid the use of this
+   addressing mode, and then define the following predicates that permit
+   this addressing mode.  These predicates can then be used for the
+   source operands of the appropriate instructions.
+
+   n.b.  While it is theoretically possible to change all machine patterns
+   to use this addressing more where permitted by the architecture,
+   it has only been implemented for "common" cases: SImode, HImode, and
+   QImode operands, and only for the principle operations that would
+   require this addressing mode: data movement and simple integer operations.
+
+   In parallel with these new predicates, two new constraint letters
+   were defined: 'S' and 'T'.  'S' is the -mpcrel analog of 'm'.
+   'T' replaces 's' in the non-pcrel case.  It is a no-op in the pcrel case.
+   In the pcrel case 's' is only valid in combination with 'a' registers.
+   See addsi3, subsi3, cmpsi, and movsi patterns for a better understanding
+   of how these constraints are used.
+
+   The use of these predicates is strictly optional, though patterns that
+   don't will cause an extra reload register to be allocated where one
+   was not necessary:
+
+       lea (abc:w,%pc),%a0     ; need to reload address
+       moveq &1,%d1            ; since write to pc-relative space
+       movel %d1,%a0@          ; is not allowed
+       ...
+       lea (abc:w,%pc),%a1     ; no need to reload address here
+       movel %a1@,%d0          ; since "movel (abc:w,%pc),%d0" is ok
+
+   For more info, consult tiemann@cygnus.com.
+
+
+   All of the ugliness with predicates and constraints is due to the
+   simple fact that the m68k does not allow a pc-relative addressing
+   mode as a destination.  gcc does not distinguish between source and
+   destination addresses.  Hence, if we claim that pc-relative address
+   modes are valid, e.g. GO_IF_LEGITIMATE_ADDRESS accepts them, then we
+   end up with invalid code.  To get around this problem, we left
+   pc-relative modes as invalid addresses, and then added special
+   predicates and constraints to accept them.
+
+   A cleaner way to handle this is to modify gcc to distinguish
+   between source and destination addresses.  We can then say that
+   pc-relative is a valid source address but not a valid destination
+   address, and hopefully avoid a lot of the predicate and constraint
+   hackery.  Unfortunately, this would be a pretty big change.  It would
+   be a useful change for a number of ports, but there aren't any current
+   plans to undertake this.
+
+   ***************************************************************************/
+
+
+/* Special case of a general operand that's used as a source operand.
+   Use this to permit reads from PC-relative memory when -mpcrel
+   is specified.  */
+
+int
+general_src_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (TARGET_PCREL
+      && GET_CODE (op) == MEM
+      && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+         || GET_CODE (XEXP (op, 0)) == LABEL_REF
+         || GET_CODE (XEXP (op, 0)) == CONST))
+    return 1;
+  return general_operand (op, mode);
+}
+
+/* Special case of a nonimmediate operand that's used as a source.
+   Use this to permit reads from PC-relative memory when -mpcrel
+   is specified.  */
+
+int
+nonimmediate_src_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (TARGET_PCREL && GET_CODE (op) == MEM
+      && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+         || GET_CODE (XEXP (op, 0)) == LABEL_REF
+         || GET_CODE (XEXP (op, 0)) == CONST))
+    return 1;
+  return nonimmediate_operand (op, mode);
+}
+
+/* Special case of a memory operand that's used as a source.
+   Use this to permit reads from PC-relative memory when -mpcrel
+   is specified.  */
+
+int
+memory_src_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (TARGET_PCREL && GET_CODE (op) == MEM
+      && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+         || GET_CODE (XEXP (op, 0)) == LABEL_REF
+         || GET_CODE (XEXP (op, 0)) == CONST))
+    return 1;
+  return memory_operand (op, mode);
+}
+
+/* Predicate that accepts only a pc-relative address.  This is needed
+   because pc-relative addresses don't satisfy the predicate
+   "general_src_operand".  */
+
+int
+pcrel_address (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
+         || GET_CODE (op) == CONST);
+}
+
 char *
 output_andsi3 (operands)
      rtx *operands;
index 268b639..83af590 100644 (file)
@@ -123,6 +123,18 @@ extern int target_flags;
        /* A 68020 without bitfields is a good heuristic for a CPU32 */
 #define TARGET_CPU32   (TARGET_68020 && !TARGET_BITFIELD)
 
+/* Use PC-relative addressing modes (without using a global offset table).
+   The m68000 supports 16-bit PC-relative addressing.
+   The m68020 supports 32-bit PC-relative addressing
+   (using outer displacements).
+
+   Under this model, all SYMBOL_REFs (and CONSTs) and LABEL_REFs are
+   treated as all containing an implicit PC-relative component, and hence
+   cannot be used directly as addresses for memory writes.  See the comments
+   in m68k.c for more information.  */
+#define MASK_PCREL     4096
+#define TARGET_PCREL   (target_flags & MASK_PCREL)
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -181,6 +193,7 @@ extern int target_flags;
     { "cpu32", MASK_68020},                                            \
     { "align-int", MASK_ALIGN_INT },                                   \
     { "no-align-int", -MASK_ALIGN_INT },                               \
+    { "pcrel", MASK_PCREL},                                            \
     SUBTARGET_SWITCHES                                                 \
     { "", TARGET_DEFAULT}}
 /* TARGET_DEFAULT is defined in sun*.h and isi.h, etc.  */
@@ -215,6 +228,8 @@ extern int target_flags;
   override_options();                  \
   if (! TARGET_68020 && flag_pic == 2) \
     error("-fPIC is not currently supported on the 68000 or 68010\n"); \
+  if (TARGET_PCREL && flag_pic == 0)   \
+    flag_pic = 1;                      \
   SUBTARGET_OVERRIDE_OPTIONS;          \
 }
 
@@ -760,11 +775,35 @@ extern enum reg_class regno_reg_class[];
    C.  If C is not defined as an extra constraint, the value returned should 
    be 0 regardless of VALUE.  */
 
-/* For the m68k, `Q' means address register indirect addressing mode. */
-
-#define EXTRA_CONSTRAINT(OP, C)        \
-  ((C) == 'Q' ? (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) : \
-   0 )
+/* Letters in the range `Q' through `U' may be defined in a
+   machine-dependent fashion to stand for arbitrary operand types. 
+   The machine description macro `EXTRA_CONSTRAINT' is passed the
+   operand as its first argument and the constraint letter as its
+   second operand.
+
+   `Q' means address register indirect addressing mode.
+   `S' is for operands that satisfy 'm' when -mpcrel is in effect.
+   `T' is for operands that satisfy 's' when -mpcrel is not in effect.  */
+
+#define EXTRA_CONSTRAINT(OP,CODE)                      \
+  (((CODE) == 'S')                                     \
+   ? (TARGET_PCREL                                     \
+      && GET_CODE (OP) == MEM                          \
+      && (GET_CODE (XEXP (OP, 0)) == SYMBOL_REF                \
+         || GET_CODE (XEXP (OP, 0)) == LABEL_REF       \
+         || GET_CODE (XEXP (OP, 0)) == CONST))         \
+   :                                                   \
+  (((CODE) == 'T')                                     \
+   ? ( !TARGET_PCREL                                   \
+      && (GET_CODE (OP) == SYMBOL_REF                  \
+         || GET_CODE (OP) == LABEL_REF                 \
+         || GET_CODE (OP) == CONST))                   \
+   :                                                   \
+  (((CODE) == 'Q')                                     \
+   ? (GET_CODE (OP) == MEM                             \
+      && GET_CODE (XEXP (OP, 0)) == REG)               \
+   :                                                   \
+   0)))
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
@@ -789,6 +828,10 @@ extern enum reg_class regno_reg_class[];
    ? (! CONST_DOUBLE_OK_FOR_LETTER_P (X, 'G')  \
       && (CLASS == FP_REGS || CLASS == DATA_OR_FP_REGS) \
       ? FP_REGS : NO_REGS)                     \
+   : (TARGET_PCREL                             \
+      && (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
+         || GET_CODE (X) == LABEL_REF))        \
+   ? ADDR_REGS                                 \
    : (CLASS))
 
 /* Force QImode output reloads from subregs to be allocated to data regs,
@@ -1353,7 +1396,17 @@ __transfer_from_trampoline ()                                    \
 
 /* Nonzero if the constant value X is a legitimate general operand
    when generating PIC code.  It is given that flag_pic is on and 
-   that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
+   that X satisfies CONSTANT_P or is a CONST_DOUBLE.
+
+   PCREL_GENERAL_OPERAND_OK makes reload accept addresses that are
+   accepted by insn predicates, but which would otherwise fail the
+   `general_operand' test.  */
+
+#ifndef REG_OK_STRICT
+#define PCREL_GENERAL_OPERAND_OK 0
+#else
+#define PCREL_GENERAL_OPERAND_OK (TARGET_PCREL)
+#endif
 
 #define LEGITIMATE_PIC_OPERAND_P(X)    \
   ((! symbolic_operand (X, VOIDmode)                           \
@@ -1361,7 +1414,8 @@ __transfer_from_trampoline ()                                     \
          && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM             \
          && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0),  \
                               VOIDmode)))                      \
-   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
+   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X))      \
+   || PCREL_GENERAL_OPERAND_OK)
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -1431,7 +1485,7 @@ __transfer_from_trampoline ()                                     \
    || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx     \
        && flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF)            \
    || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx     \
-       && flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF))            \
+       && flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF))
 
 #define GO_IF_NONINDEXED_ADDRESS(X, ADDR)  \
 { if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; }
@@ -2032,6 +2086,8 @@ do { long l;                                              \
    'b' for byte insn (no effect, on the Sun; this is for the ISI).
    'd' to force memory addressing to be absolute, not relative.
    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+   'o' for operands to go directly to output_operand_address (bypassing
+       print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
        than directly).  Second part of 'y' below.
    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
index a8dac72..c36e5dd 100644 (file)
   "
 {
   m68k_last_compare_had_fp_operands = 0;
-  if (flag_pic && symbolic_operand (operands[1], SImode))
+  if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
     {
       /* The source is an address which requires PIC relocation.
          Call legitimize_pic_address with the source, mode, and a relocation
 ;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>")
-                (match_operand:SI 1 "general_operand" "mr,rKs,>")))]
+        (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mSr,mSa,>")
+                 (match_operand:SI 1 "general_src_operand" "mSr,mSa,KTr,Ksr,>")))]
   "!TARGET_5200"
   "*
 {
 
 (define_expand "cmphi"
   [(set (cc0)
-       (compare (match_operand:HI 0 "nonimmediate_operand" "")
-                (match_operand:HI 1 "general_operand" "")))]
+        (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
+                 (match_operand:HI 1 "general_src_operand" "")))]
   "!TARGET_5200"
   "m68k_last_compare_had_fp_operands = 0;")
 
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
-                (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+        (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>")
+                 (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))]
   "!TARGET_5200"
   "*
 {
 
 (define_expand "cmpqi"
   [(set (cc0)
-       (compare (match_operand:QI 0 "nonimmediate_operand" "")
-                (match_operand:QI 1 "general_operand" "")))]
+        (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
+                 (match_operand:QI 1 "general_src_operand" "")))]
   "!TARGET_5200"
   "m68k_last_compare_had_fp_operands = 0;")
 
 (define_insn ""
   [(set (cc0)
-       (compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>")
-                (match_operand:QI 1 "general_operand" "dm,nd,>")))]
+        (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>")
+                 (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))]
   "!TARGET_5200"
   "*
 {
 ;; from a MEM at a constant bit position if we can't use this as a constraint.
 
 (define_insn ""
-  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
+  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_src_operand" "oS")
                            (const_int 1)
                            (minus:SI (const_int 7)
                                      (match_operand:SI 1 "general_operand" "di"))))]
   ""
   "
 {
-  if (flag_pic && symbolic_operand (operands[1], SImode))
+  if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
     {
       /* The source is an address which requires PIC relocation.
          Call legitimize_pic_address with the source, mode, and a relocation
       rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
       operands[1] = legitimize_pic_address (operands[1], SImode, temp);
     }
+  else if (flag_pic && TARGET_PCREL && ! reload_in_progress)
+    {
+      /* Don't allow writes to memory except via a register;
+        the m68k doesn't consider PC-relative addresses to be writable.  */
+      if (symbolic_operand (operands[0], SImode))
+       operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+      else if (GET_CODE (operands[0]) == MEM
+              && symbolic_operand (XEXP (operands[0], 0), SImode))
+       operands[0] = gen_rtx (MEM, SImode,
+                              force_reg (SImode, XEXP (operands[0], 0)));
+    }
 }")
 
 ;; General case of fullword move.  The register constraints
   ;; Notes: make sure no alternative allows g vs g.
   ;; We don't allow f-regs since fixed point cannot go in them.
   ;; We do allow y and x regs since fixed point is allowed in them.
-  [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
-       (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
+  [(set (match_operand:SI 0 "general_operand" "=g,d,a<,y,!*x*r*m")
+        (match_operand:SI 1 "general_src_operand" "daymSKT,n,i,g,*x*r*m"))]
+
   "!TARGET_5200"
   "*
 {
-  if (which_alternative == 3)
+  if (which_alternative == 4)
     return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
   if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
     return \"fpmove%.l %x1,%x0\";
   "TARGET_5200"
   "* return output_move_simode (operands);")
 
+;; Special case of fullword move, where we need to get a non-GOT PIC
+;; reference into an address register.
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=a<")
+        (match_operand:SI 1 "pcrel_address" ""))]
+  "TARGET_PCREL"
+  "*
+{
+  if (push_operand (operands[0], SImode))
+    return \"pea %a1\";
+  return \"lea %a1,%0\";
+}")
+
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand" "")
        (match_operand:HI 1 "general_operand" ""))]
 
 (define_insn ""
   [(set (match_operand:HI 0 "general_operand" "=g")
-       (match_operand:HI 1 "general_operand" "g"))]
+        (match_operand:HI 1 "general_src_operand" "gS"))]
   "!TARGET_5200"
   "* return output_move_himode (operands);")
 
 
 (define_expand "movstricthi"
   [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
-       (match_operand:HI 1 "general_operand" ""))]
+        (match_operand:HI 1 "general_src_operand" ""))]
   ""
   "")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
-       (match_operand:HI 1 "general_operand" "rmn"))]
+       (match_operand:HI 1 "general_src_operand" "rmSn"))]
   "!TARGET_5200"
   "* return output_move_stricthi (operands);")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+d,m"))
-       (match_operand:HI 1 "general_operand" "rmn,r"))]
+       (match_operand:HI 1 "general_src_operand" "rmn,r"))]
   "TARGET_5200"
   "* return output_move_stricthi (operands);")
 
 (define_expand "movqi"
   [(set (match_operand:QI 0 "general_operand" "")
-       (match_operand:QI 1 "general_operand" ""))]
+        (match_operand:QI 1 "general_src_operand" ""))]
   ""
   "")
 
 (define_insn ""
   [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
-       (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))]
+       (match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
   "!TARGET_5200"
   "* return output_move_qimode (operands);")
 
 (define_insn ""
   [(set (match_operand:QI 0 "general_operand" "=d<Q>,dm,d*a")
-       (match_operand:QI 1 "general_operand" "dmi,d<Q>,di*a"))]
+       (match_operand:QI 1 "general_src_operand" "dmi,d<Q>,di*a"))]
   "TARGET_5200"
   "* return output_move_qimode (operands);")
 
 (define_expand "movstrictqi"
   [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
-       (match_operand:QI 1 "general_operand" ""))]
+        (match_operand:QI 1 "general_src_operand" ""))]
   ""
   "")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
-       (match_operand:QI 1 "general_operand" "dmn"))]
+       (match_operand:QI 1 "general_src_operand" "dmSn"))]
   "!TARGET_5200"
   "* return output_move_strictqi (operands);")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+d,m"))
-       (match_operand:QI 1 "general_operand" "dmn,d"))]
+       (match_operand:QI 1 "general_src_operand" "dmn,d"))]
   "TARGET_5200"
   "* return output_move_strictqi (operands);")
 
        operands[1] = change_address (operands[1], XFmode,
                                      XEXP (operands[1], 0));
     }
+  if (flag_pic && TARGET_PCREL && ! reload_in_progress)
+    {
+      /* Don't allow writes to memory except via a register;
+        the m68k doesn't consider PC-relative addresses to be writable.  */
+      if (GET_CODE (operands[0]) == MEM
+         && symbolic_operand (XEXP (operands[0], 0), SImode))
+       operands[0] = gen_rtx (MEM, XFmode,
+                              force_reg (SImode, XEXP (operands[0], 0)));
+    }
 }")
 
 (define_insn ""
 (define_insn "truncsiqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm,d")
        (truncate:QI
-        (match_operand:SI 1 "general_operand" "doJ,i")))]
+        (match_operand:SI 1 "general_src_operand" "doJS,i")))]
   ""
   "*
 {
 (define_insn "trunchiqi2"
   [(set (match_operand:QI 0 "general_operand" "=dm,d")
        (truncate:QI
-        (match_operand:HI 1 "general_operand" "doJ,i")))]
+        (match_operand:HI 1 "general_src_operand" "doJS,i")))]
   ""
   "*
 {
 (define_insn "truncsihi2"
   [(set (match_operand:HI 0 "general_operand" "=dm,d")
        (truncate:HI
-        (match_operand:SI 1 "general_operand" "roJ,i")))]
+        (match_operand:SI 1 "general_src_operand" "roJS,i")))]
   ""
   "*
 {
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=do<>,d<")
-       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn ""
   [(set (match_operand:HI 0 "general_operand" "=do<>,d")
-       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+       (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=do<>,d")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
   "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
 
 (define_insn "extendqidi2"
   [(set (match_operand:DI 0 "general_operand" "=d")
-       (sign_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
+        (sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
   ""
   "*
 {
 (define_insn "extendhidi2"
   [(set (match_operand:DI 0 "general_operand" "=d")
        (sign_extend:DI
-        (match_operand:HI 1 "general_operand" "rm")))]
+        (match_operand:HI 1 "general_src_operand" "rmS")))]
   ""
   "*
 {
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "general_operand" "=*d,a")
        (sign_extend:SI
-        (match_operand:HI 1 "nonimmediate_operand" "0,rm")))]
+        (match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))]
   ""
   "*
 {
 (define_expand "addsi3"
   [(set (match_operand:SI 0 "general_operand" "")
        (plus:SI (match_operand:SI 1 "general_operand" "")
-                (match_operand:SI 2 "general_operand" "")))]
+                (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 ;; This is needed since they are not themselves reloaded,
 ;; so commutativity won't apply to them.
 (define_insn "*addsi3_internal"
-  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
-       (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
-                (match_operand:SI 2 "general_operand" "dIKLs,rJK,a,mrIKLs")))]
+  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,d,a")
+        (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0")
+                 (match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))]
+
+
   "! TARGET_5200"
   "* return output_addsi3 (operands);")
 
 (define_insn "*addsi3_5200"
   [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
        (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
-                (match_operand:SI 2 "general_operand" "d,rJK,a,mrIKLs")))]
+                (match_operand:SI 2 "general_src_operand" "d,rJK,a,mrIKLs")))]
   "TARGET_5200"
   "* return output_addsi3 (operands);")
 
   [(set (match_operand:SI 0 "general_operand" "=a")
        (plus:SI (match_operand:SI 1 "general_operand" "0")
                 (sign_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
   "!TARGET_5200"
   "add%.w %2,%0")
 
 (define_insn "addhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,r")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
-                (match_operand:HI 2 "general_operand" "dn,rmn")))]
+                (match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "*
 {
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (plus:HI (match_dup 0)
-                (match_operand:HI 1 "general_operand" "dn,rmn")))]
+                (match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "*
 {
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
+       (plus:HI (match_operand:HI 1 "general_src_operand" "dn,rmSn")
                 (match_dup 0)))]
   "!TARGET_5200"
   "*
 (define_insn "addqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
-                (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "*
 {
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (plus:QI (match_dup 0)
-                (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "*
 {
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+       (plus:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                 (match_dup 0)))]
   "!TARGET_5200"
   "*
 } ")
 
 (define_insn "subsi3"
-  [(set (match_operand:SI 0 "general_operand" "=m,r")
-       (minus:SI (match_operand:SI 1 "general_operand" "0,0")
-                 (match_operand:SI 2 "general_operand" "ds,mrs")))]
+  [(set (match_operand:SI 0 "general_operand" "=m,d,a")
+       (minus:SI (match_operand:SI 1 "general_operand" "0,0,0")
+                 (match_operand:SI 2 "general_src_operand" "dT,mSrT,mSrs")))]
   ""
   "sub%.l %2,%0")
 
   [(set (match_operand:SI 0 "general_operand" "=a")
        (minus:SI (match_operand:SI 1 "general_operand" "0")
                  (sign_extend:SI
-                  (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+                  (match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
   "!TARGET_5200"
   "sub%.w %2,%0")
 
 (define_insn "subhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,r")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
-                 (match_operand:HI 2 "general_operand" "dn,rmn")))]
+                 (match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "sub%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (minus:HI (match_dup 0)
-                 (match_operand:HI 1 "general_operand" "dn,rmn")))]
+                 (match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
   "!TARGET_5200"
   "sub%.w %1,%0")
 
 (define_insn "subqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (minus:QI (match_operand:QI 1 "general_operand" "0,0")
-                 (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                 (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "sub%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (minus:QI (match_dup 0)
-                 (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                 (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "sub%.b %1,%0")
 
 (define_insn "mulhi3"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (mult:HI (match_operand:HI 1 "general_operand" "%0")
-                (match_operand:HI 2 "general_operand" "dmn")))]
+                (match_operand:HI 2 "general_src_operand" "dmSn")))]
   ""
   "*
 {
        (mult:SI (sign_extend:SI
                  (match_operand:HI 1 "nonimmediate_operand" "%0"))
                 (sign_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "dmS"))))]
   ""
   "*
 {
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=d")
        (mult:SI (match_operand:SI 1 "general_operand" "%0")
-                (match_operand:SI 2 "general_operand" "dmsK")))]
+                 (match_operand:SI 2 "general_src_operand" "dmSTK")))]
+
   "TARGET_68020"
   "muls%.l %2,%0")
 
        (mult:SI (zero_extend:SI
                  (match_operand:HI 1 "nonimmediate_operand" "%0"))
                 (zero_extend:SI
-                 (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+                 (match_operand:HI 2 "nonimmediate_src_operand" "dmS"))))]
   ""
   "*
 {
 (define_insn "divmodsi4"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (div:SI (match_operand:SI 1 "general_operand" "0")
-               (match_operand:SI 2 "general_operand" "dmsK")))
+               (match_operand:SI 2 "general_src_operand" "dmSTK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (mod:SI (match_dup 1) (match_dup 2)))]
   "TARGET_68020 && !TARGET_5200"
 (define_insn "udivmodsi4"
   [(set (match_operand:SI 0 "general_operand" "=d")
        (udiv:SI (match_operand:SI 1 "general_operand" "0")
-                (match_operand:SI 2 "general_operand" "dmsK")))
+                (match_operand:SI 2 "general_src_operand" "dmSTK")))
    (set (match_operand:SI 3 "general_operand" "=d")
        (umod:SI (match_dup 1) (match_dup 2)))]
   "TARGET_68020 && !TARGET_5200"
 (define_insn "divmodhi4"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (div:HI (match_operand:HI 1 "general_operand" "0")
-               (match_operand:HI 2 "general_operand" "dmsK")))
+               (match_operand:HI 2 "general_src_operand" "dmSKT")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (mod:HI (match_dup 1) (match_dup 2)))]
   "!TARGET_5200"
 (define_insn "udivmodhi4"
   [(set (match_operand:HI 0 "general_operand" "=d")
        (udiv:HI (match_operand:HI 1 "general_operand" "0")
-                (match_operand:HI 2 "general_operand" "dmsK")))
+                (match_operand:HI 2 "general_src_operand" "dmSKT")))
    (set (match_operand:HI 3 "general_operand" "=d")
        (umod:HI (match_dup 1) (match_dup 2)))]
   "!TARGET_5200"
 ;; can't allocate pseudos into it.
 
 (define_expand "andsi3"
-  [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
-       (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+  [(set (match_operand:SI 0 "not_sp_operand" "")
+       (and:SI (match_operand:SI 1 "general_operand" "")
+               (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 (define_insn "andsi3_internal"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+               (match_operand:SI 2 "general_src_operand" "dKT,dmSM")))]
   "!TARGET_5200"
   "*
 {
 (define_insn "andsi3_5200"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "d,dmsK")))]
+               (match_operand:SI 2 "general_src_operand" "d,dmsK")))]
   "TARGET_5200"
   "and%.l %2,%0")
 
 (define_insn "andhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,d")
        (and:HI (match_operand:HI 1 "general_operand" "%0,0")
-               (match_operand:HI 2 "general_operand" "dn,dmn")))]
+               (match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (and:HI (match_dup 0)
-               (match_operand:HI 1 "general_operand" "dn,dmn")))]
+               (match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.w %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (and:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+       (and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "and%.w %1,%0")
 (define_insn "andqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (and:QI (match_operand:QI 1 "general_operand" "%0,0")
-               (match_operand:QI 2 "general_operand" "dn,dmn")))]
+               (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (and:QI (match_dup 0)
-               (match_operand:QI 1 "general_operand" "dn,dmn")))]
+               (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "and%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (and:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+       (and:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "and%.b %1,%0")
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "general_operand" "")
        (ior:SI (match_operand:SI 1 "general_operand" "")
-               (match_operand:SI 2 "general_operand" "")))]
+               (match_operand:SI 2 "general_src_operand" "")))]
   ""
   "")
 
 (define_insn "iorsi3_internal"
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+                (match_operand:SI 2 "general_src_operand" "dKT,dmSMT")))]
   "! TARGET_5200"
   "*
 {
 (define_insn "iorsi3_5200"
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "d,dmsK")))]
+               (match_operand:SI 2 "general_src_operand" "d,dmsK")))]
   "TARGET_5200"
   "or%.l %2,%0")
 
 (define_insn "iorhi3"
   [(set (match_operand:HI 0 "general_operand" "=m,d")
        (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
-               (match_operand:HI 2 "general_operand" "dn,dmn")))]
+               (match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.w %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
        (ior:HI (match_dup 0)
-               (match_operand:HI 1 "general_operand" "dn,dmn")))]
+               (match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.w %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
-       (ior:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+       (ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "or%.w %1,%0")
 (define_insn "iorqi3"
   [(set (match_operand:QI 0 "general_operand" "=m,d")
        (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
-               (match_operand:QI 2 "general_operand" "dn,dmn")))]
+                (match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.b %2,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
        (ior:QI (match_dup 0)
-               (match_operand:QI 1 "general_operand" "dn,dmn")))]
+                (match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
   "!TARGET_5200"
   "or%.b %1,%0")
 
 (define_insn ""
   [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
-       (ior:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+        (ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
                (match_dup 0)))]
   "!TARGET_5200"
   "or%.b %1,%0")
 (define_insn "xorsi3_internal"
   [(set (match_operand:SI 0 "general_operand" "=do,m")
        (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
-               (match_operand:SI 2 "general_operand" "di,dKs")))]
+                (match_operand:SI 2 "general_operand" "di,dKT")))]
+
   "!TARGET_5200"
   "*
 {
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
                         (const_int 32)
                         (match_operand:SI 2 "const_int_operand" "n"))
-       (match_operand:SI 3 "general_operand" "rmi"))]
+       (match_operand:SI 3 "general_src_operand" "rmSi"))]
   "TARGET_68020 && TARGET_BITFIELD
    && (INTVAL (operands[2]) % 8) == 0
    && ! mode_dependent_address_p (XEXP (operands[0], 0))"
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
+       (zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
                         (const_int 32)
                         (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
 ;
 (define_insn ""
   [(set (match_operand:SI 0 "general_operand" "=rm")
-       (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+       (sign_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
                         (const_int 32)
                         (match_operand:SI 3 "const_int_operand" "n")))]
   "TARGET_68020 && TARGET_BITFIELD
   "*
   if (GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+    {
+      if (TARGET_PCREL) return \"bsr.l %o0\";
 #ifdef MOTOROLA
 #ifdef HPUX_ASM
-    return \"bsr.l %0\";
+      return \"bsr.l %0\";
 #else
 #ifdef USE_GAS
-    return \"bsr.l %0@PLTPC\";
+      return \"bsr.l %0@PLTPC\";
 #else
-    return \"bsr %0@PLTPC\";
+      return \"bsr %0@PLTPC\";
 #endif
 #endif
 #else
-    /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
-       GAS just plain ignores it.  */
-    return \"jbsr %0,a1\";
+#ifdef USE_GAS
+      return \"bsr.l %0\";
+#else
+      /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
+        GAS just plain ignores it.  FIXME: not anymore, gas doesnt!  */
+      return \"jbsr %0,a1\";
 #endif
+#endif
+    }
   return \"jsr %0\";
 ")
 
   if (GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
     {
+      if (TARGET_PCREL) return \"bsr.l %o1\";
 #ifdef MOTOROLA
 #ifdef HPUX_ASM
       return \"bsr.l %1\";
 #endif
 #endif
 #else
+#ifdef USE_GAS
+      return \"bsr.l %1\";
+#else
       /* The ',a1' is a dummy argument telling the Sun assembler we want PIC
-         GAS just plain ignores it.  */
+         GAS just plain ignores it.  FIXME: Not anymore, gas doesnt!  */
       return \"jbsr %1,a1\";
 #endif
+#endif
     }
   return \"jsr %1\";
 ")
index 476692d..88dfc3d 100644 (file)
@@ -246,9 +246,11 @@ extern int switch_table_difference_label_flag;
 /* In m68k svr4, a symbol_ref rtx can be a valid PIC operand if it is an
    operand of a function call. */
 #undef LEGITIMATE_PIC_OPERAND_P
-#define LEGITIMATE_PIC_OPERAND_P(X) \
-  (! symbolic_operand (X, VOIDmode) \
-   || ((GET_CODE(X) == SYMBOL_REF) && SYMBOL_REF_FLAG(X)))
+
+#define LEGITIMATE_PIC_OPERAND_P(X)    \
+  (! symbolic_operand (X, VOIDmode)                            \
+   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X))      \
+   || PCREL_GENERAL_OPERAND_OK)
 
 /* Turn off function cse if we are doing PIC. We always want function call
    to be done as `bsr foo@PLTPC', so it will force the assembler to create 
@@ -261,6 +263,8 @@ extern int switch_table_difference_label_flag;
   if (flag_pic) flag_no_function_cse = 1; \
   if (! TARGET_68020 && flag_pic == 2) \
     error("-fPIC is not currently supported on the 68000 or 68010\n"); \
+  if (TARGET_PCREL && flag_pic == 0)   \
+    flag_pic = 1;                      \
 }
 /* end of stuff from m68kv4.h */
 
index 16cc1c9..9f2744d 100644 (file)
@@ -297,7 +297,8 @@ int switch_table_difference_label_flag;
     && ! (GET_CODE (X) == CONST_DOUBLE && CONST_DOUBLE_MEM (X) \
          && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM             \
          && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0), VOIDmode))) \
-   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
+   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X))       \
+   || PCREL_GENERAL_OPERAND_OK)
 
 /* Turn off function cse if we are doing PIC. We always want function call
    to be done as `bsr foo@PLTPC', so it will force the assembler to create