From 2c8ec431e3d004bab9f620815ffafe7d3be3597e Mon Sep 17 00:00:00 2001 From: Don Lindsay Date: Thu, 17 Jun 1999 15:09:47 +0000 Subject: [PATCH] Added -mpcrel flag, and underlying support for PC-relative addressing on m68k. h Added -mpcrel flag, and underlying support for PC-relative addressing on m68k. Patch is tested, and approved by Jim Wilson. From-SVN: r27576 --- ChangeLog | 43 +++++++ gcc/config/m68k/hp320.h | 3 +- gcc/config/m68k/linux.h | 3 +- gcc/config/m68k/m68k.c | 163 +++++++++++++++++++++++++- gcc/config/m68k/m68k.h | 70 +++++++++-- gcc/config/m68k/m68k.md | 238 +++++++++++++++++++++++--------------- gcc/config/m68k/m68kelf.h | 10 +- gcc/config/m68k/m68kv4.h | 3 +- 8 files changed, 424 insertions(+), 109 deletions(-) diff --git a/ChangeLog b/ChangeLog index a9fa0f985f7..b2773591962 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +Thu Jun 17 15:06:10 PDT 1999 Don Lindsay + + * added support for -mpcrel (PC relative addressing for m68k) + based on code done by Michael Tiemann . + * 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 * config.guess (ppc-*-linux-gnu): Also use ld emul elf32ppclinux. diff --git a/gcc/config/m68k/hp320.h b/gcc/config/m68k/hp320.h index 98165029962..977812e65a8 100644 --- a/gcc/config/m68k/hp320.h +++ b/gcc/config/m68k/hp320.h @@ -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"'. */ diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h index 0df0bd8e575..a1a4fffbb20 100644 --- a/gcc/config/m68k/linux.h +++ b/gcc/config/m68k/linux.h @@ -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 diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 98f51978ac8..2d2028b8caa 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -54,6 +54,7 @@ int switch_table_difference_label_flag; static rtx find_addr_reg (); rtx legitimize_pic_address (); +void print_operand_address (); /* 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; diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 268b639d8b7..83af5901299 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -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. */ +/* 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. -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' ? (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) : \ - 0 ) + `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), diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index a8dac721d99..c36e5dd3fae 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -502,7 +502,7 @@ " { 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 @@ -517,8 +517,8 @@ ;; 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" "* { @@ -580,15 +580,15 @@ (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" "* { @@ -616,15 +616,15 @@ (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" "* { @@ -765,7 +765,7 @@ ;; 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"))))] @@ -948,7 +948,7 @@ "" " { - 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 @@ -958,6 +958,17 @@ 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 @@ -967,12 +978,13 @@ ;; 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\"; @@ -985,6 +997,19 @@ "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" ""))] @@ -993,7 +1018,7 @@ (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);") @@ -1005,55 +1030,55 @@ (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,dm,d*a") - (match_operand:QI 1 "general_operand" "dmi,d,di*a"))] + (match_operand:QI 1 "general_src_operand" "dmi,d,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);") @@ -1234,6 +1259,15 @@ 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 "" @@ -1398,7 +1432,7 @@ (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")))] "" "* { @@ -1417,7 +1451,7 @@ (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")))] "" "* { @@ -1445,7 +1479,7 @@ (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")))] "" "* { @@ -1565,7 +1599,7 @@ (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" "* { @@ -1594,7 +1628,7 @@ (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" "* { @@ -1635,7 +1669,7 @@ (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" "* { @@ -1688,7 +1722,7 @@ (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")))] "" "* { @@ -1703,7 +1737,7 @@ (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")))] "" "* { @@ -1765,7 +1799,7 @@ (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")))] "" "* { @@ -2278,7 +2312,7 @@ (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" "")))] "" "") @@ -2287,16 +2321,18 @@ ;; 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);") @@ -2304,14 +2340,14 @@ [(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" "* { @@ -2373,7 +2409,7 @@ (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" "* { @@ -2428,7 +2464,7 @@ (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" "* @@ -2485,7 +2521,7 @@ (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" "* { @@ -2511,7 +2547,7 @@ (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" "* { @@ -2536,7 +2572,7 @@ (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" "* @@ -2802,9 +2838,9 @@ } ") (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") @@ -2812,35 +2848,35 @@ [(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") @@ -2961,7 +2997,7 @@ (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")))] "" "* { @@ -2977,7 +3013,7 @@ (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"))))] "" "* { @@ -3013,7 +3049,8 @@ (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") @@ -3029,7 +3066,7 @@ (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"))))] "" "* { @@ -3519,7 +3556,7 @@ (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" @@ -3534,7 +3571,7 @@ (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" @@ -3549,7 +3586,7 @@ (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" @@ -3572,7 +3609,7 @@ (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" @@ -3675,16 +3712,16 @@ ;; 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" "* { @@ -3694,27 +3731,27 @@ (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") @@ -3722,20 +3759,20 @@ (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") @@ -3850,14 +3887,14 @@ (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" "* { @@ -3867,27 +3904,27 @@ (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") @@ -3895,20 +3932,20 @@ (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") @@ -4046,7 +4083,8 @@ (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" "* { @@ -5267,7 +5305,7 @@ [(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))" @@ -5318,7 +5356,7 @@ ; (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 @@ -5372,7 +5410,7 @@ ; (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 @@ -6823,21 +6861,28 @@ "* 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\"; ") @@ -6887,6 +6932,7 @@ 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\"; @@ -6897,10 +6943,14 @@ return \"bsr %1@PLTPC\"; #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\"; diff --git a/gcc/config/m68k/m68kelf.h b/gcc/config/m68k/m68kelf.h index 476692db31d..88dfc3db9a2 100644 --- a/gcc/config/m68k/m68kelf.h +++ b/gcc/config/m68k/m68kelf.h @@ -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 */ diff --git a/gcc/config/m68k/m68kv4.h b/gcc/config/m68k/m68kv4.h index 16cc1c904de..9f2744db0dc 100644 --- a/gcc/config/m68k/m68kv4.h +++ b/gcc/config/m68k/m68kv4.h @@ -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