--- gcc/config/m68k/m68k.c 2018/04/24 18:10:24 1.1.1.1 +++ gcc/config/m68k/m68k.c 2018/04/24 18:21:09 1.1.1.3 @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Motorola 68000 family. - Copyright (C) 1987, 1993 Free Software Foundation, Inc. + Copyright (C) 1987, 1993, 1994 Free Software Foundation, Inc. This file is part of GNU CC. @@ -58,6 +58,7 @@ rtx legitimize_pic_address (); all PIC references were deleted from the current function. That would save an address register */ +void finalize_pic () { if (flag_pic && current_function_uses_pic_offset_table) @@ -92,8 +93,20 @@ output_function_prologue (stream, size) if (frame_pointer_needed) { - /* Adding negative number is faster on the 68040. */ - if (fsize < 0x8000 && !TARGET_68040) + if (fsize == 0 && TARGET_68040) + { + /* on the 68040, pea + move is faster than link.w 0 */ +#ifdef MOTOROLA + asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n", + reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM], + reg_names[FRAME_POINTER_REGNUM]); +#else + asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n", + reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM], + reg_names[FRAME_POINTER_REGNUM]); +#endif + } + else if (fsize < 0x8000) { #ifdef MOTOROLA asm_fprintf (stream, "\tlink.w %s,%0I%d\n", @@ -115,6 +128,7 @@ output_function_prologue (stream, size) } else { + /* Adding negative number is faster on the 68040. */ #ifdef MOTOROLA asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n", reg_names[FRAME_POINTER_REGNUM], -fsize); @@ -129,6 +143,7 @@ output_function_prologue (stream, size) /* Adding negative number is faster on the 68040. */ if (fsize + 4 < 0x8000) { + /* asm_fprintf() cannot handle %. */ #ifdef MOTOROLA asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4)); #else @@ -137,6 +152,7 @@ output_function_prologue (stream, size) } else { + /* asm_fprintf() cannot handle %. */ #ifdef MOTOROLA asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4)); #else @@ -314,9 +330,9 @@ output_function_epilogue (stream, size) && (mask || fmask || fpoffset)) { #ifdef MOTOROLA - asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra0\n", -fsize); + asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize); #else - asm_fprintf (stream, "\tmovel %0I%d,%Ra0\n", -fsize); + asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize); #endif fsize = 0, big = 1; } @@ -336,12 +352,12 @@ output_function_epilogue (stream, size) if (big) { #ifdef MOTOROLA - asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra0.l),%s\n", + asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n", offset + fsize, reg_names[FRAME_POINTER_REGNUM], reg_names[i]); #else - asm_fprintf (stream, "\tmovel %s@(-%d,%Ra0:l),%s\n", + asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n", reg_names[FRAME_POINTER_REGNUM], offset + fsize, reg_names[i]); #endif @@ -377,12 +393,12 @@ output_function_epilogue (stream, size) if (big) { #ifdef MOTOROLA - asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra0.l),%0I0x%x\n", + asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n", offset + fsize, reg_names[FRAME_POINTER_REGNUM], mask); #else - asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra0:l),%0I0x%x\n", + asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n", reg_names[FRAME_POINTER_REGNUM], offset + fsize, mask); #endif @@ -414,12 +430,12 @@ output_function_epilogue (stream, size) if (big) { #ifdef MOTOROLA - asm_fprintf (stream, "\tfmovm -%d(%s,%Ra0.l),%0I0x%x\n", + asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n", foffset + fsize, reg_names[FRAME_POINTER_REGNUM], fmask); #else - asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra0:l),%0I0x%x\n", + asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n", reg_names[FRAME_POINTER_REGNUM], foffset + fsize, fmask); #endif @@ -453,12 +469,12 @@ output_function_epilogue (stream, size) if (big) { #ifdef MOTOROLA - asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra0.l), %s\n", + asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n", fpoffset + fsize, reg_names[FRAME_POINTER_REGNUM], reg_names[regno]); #else - asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra0:l), %s\n", + asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n", reg_names[FRAME_POINTER_REGNUM], fpoffset + fsize, reg_names[regno]); #endif @@ -495,6 +511,7 @@ output_function_epilogue (stream, size) { if (fsize + 4 < 0x8000) { + /* asm_fprintf() cannot handle %. */ #ifdef MOTOROLA asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4); #else @@ -503,6 +520,7 @@ output_function_epilogue (stream, size) } else { + /* asm_fprintf() cannot handle %. */ #ifdef MOTOROLA asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4); #else @@ -884,7 +902,9 @@ output_move_double (operands) } optype0, optype1; rtx latehalf[2]; rtx middlehalf[2]; + rtx xops[2]; rtx addreg0 = 0, addreg1 = 0; + int dest_overlapped_low = 0; int size = GET_MODE_SIZE (GET_MODE (operands[0])); middlehalf[0] = 0; @@ -1064,7 +1084,69 @@ output_move_double (operands) if (optype0 == PUSHOP && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) - operands[1] = latehalf[1]; + operands[1] = middlehalf[1] = latehalf[1]; + + /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)), + if the upper part of reg N does not appear in the MEM, arrange to + emit the move late-half first. Otherwise, compute the MEM address + into the upper part of N and use that as a pointer to the memory + operand. */ + if (optype0 == REGOP + && (optype1 == OFFSOP || optype1 == MEMOP)) + { + rtx testlow = gen_rtx (REG, SImode, REGNO (operands[0])); + + if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)) + && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0))) + { + /* If both halves of dest are used in the src memory address, + compute the address into latehalf of dest. + Note that this can't happen if the dest is two data regs. */ +compadr: + xops[0] = latehalf[0]; + xops[1] = XEXP (operands[1], 0); + output_asm_insn ("lea %a1,%0", xops); + if( GET_MODE (operands[1]) == XFmode ) + { + operands[1] = gen_rtx (MEM, XFmode, latehalf[0]); + middlehalf[1] = adj_offsettable_operand (operands[1], size-8); + latehalf[1] = adj_offsettable_operand (operands[1], size-4); + } + else + { + operands[1] = gen_rtx (MEM, DImode, latehalf[0]); + latehalf[1] = adj_offsettable_operand (operands[1], size-4); + } + } + else if (size == 12 + && reg_overlap_mentioned_p (middlehalf[0], + XEXP (operands[1], 0))) + { + /* Check for two regs used by both source and dest. + Note that this can't happen if the dest is all data regs. + It can happen if the dest is d6, d7, a0. + But in that case, latehalf is an addr reg, so + the code at compadr does ok. */ + + if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)) + || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0))) + goto compadr; + + /* JRV says this can't happen: */ + if (addreg0 || addreg1) + abort (); + + /* Only the middle reg conflicts; simply put it last. */ + output_asm_insn (singlemove_string (operands), operands); + output_asm_insn (singlemove_string (latehalf), latehalf); + output_asm_insn (singlemove_string (middlehalf), middlehalf); + return ""; + } + else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))) + /* If the low half of dest is mentioned in the source memory + address, the arrange to emit the move late half first. */ + dest_overlapped_low = 1; + } /* If one or both operands autodecrementing, do the two words, high-numbered first. */ @@ -1077,22 +1159,23 @@ output_move_double (operands) if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1])) - || REGNO (operands[0]) == REGNO (latehalf[1])))) + || REGNO (operands[0]) == REGNO (latehalf[1]))) + || dest_overlapped_low) { /* Make any unoffsettable addresses point at high-numbered word. */ if (addreg0) { if (size == 12) - output_asm_insn ("addql %#8,%0", &addreg0); + output_asm_insn ("addq%.l %#8,%0", &addreg0); else - output_asm_insn ("addql %#4,%0", &addreg0); + output_asm_insn ("addq%.l %#4,%0", &addreg0); } if (addreg1) { if (size == 12) - output_asm_insn ("addql %#8,%0", &addreg1); + output_asm_insn ("addq%.l %#8,%0", &addreg1); else - output_asm_insn ("addql %#4,%0", &addreg1); + output_asm_insn ("addq%.l %#4,%0", &addreg1); } /* Do that word. */ @@ -1100,17 +1183,17 @@ output_move_double (operands) /* Undo the adds we just did. */ if (addreg0) - output_asm_insn ("subql %#4,%0", &addreg0); + output_asm_insn ("subq%.l %#4,%0", &addreg0); if (addreg1) - output_asm_insn ("subql %#4,%0", &addreg1); + output_asm_insn ("subq%.l %#4,%0", &addreg1); if (size == 12) { output_asm_insn (singlemove_string (middlehalf), middlehalf); if (addreg0) - output_asm_insn ("subql %#4,%0", &addreg0); + output_asm_insn ("subq%.l %#4,%0", &addreg0); if (addreg1) - output_asm_insn ("subql %#4,%0", &addreg1); + output_asm_insn ("subq%.l %#4,%0", &addreg1); } /* Do low-numbered word. */ @@ -1125,18 +1208,18 @@ output_move_double (operands) if (size == 12) { if (addreg0) - output_asm_insn ("addql %#4,%0", &addreg0); + output_asm_insn ("addq%.l %#4,%0", &addreg0); if (addreg1) - output_asm_insn ("addql %#4,%0", &addreg1); + output_asm_insn ("addq%.l %#4,%0", &addreg1); output_asm_insn (singlemove_string (middlehalf), middlehalf); } /* Make any unoffsettable addresses point at high-numbered word. */ if (addreg0) - output_asm_insn ("addql %#4,%0", &addreg0); + output_asm_insn ("addq%.l %#4,%0", &addreg0); if (addreg1) - output_asm_insn ("addql %#4,%0", &addreg1); + output_asm_insn ("addq%.l %#4,%0", &addreg1); /* Do that word. */ output_asm_insn (singlemove_string (latehalf), latehalf); @@ -1145,16 +1228,16 @@ output_move_double (operands) if (addreg0) { if (size == 12) - output_asm_insn ("subql %#8,%0", &addreg0); + output_asm_insn ("subq%.l %#8,%0", &addreg0); else - output_asm_insn ("subql %#4,%0", &addreg0); + output_asm_insn ("subq%.l %#4,%0", &addreg0); } if (addreg1) { if (size == 12) - output_asm_insn ("subql %#8,%0", &addreg1); + output_asm_insn ("subq%.l %#8,%0", &addreg1); else - output_asm_insn ("subql %#4,%0", &addreg1); + output_asm_insn ("subq%.l %#4,%0", &addreg1); } return ""; @@ -1278,7 +1361,7 @@ notice_update_cc (exp, insn) { case PLUS: case MINUS: case MULT: case DIV: case UDIV: case MOD: case UMOD: case NEG: - case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT: + case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATE: case ROTATERT: if (GET_MODE (cc_status.value2) != VOIDmode) cc_status.flags |= CC_NO_OVERFLOW; @@ -1429,6 +1512,10 @@ standard_68881_constant_p (x) int i; enum machine_mode mode; +#ifdef NO_ASM_FMOVECR + return 0; +#endif + /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */ if (TARGET_68040) return 0; @@ -1776,6 +1863,7 @@ print_operand (file, op, letter) } else if (GET_CODE (op) == REG) { +#ifdef SUPPORT_SUN_FPA if (REGNO (op) < 16 && (letter == 'y' || letter == 'x') && GET_MODE (op) == DFmode) @@ -1784,6 +1872,7 @@ print_operand (file, op, letter) reg_names[REGNO (op)+1]); } else +#endif { fprintf (file, "%s", reg_names[REGNO (op)]); } @@ -1851,6 +1940,9 @@ print_operand (file, op, letter) define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END macro. See m68k/sgs.h for an example; for versions without the bug. + Some assemblers refuse all the above solutions. The workaround is to + emit "K(pc,d0.l*2)" with K being a small constant known to give the + right behaviour. They also do not like things like "pea 1.w", so we simple leave off the .w on small constants. @@ -1860,6 +1952,21 @@ print_operand (file, op, letter) offset is output in word mode (eg movel a5@(_foo:w), a0). When generating -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */ +#ifndef ASM_OUTPUT_CASE_FETCH +#ifdef MOTOROLA +#ifdef SGS +#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\ + asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname) +#else +#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\ + asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname) +#endif +#else +#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\ + asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname) +#endif +#endif /* ASM_OUTPUT_CASE_FETCH */ + void print_operand_address (file, addr) FILE *file; @@ -1996,43 +2103,17 @@ print_operand_address (file, addr) } if (GET_CODE (ireg) == SIGN_EXTEND) { -#ifdef MOTOROLA -#ifdef SGS - asm_fprintf (file, "%LLD%d(%Rpc,%s.w", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (XEXP (ireg, 0))]); -#else - asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w", - CODE_LABEL_NUMBER (XEXP (addr, 0)), + ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (XEXP (ireg, 0))]); -#endif -#else - asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (XEXP (ireg, 0))]); -#endif + fprintf (file, "w"); } else { -#ifdef MOTOROLA -#ifdef SGS - asm_fprintf (file, "%LLD%d(%Rpc,%s.l", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (ireg)]); -#else - asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (ireg)]); -#endif -#else - asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l", - CODE_LABEL_NUMBER (XEXP (addr, 0)), + ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (ireg)]); -#endif + fprintf (file, "l"); } if (scale != 1) { @@ -2048,24 +2129,10 @@ print_operand_address (file, addr) if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF && ! (flag_pic && breg == pic_offset_table_rtx)) { -#ifdef MOTOROLA -#ifdef SGS - asm_fprintf (file, "%LLD%d(%Rpc,%s.l", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (breg)]); -#else - asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", - CODE_LABEL_NUMBER (XEXP (addr, 0)), + ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (breg)]); -#endif -#else - asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (breg)]); -#endif - putc (')', file); + fprintf (file, "l)"); break; } if (ireg != 0 || breg != 0) @@ -2141,23 +2208,10 @@ print_operand_address (file, addr) else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF && ! (flag_pic && reg1 == pic_offset_table_rtx)) { -#ifdef MOTOROLA -#ifdef SGS - asm_fprintf (file, "%LLD%d(%Rpc,%s.l)", + ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (reg1)]); -#else - asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (reg1)]); -#endif -#else - asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)", - CODE_LABEL_NUMBER (XEXP (addr, 0)), - CODE_LABEL_NUMBER (XEXP (addr, 0)), - reg_names[REGNO (reg1)]); -#endif + fprintf (file, "l)"); break; } /* FALL-THROUGH (is this really what we want? */