--- gcc/config/m88k/m88k.c 2018/04/24 18:10:23 1.1 +++ gcc/config/m88k/m88k.c 2018/04/24 18:27:44 1.1.1.4 @@ -1,8 +1,7 @@ /* Subroutines for insn-output.c for Motorola 88000. - Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 93, 94, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@mcc.com) - Enhanced by Michael Meissner (meissner@osf.org) - Version 2 port by Tom Wood (Tom_Wood@NeXT.com) + Currently maintained by (gcc@dg-rtp.dg.com) This file is part of GNU CC. @@ -18,7 +17,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include #include @@ -47,27 +47,26 @@ extern char *ctime (); extern int flag_traditional; extern FILE *asm_out_file; -static char out_sccs_id[] = "@(#)m88k.c 2.3.3.2 12/16/92 08:26:06"; -static char tm_sccs_id [] = TM_SCCS_ID; +static char out_rcs_id[] = "$What: <@(#) m88k.c,v 1.8> $"; +static char tm_rcs_id [] = TM_RCS_ID; char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */ char *m88k_short_data; char *m88k_version; char m88k_volatile_code; -int m88k_gp_threshold; +unsigned m88k_gp_threshold = 0; int m88k_prologue_done = 0; /* Ln directives can now be emitted */ int m88k_function_number = 0; /* Counter unique to each function */ int m88k_fp_offset = 0; /* offset of frame pointer if used */ int m88k_stack_size = 0; /* size of allocated stack (including frame) */ int m88k_case_index; -int m88k_version_0300; /* Version is at least 03.00 */ rtx m88k_compare_reg; /* cmp output pseudo register */ rtx m88k_compare_op0; /* cmpsi operand 0 */ rtx m88k_compare_op1; /* cmpsi operand 1 */ -enum attr_cpu m88k_cpu; /* target cpu */ +enum processor_type m88k_cpu; /* target cpu */ /* Determine what instructions are needed to manufacture the integer VALUE in the given MODE. */ @@ -225,6 +224,10 @@ emit_move_sequence (operands, mode, scra register rtx operand0 = operands[0]; register rtx operand1 = operands[1]; + if (CONSTANT_P (operand1) && flag_pic + && pic_address_needs_scratch (operand1)) + operands[1] = operand1 = legitimize_address (1, operand1, 0, 0); + /* Handle most common case first: storing into a register. */ if (register_operand (operand0, mode)) { @@ -314,10 +317,16 @@ legitimize_address (pic, orig, reg, scra temp = ((reload_in_progress || reload_completed) ? reg : gen_reg_rtx (Pmode)); - emit_insn (gen_rtx (SET, VOIDmode, - temp, gen_rtx (HIGH, SImode, addr))); - emit_insn (gen_rtx (SET, VOIDmode, - temp, gen_rtx (LO_SUM, SImode, temp, addr))); + emit_insn (gen_rtx (SET, VOIDmode, temp, + gen_rtx (HIGH, SImode, + gen_rtx (UNSPEC, SImode, + gen_rtvec (1, addr), + 0)))); + emit_insn (gen_rtx (SET, VOIDmode, temp, + gen_rtx (LO_SUM, SImode, temp, + gen_rtx (UNSPEC, SImode, + gen_rtvec (1, addr), + 0)))); addr = temp; } new = gen_rtx (MEM, Pmode, @@ -356,7 +365,7 @@ legitimize_address (pic, orig, reg, scra if (GET_CODE (addr) == CONST_INT) { - if (SMALL_INT (addr)) + if (ADD_INT (addr)) return plus_constant_for_output (base, INTVAL (addr)); else if (! reload_in_progress && ! reload_completed) addr = force_reg (Pmode, addr); @@ -491,9 +500,9 @@ expand_block_move (dest_mem, src_mem, op int bytes = (constp ? INTVAL (operands[2]) : 0); int target = (int) m88k_cpu; - assert (CPU_M88100 == 0); - assert (CPU_M88110 == 1); - assert (CPU_M88000 == 2); + assert (PROCESSOR_M88100 == 0); + assert (PROCESSOR_M88110 == 1); + assert (PROCESSOR_M88000 == 2); if (constp && bytes <= 0) return; @@ -590,7 +599,7 @@ block_move_loop (dest, dest_mem, src, sr offset_rtx)); RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem); MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem); - MEM_IN_STRUCT_P (value_rtx) = 1; + MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); emit_insn (gen_call_movstrsi_loop (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), @@ -647,7 +656,7 @@ block_move_no_loop (dest, dest_mem, src, offset_rtx)); RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem); MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem); - MEM_IN_STRUCT_P (value_rtx) = 1; + MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); value_reg = ((((most - (size - remainder)) / align) & 1) == 0 ? (align == 8 ? 6 : 5) : 4); @@ -720,7 +729,7 @@ block_move_sequence (dest, dest_mem, src gen_rtx (CONST_INT, SImode, offset_ld))); RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem); MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem); - MEM_IN_STRUCT_P (srcp) = 1; + MEM_IN_STRUCT_P (srcp) = MEM_IN_STRUCT_P (src_mem); emit_insn (gen_rtx (SET, VOIDmode, temp[next], srcp)); offset_ld += amount[next]; active[next] = TRUE; @@ -735,7 +744,7 @@ block_move_sequence (dest, dest_mem, src gen_rtx (CONST_INT, SImode, offset_st))); RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem); MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem); - MEM_IN_STRUCT_P (dstp) = 1; + MEM_IN_STRUCT_P (dstp) = MEM_IN_STRUCT_P (dest_mem); emit_insn (gen_rtx (SET, VOIDmode, dstp, temp[phase])); offset_st += amount[phase]; } @@ -868,14 +877,20 @@ output_call (operands, addr) If we loose, we must use the non-delay form. This is unlikely to ever happen. If it becomes a problem, claim that a call has two delay slots and only the second can be filled with - a jump. */ + a jump. + + The 88110 can lose when a jsr.n r1 is issued and a page fault + occurs accessing the delay slot. So don't use jsr.n form when + jumping thru r1. + */ #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */ if (optimize < 2 - || ! ADD_INTVAL (delta * 2)) + || ! ADD_INTVAL (delta * 2) #else if (optimize < 2 - || ! ADD_INTVAL (delta)) + || ! ADD_INTVAL (delta) #endif + || (REG_P (addr) && REGNO (addr) == 1)) { operands[1] = dest; return (REG_P (addr) @@ -1260,7 +1275,7 @@ arith64_operand (op, mode) { return (register_operand (op, mode) || GET_CODE (op) == CONST_INT - || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DImode)); + || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)); } int @@ -1335,6 +1350,17 @@ real_or_0_operand (op, mode) && op == CONST0_RTX (mode))); } +/* Return true if OP is valid to use in the context of logic arithmetic + on condition codes. */ + +int +partial_ccmode_register_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return register_operand (op, CCmode) || register_operand (op, CCEVENmode); +} + /* Return true if OP is a relational operator. */ int @@ -1360,6 +1386,42 @@ relop (op, mode) } } +int +even_relop (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case EQ: + case LT: + case GT: + case LTU: + case GTU: + return 1; + default: + return 0; + } +} + +int +odd_relop (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case NE: + case LE: + case GE: + case LEU: + case GEU: + return 1; + default: + return 0; + } +} + /* Return true if OP is a relational operator, and is not an unsigned relational operator. */ @@ -1500,7 +1562,7 @@ output_file_start (file, f_options, f_le ASM_FIRST_LINE (file); if (TARGET_88110 - && m88k_version != 0 && strcmp (m88k_version, "04.00") >= 0) + && TARGET_SVR4) fprintf (file, "\t%s\n", REQUIRES_88110_ASM_OP); output_file_directive (file, main_input_filename); /* Switch to the data section so that the coffsem symbol and the @@ -1968,7 +2030,7 @@ m88k_end_epilogue (stream, size) PUT_OCS_FUNCTION_END (stream); /* If the last insn isn't a BARRIER, we must write a return insn. This - should only happen if the function has no prologe and no body. */ + should only happen if the function has no prologue and no body. */ if (GET_CODE (insn) == NOTE) insn = prev_nonnote_insn (insn); if (insn == 0 || GET_CODE (insn) != BARRIER) @@ -2555,7 +2617,7 @@ m88k_builtin_saveregs (arglist) change_address (addr, Pmode, plus_constant (XEXP (addr, 0), fixed * UNITS_PER_WORD)), - 8 - fixed); + 8 - fixed, UNITS_PER_WORD * (8 - fixed)); /* Return the address of the va_list constructor, but don't put it in a register. This fails when not optimizing and produces worse code when @@ -2587,17 +2649,15 @@ emit_bcnd (op, label) rtx label; { if (m88k_compare_op1 == const0_rtx) - emit_jump_insn (optimize - ? gen_bxx (emit_test (op, VOIDmode), label) - : gen_bcnd (gen_rtx (op, VOIDmode, - m88k_compare_op0, const0_rtx), - label)); + emit_jump_insn( gen_bcnd ( + gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx), + label)); else if (m88k_compare_op0 == const0_rtx) - emit_jump_insn (optimize - ? gen_bxx (emit_test (op, VOIDmode), label) - : gen_bcnd (gen_rtx (swap_condition (op), VOIDmode, - m88k_compare_op1, const0_rtx), - label)); + emit_jump_insn( gen_bcnd( + gen_rtx( + swap_condition (op), + VOIDmode, m88k_compare_op1, const0_rtx), + label)); else if (op != EQ && op != NE) emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label)); else @@ -2687,6 +2747,13 @@ print_operand (file, x, code) The mechanism below is completed by having CC_STATUS_INIT set the code to the unknown value. */ + /* + hassey 6/30/93 + A problem with 88110 4.1 & 4.2 makes the use of fldcr for + this purpose undesirable. Instead we will use tb1, this will + cause serialization on the 88100 but such is life. + */ + static rtx last_addr = 0; if (code == 'V' /* Only need to serialize before a load. */ && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */ @@ -2694,12 +2761,16 @@ print_operand (file, x, code) && GET_CODE (XEXP (x, 0)) == LO_SUM && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr))) fprintf (file, +#if 0 #ifdef AS_BUG_FLDCR "fldcr\t %s,%scr63\n\t", #else "fldcr\t %s,%sfcr63\n\t", #endif reg_names[0], m88k_pound_sign); +#else /* 0 */ + "tb1\t 1,%s,0xff\n\t", reg_names[0]); +#endif /* 0 */ m88k_volatile_code = code; last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM ? XEXP (XEXP (x, 0), 1) : 0); @@ -2786,6 +2857,10 @@ print_operand (file, x, code) ? ".n\t" : "\t", file); return; + case '!': /* Reverse the following condition. */ + sequencep++; + reversep = 1; + return; case 'R': /* reverse the condition of the next print_operand if operand is a label_ref. */ sequencep++; @@ -2871,6 +2946,11 @@ print_operand (file, x, code) output_address (x); else if (xc == MEM) output_address (XEXP (x, 0)); + else if (flag_pic && xc == UNSPEC) + { + output_addr_const (file, XVECEXP (x, 0, 0)); + fputs ("#got_rel", file); + } else if (xc == CONST_DOUBLE) output_operand_lossage ("operand is const_double"); else @@ -2981,12 +3061,6 @@ print_operand_address (file, addr) reg_names[0], reg_names[REGNO (XEXP (addr, 0))]); break; - case LSHIFT: - fprintf (file, "%s,%shi16(", reg_names[0], m88k_pound_sign); - output_addr_const (file, XEXP (addr, 0)); - fputc (')', file); - break; - case CONST_INT: fprintf (file, "%s,%d", reg_names[0], INTVAL (addr)); break; @@ -3003,3 +3077,49 @@ print_operand_address (file, addr) output_addr_const (file, addr); } } + +/* Return true if X is an address which needs a temporary register when + reloaded while generating PIC code. */ + +int +pic_address_needs_scratch (x) + rtx x; +{ + /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */ + if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT + && ! ADD_INT (XEXP (XEXP (x, 0), 1))) + return 1; + + return 0; +} + +/* Returns 1 if OP is either a symbol reference or a sum of a symbol + reference and a constant. */ + +int +symbolic_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + + case CONST: + op = XEXP (op, 0); + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + + /* ??? This clause seems to be irrelevant. */ + case CONST_DOUBLE: + return GET_MODE (op) == mode; + + default: + return 0; + } +}