--- gcc/config/tm-m68k.h 2018/04/24 16:53:26 1.1 +++ gcc/config/tm-m68k.h 2018/04/24 17:01:53 1.1.1.4 @@ -968,13 +968,15 @@ extern enum reg_class regno_reg_class[]; However, if REG is a broken-out memory address or multiplication, nothing needs to be done because REG can certainly go in an address reg. */ +#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; } #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ { register int ch = (X) != (OLDX); \ if (GET_CODE (X) == PLUS) \ - { if (GET_CODE (XEXP (X, 0)) == MULT) \ - ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \ + { int copied = 0; \ + if (GET_CODE (XEXP (X, 0)) == MULT) \ + { COPY_ONCE (X); XEXP (X, 0) = force_operand (XEXP (X, 0), 0);} \ if (GET_CODE (XEXP (X, 1)) == MULT) \ - ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \ + { COPY_ONCE (X); XEXP (X, 1) = force_operand (XEXP (X, 1), 0);} \ if (ch && GET_CODE (XEXP (X, 1)) == REG \ && GET_CODE (XEXP (X, 0)) == REG) \ return X; \ @@ -986,6 +988,7 @@ extern enum reg_class regno_reg_class[]; { register rtx temp = gen_reg_rtx (Pmode); \ register rtx val = force_operand (XEXP (X, 1), 0); \ emit_move_insn (temp, val); \ + COPY_ONCE (X); \ XEXP (X, 1) = temp; \ return X; } \ else if (GET_CODE (XEXP (X, 1)) == REG \ @@ -995,6 +998,7 @@ extern enum reg_class regno_reg_class[]; { register rtx temp = gen_reg_rtx (Pmode); \ register rtx val = force_operand (XEXP (X, 0), 0); \ emit_move_insn (temp, val); \ + COPY_ONCE (X); \ XEXP (X, 0) = temp; \ return X; }}} @@ -1097,6 +1101,9 @@ extern enum reg_class regno_reg_class[]; can make it possibly invalid to use the saved cc's. In those cases we clear out some or all of the saved cc's so they won't be used. */ +/* It was claimed recently that addq, subq to an address register + do update the cc's, but the 68000 and 68020 manuals say otherwise. */ + #define NOTICE_UPDATE_CC(EXP, INSN) \ { \ /* If the cc is being set from the fpa and the @@ -1110,7 +1117,9 @@ extern enum reg_class regno_reg_class[]; && XEXP (XVECEXP (EXP, 0, 0), 0) == cc0_rtx)) \ { CC_STATUS_INIT; } \ else if (GET_CODE (EXP) == SET) \ - { if (ADDRESS_REG_P (SET_DEST (EXP))) \ + { if (GET_CODE (SET_SRC (EXP)) == CALL) \ + { CC_STATUS_INIT; } \ + else if (ADDRESS_REG_P (SET_DEST (EXP))) \ { if (cc_status.value1 \ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1)) \ cc_status.value1 = 0; \ @@ -1132,8 +1141,6 @@ extern enum reg_class regno_reg_class[]; || GET_CODE (SET_SRC (EXP)) == MEM \ || GET_CODE (SET_SRC (EXP)) == CONST_DOUBLE))\ { CC_STATUS_INIT; } \ - else if (GET_CODE (SET_SRC (EXP)) == CALL) \ - { CC_STATUS_INIT; } \ else if (XEXP (EXP, 0) != pc_rtx) \ { cc_status.flags = 0; \ cc_status.value1 = XEXP (EXP, 0); \ @@ -1163,6 +1170,7 @@ extern enum reg_class regno_reg_class[]; cc_status.flags |= CC_NO_OVERFLOW; \ break; \ case ZERO_EXTEND: \ + case ZERO_EXTRACT: \ /* (SET r1 (ZERO_EXTEND r2)) on this machine ends with a move insn moving r2 in r2's mode. Thus, the cc's are set for r2. @@ -1179,11 +1187,11 @@ extern enum reg_class regno_reg_class[]; cc_status.flags = CC_IN_68881; } #define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ -{ if (cc_prev_status.flags & CC_IN_68881) \ - return FLOAT; \ - if (cc_prev_status.flags & CC_NO_OVERFLOW) \ - return NO_OV; \ - return NORMAL; } +do { if (cc_prev_status.flags & CC_IN_68881) \ + return FLOAT; \ + if (cc_prev_status.flags & CC_NO_OVERFLOW) \ + return NO_OV; \ + return NORMAL; } while (0) /* Control the assembler format that we output. */ @@ -1267,12 +1275,24 @@ extern enum reg_class regno_reg_class[]; /* This is how to output an assembler line defining a `float' constant. */ +/* Sun's assembler can't handle floating constants written as floating. + However, when cross-compiling, always use that in case format differs. */ + +#ifdef CROSS_COMPILER + +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + fprintf (FILE, "\t.float 0r%.10g\n", (VALUE)) + +#else + #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ do { union { float f; long l;} tem; \ tem.f = (VALUE); \ fprintf (FILE, "\t.long 0x%x\n", tem.l); \ } while (0) +#endif /* not CROSS_COMPILER */ + /* This is how to output an assembler line defining an `int' constant. */ #define ASM_OUTPUT_INT(FILE,VALUE) \ @@ -1332,7 +1352,7 @@ do { union { float f; long l;} tem; \ abort (); #define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.skip %d\n", (SIZE)) + fprintf (FILE, "\t.skip %u\n", (SIZE)) /* This says how to output an assembler line to define a global common symbol. */ @@ -1340,7 +1360,7 @@ do { union { float f; long l;} tem; \ #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ( fputs (".comm ", (FILE)), \ assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (ROUNDED))) + fprintf ((FILE), ",%u\n", (ROUNDED))) /* This says how to output an assembler line to define a local common symbol. */ @@ -1348,7 +1368,7 @@ do { union { float f; long l;} tem; \ #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ( fputs (".lcomm ", (FILE)), \ assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (ROUNDED))) + fprintf ((FILE), ",%u\n", (ROUNDED))) /* Store in OUTPUT a string (made with alloca) containing an assembler-name for a local static variable named NAME. @@ -1414,6 +1434,22 @@ do { union { float f; long l;} tem; \ ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \ || (CODE) == '+' || (CODE) == '@' || (CODE) == '!') +/* This assumes the compiler is running on a big-endian machine. + The support for the other case is left for version 2. */ +#define PRINT_OPERAND_EXTRACT_FLOAT(X) \ + u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); + +#ifdef CROSS_COMPILER +#define PRINT_OPERAND_PRINT_FLOAT(CODE, FILE) \ + ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f); +#else +#define PRINT_OPERAND_PRINT_FLOAT(CODE, FILE) \ +{ if (CODE == 'f') \ + ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f); \ + else \ + fprintf (FILE, "#0x%x", u1.i); } +#endif + #define PRINT_OPERAND(FILE, X, CODE) \ { int i; \ if (CODE == '.') ; \ @@ -1432,7 +1468,10 @@ do { union { float f; long l;} tem; \ { \ output_address (XEXP (X, 0)); \ if (CODE == 'd' && ! TARGET_68020 \ - && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ + && CONSTANT_ADDRESS_P (XEXP (X, 0)) \ + && !(GET_CODE (XEXP (X, 0)) == CONST_INT \ + && INTVAL (XEXP (X, 0)) < 0x8000 \ + && INTVAL (XEXP (X, 0)) >= -0x8000)) \ fprintf (FILE, ":l"); \ } \ else if ((CODE == 'y' || CODE == 'w') \ @@ -1442,15 +1481,12 @@ do { union { float f; long l;} tem; \ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ { union { double d; int i[2]; } u; \ union { float f; int i; } u1; \ - u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ + PRINT_OPERAND_EXTRACT_FLOAT (X); \ u1.f = u.d; \ - if (CODE == 'f') \ - ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f); \ - else \ - fprintf (FILE, "#0x%x", u1.i); } \ + PRINT_OPERAND_PRINT_FLOAT (CODE, FILE); } \ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ - u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ + PRINT_OPERAND_EXTRACT_FLOAT (X); \ ASM_OUTPUT_DOUBLE_OPERAND (FILE, u.d); } \ else { putc ('#', FILE); output_addr_const (FILE, X); }}