--- gcc/config/ns32k/ns32k.c 2018/04/24 18:14:56 1.1.1.2 +++ gcc/config/ns32k/ns32k.c 2018/04/24 18:21:18 1.1.1.3 @@ -1,5 +1,5 @@ /* Subroutines for assembler code output on the NS32000. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1994 Free Software Foundation, Inc. This file is part of GNU CC. @@ -260,7 +260,7 @@ output_move_double (operands) if (REG_P (operands[1])) optype1 = REGOP; - else if (CONSTANT_ADDRESS_P (operands[1]) + else if (CONSTANT_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE) optype1 = CNSTOP; else if (offsettable_memref_p (operands[1])) @@ -298,12 +298,7 @@ output_move_double (operands) else if (optype1 == OFFSOP) latehalf[1] = adj_offsettable_operand (operands[1], 4); else if (optype1 == CNSTOP) - { - if (CONSTANT_ADDRESS_P (operands[1])) - latehalf[1] = const0_rtx; - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - split_double (operands[1], &operands[1], &latehalf[1]); - } + split_double (operands[1], &operands[1], &latehalf[1]); else latehalf[1] = operands[1]; @@ -344,12 +339,12 @@ output_move_double (operands) && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) { /* If both halves of dest are used in the src memory address, - add the two regs and put them in the low reg (operands[0]). + load the destination address into the low reg (operands[0]). Then it works to load latehalf first. */ rtx xops[2]; - xops[0] = latehalf[0]; + xops[0] = XEXP (operands[1], 0); xops[1] = operands[0]; - output_asm_insn ("addd %0,%1", xops); + output_asm_insn ("addr %a0,%1", xops); operands[1] = gen_rtx (MEM, DImode, operands[0]); latehalf[1] = adj_offsettable_operand (operands[1], 4); /* The first half has the overlap, Do the late half first. */ @@ -396,6 +391,46 @@ check_reg (oper, reg) } return 0; } + +/* Returns 1 if OP contains a global symbol reference */ + +int +global_symbolic_reference_mentioned_p (op, f) + rtx op; + int f; +{ + register char *fmt; + register int i; + + if (GET_CODE (op) == SYMBOL_REF) + { + if (! SYMBOL_REF_FLAG (op)) + return 1; + else + return 0; + } + else if (f && GET_CODE (op) != CONST) + return 0; + + fmt = GET_RTX_FORMAT (GET_CODE (op)); + for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) + { + if (fmt[i] == 'E') + { + register int j; + + for (j = XVECLEN (op, i) - 1; j >= 0; j--) + if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0)) + return 1; + } + else if (fmt[i] == 'e' + && global_symbolic_reference_mentioned_p (XEXP (op, i), 0)) + return 1; + } + + return 0; +} + /* PRINT_OPERAND is defined to call this function, which is easier to debug than putting all the code in @@ -416,23 +451,9 @@ print_operand (file, x, code) else if (GET_CODE (x) == MEM) { rtx tmp = XEXP (x, 0); -#if ! (defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)) - if (GET_CODE (tmp) != CONST_INT) - { - char *out = XSTR (tmp, 0); - if (out[0] == '*') - { - PUT_ABSOLUTE_PREFIX (file); - fprintf (file, "%s", &out[1]); - } - else - ASM_OUTPUT_LABELREF (file, out); - } - else -#endif - output_address (XEXP (x, 0)); + output_address (XEXP (x, 0)); } - else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode) + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode) { if (GET_MODE (x) == DFmode) { @@ -497,6 +518,7 @@ print_operand_address (file, addr) static char scales[] = { 'b', 'w', 'd', 0, 'q', }; rtx offset, base, indexexp, tmp; int scale; + extern int flag_pic; if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC) { @@ -560,9 +582,65 @@ print_operand_address (file, addr) case MULT: indexexp = tmp; break; + case SYMBOL_REF: + if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp) + && ! SYMBOL_REF_FLAG (tmp)) + { + if (base) + { + if (indexexp) + abort (); + indexexp = base; + } + base = tmp; + break; + } case CONST: + if (flag_pic && GET_CODE (tmp) == CONST) + { + rtx sym, off, tmp1; + tmp1 = XEXP (tmp,0); + if (GET_CODE (tmp1) != PLUS) + abort (); + + sym = XEXP (tmp1,0); + if (GET_CODE (sym) != SYMBOL_REF) + { + off = sym; + sym = XEXP (tmp1,1); + } + else + off = XEXP (tmp1,1); + if (GET_CODE (sym) == SYMBOL_REF) + { + if (GET_CODE (off) != CONST_INT) + abort (); + + if (CONSTANT_POOL_ADDRESS_P (sym) + || SYMBOL_REF_FLAG (sym)) + { + SYMBOL_REF_FLAG (tmp) = 1; + } + else + { + if (base) + { + if (indexexp) + abort (); + + indexexp = base; + } + + if (offset != 0) + abort (); + + base = sym; + offset = off; + break; + } + } + } case CONST_INT: - case SYMBOL_REF: case LABEL_REF: if (offset) offset = gen_rtx (PLUS, SImode, tmp, offset); @@ -576,26 +654,31 @@ print_operand_address (file, addr) if (! offset) offset = const0_rtx; -#ifdef INDEX_RATHER_THAN_BASE + if (base +#ifndef INDEX_RATHER_THAN_BASE + && (flag_pic || TARGET_HIMEM) + && GET_CODE (base) != SYMBOL_REF + && GET_CODE (offset) != CONST_INT +#else /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */ - if (base && !indexexp && GET_CODE (base) == REG +#endif + && !indexexp && GET_CODE (base) == REG && REG_OK_FOR_INDEX_P (base)) { indexexp = base; - base = 0; + base = NULL; } -#endif /* now, offset, base and indexexp are set */ +#ifndef BASE_REG_NEEDED if (! base) { #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC) if (GET_CODE (offset) == CONST_INT) -/* if (! (GET_CODE (offset) == LABEL_REF - || GET_CODE (offset) == SYMBOL_REF)) */ #endif PUT_ABSOLUTE_PREFIX (file); } +#endif output_addr_const (file, offset); if (base) /* base can be (REG ...) or (MEM ...) */ @@ -613,6 +696,14 @@ print_operand_address (file, addr) case REG: fprintf (file, "(%s)", reg_names[REGNO (base)]); break; + case SYMBOL_REF: + if (! flag_pic) + abort (); + + fprintf (file, "("); + output_addr_const (file, base); + fprintf (file, "(sb))"); + break; case MEM: addr = XEXP(base,0); base = NULL; @@ -661,30 +752,26 @@ print_operand_address (file, addr) output_addr_const (file, offset); if (base) fprintf (file, "(%s)", reg_names[REGNO (base)]); -#ifdef BASE_REG_NEEDED else if (TARGET_SB) fprintf (file, "(sb)"); else abort (); -#endif fprintf (file, ")"); break; - default: abort (); } #ifdef PC_RELATIVE - else /* no base */ - if (GET_CODE (offset) == LABEL_REF || GET_CODE (offset) == SYMBOL_REF) - fprintf (file, "(pc)"); -#endif -#ifdef BASE_REG_NEEDED /* this is defined if the assembler always - needs a base register */ - else if (TARGET_SB) - fprintf (file, "(sb)"); - else - abort (); + else if (GET_CODE (offset) != CONST_INT) + fprintf (file, "(pc)"); +#ifdef BASE_REG_NEEDED + else if (TARGET_SB) + fprintf (file, "(sb)"); + else + abort (); #endif +#endif /* PC_RELATIVE */ + /* now print index if we have one */ if (indexexp) { @@ -760,3 +847,26 @@ output_shift_insn (operands) else return "ashd %2,%0"; return "ashd %2,%0"; } + +char * +output_move_dconst (n, s) + int n; + char *s; +{ + static char r[32]; + + if (n > -9 && n < 8) + strcpy (r, "movqd "); + else if (n > 0 && n < 256) + strcpy (r, "movzbd "); + else if (n > 0 && n < 65536) + strcpy (r, "movzwd "); + else if (n < 0 && n > -129) + strcpy (r, "movxbd "); + else if (n < 0 && n > -32769) + strcpy (r, "movxwd "); + else + strcpy (r, "movd "); + strcat (r, s); + return r; +}