output_address (XEXP (x, 0));
break;
- case CONST:
- if (TARGET_SHMEDIA
- && (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
- || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
- && (GET_MODE (XEXP (x, 0)) == DImode
- || GET_MODE (XEXP (x, 0)) == SImode)
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == TRUNCATE
- && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)
- {
- rtx val = XEXP (XEXP (XEXP (x, 0), 0), 0);
- rtx val2 = val;
- bool nested_expr = false;
-
- fputc ('(', stream);
- if (GET_CODE (val) == ASHIFTRT)
- {
- fputc ('(', stream);
- val2 = XEXP (val, 0);
- }
- if (GET_CODE (val2) == CONST
- || GET_RTX_CLASS (GET_CODE (val2)) != RTX_OBJ)
- {
- fputc ('(', stream);
- nested_expr = true;
- }
- output_addr_const (stream, val2);
- if (nested_expr)
- fputc (')', stream);
- if (GET_CODE (val) == ASHIFTRT)
- {
- fputs (" >> ", stream);
- output_addr_const (stream, XEXP (val, 1));
- fputc (')', stream);
- }
- fputs (" & 65535)", stream);
- break;
- }
-
- /* Fall through. */
default:
if (TARGET_SH1)
fputc ('#', stream);
static bool
unspec_caller_rtx_p (rtx pat)
{
- switch (GET_CODE (pat))
+ rtx base, offset;
+ int i;
+
+ split_const (pat, &base, &offset);
+ if (GET_CODE (base) == UNSPEC)
{
- case CONST:
- return unspec_caller_rtx_p (XEXP (pat, 0));
- case PLUS:
- case MINUS:
- if (unspec_caller_rtx_p (XEXP (pat, 0)))
- return true;
- return unspec_caller_rtx_p (XEXP (pat, 1));
- case UNSPEC:
- if (XINT (pat, 1) == UNSPEC_CALLER)
+ if (XINT (base, 1) == UNSPEC_CALLER)
return true;
- default:
- break;
+ for (i = 0; i < XVECLEN (base, 0); i++)
+ if (unspec_caller_rtx_p (XVECEXP (base, 0, i)))
+ return true;
}
-
return false;
}
{
rtx worker = mova;
rtx lab = gen_label_rtx ();
- rtx wpat, wpat0, wpat1, wsrc, diff;
+ rtx wpat, wpat0, wpat1, wsrc, target, base, diff;
do
{
XEXP (XVECEXP (wsrc, 0, 2), 0), lab,
XEXP (wpat1, 0)));
INSN_CODE (worker) = -1;
- diff = gen_rtx_MINUS (Pmode, XVECEXP (SET_SRC (PATTERN (mova)), 0, 0),
- gen_rtx_LABEL_REF (Pmode, lab));
- diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, diff), UNSPEC_PIC);
+ target = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+ base = gen_rtx_LABEL_REF (Pmode, lab);
+ diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, target, base), UNSPEC_SYMOFF);
SET_SRC (PATTERN (mova)) = gen_rtx_CONST (Pmode, diff);
INSN_CODE (mova) = -1;
}
|| XINT (x, 1) == UNSPEC_GOTPLT
|| XINT (x, 1) == UNSPEC_GOTTPOFF
|| XINT (x, 1) == UNSPEC_DTPOFF
- || XINT (x, 1) == UNSPEC_PLT))
+ || XINT (x, 1) == UNSPEC_PLT
+ || XINT (x, 1) == UNSPEC_SYMOFF
+ || XINT (x, 1) == UNSPEC_PCREL_SYMOFF))
return 0;
fmt = GET_RTX_FORMAT (GET_CODE (x));
emit_insn (gen_binary_sf_op1 (op0, op1, op2, op));
}
+/* Return true if hard register REGNO can hold a value of machine-mode MODE.
+ We can allow any mode in any general register. The special registers
+ only allow SImode. Don't allow any mode in the PR.
+
+ We cannot hold DCmode values in the XD registers because alter_reg
+ handles subregs of them incorrectly. We could work around this by
+ spacing the XD registers like the DR registers, but this would require
+ additional memory in every compilation to hold larger register vectors.
+ We could hold SFmode / SCmode values in XD registers, but that
+ would require a tertiary reload when reloading from / to memory,
+ and a secondary reload to reload from / to general regs; that
+ seems to be a loosing proposition.
+
+ We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
+ it won't be ferried through GP registers first. */
+
+bool
+sh_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
+{
+ if (SPECIAL_REGISTER_P (regno))
+ return mode == SImode;
+
+ if (regno == FPUL_REG)
+ return (mode == SImode || mode == SFmode);
+
+ if (FP_REGISTER_P (regno) && mode == SFmode)
+ return true;
+
+ if (mode == V2SFmode)
+ {
+ if (((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 2 == 0)
+ || GENERAL_REGISTER_P (regno)))
+ return true;
+ else
+ return false;
+ }
+
+ if (mode == V4SFmode)
+ {
+ if ((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 4 == 0)
+ || GENERAL_REGISTER_P (regno))
+ return true;
+ else
+ return false;
+ }
+
+ if (mode == V16SFmode)
+ {
+ if (TARGET_SHMEDIA)
+ {
+ if (FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 16 == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return regno == FIRST_XD_REG;
+ }
+
+ if (FP_REGISTER_P (regno))
+ {
+ if (mode == SFmode
+ || mode == SImode
+ || ((TARGET_SH2E || TARGET_SHMEDIA) && mode == SCmode)
+ || ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode)
+ || mode == DCmode
+ || (TARGET_SHMEDIA
+ && (mode == DFmode || mode == DImode
+ || mode == V2SFmode || mode == TImode)))
+ && ((regno - FIRST_FP_REG) & 1) == 0)
+ || ((TARGET_SH4 || TARGET_SHMEDIA) && mode == TImode
+ && ((regno - FIRST_FP_REG) & 3) == 0))
+ return true;
+ else
+ return false;
+ }
+
+ if (XD_REGISTER_P (regno))
+ return mode == DFmode;
+
+ if (TARGET_REGISTER_P (regno))
+ return (mode == DImode || mode == SImode || mode == PDImode);
+
+ if (regno == PR_REG)
+ return mode == SImode;
+
+ if (regno == FPSCR_REG)
+ return mode == PSImode;
+
+ /* FIXME. This works around PR target/37633 for -O0. */
+ if (!optimize && TARGET_SHMEDIA32 && GET_MODE_SIZE (mode) > 4)
+ {
+ unsigned int n = GET_MODE_SIZE (mode) / 8;
+
+ if (regno >= FIRST_GENERAL_REG + 10 - n + 1
+ && regno <= FIRST_GENERAL_REG + 14)
+ return false;
+ }
+
+ return true;
+}
+
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
bool
return NO_REGS;
}
if (TARGET_SHMEDIA && rclass == GENERAL_REGS
- && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+ && (GET_CODE (x) == LABEL_REF || PIC_ADDR_P (x)))
return TARGET_REGS;
} /* end of input-only processing. */