|| XINT (c, 1) == UNSPEC_TLS_IE))
|| (GET_CODE (c) == PLUS
&& GET_CODE (XEXP (c, 0)) == UNSPEC
- && (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF)))
+ && (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF
+ || XINT (XEXP (c, 0), 1) == ARC_UNSPEC_GOTOFFPC)))
{
arc_output_pic_addr_const (file, c, 0);
break;
switch (XINT (x, 1))
{
case ARC_UNSPEC_GOT:
+ case ARC_UNSPEC_GOTOFFPC:
case UNSPEC_TLS_GD:
case UNSPEC_TLS_IE:
return true;
|| XVECLEN (addr, 0) != 1)
return false;
- /* Must be one of @GOT, @GOTOFF, @tlsgd, tlsie. */
+ /* Must be one of @GOT, @GOTOFF, @GOTOFFPC, @tlsgd, tlsie. */
if (XINT (addr, 1) != ARC_UNSPEC_GOT
&& XINT (addr, 1) != ARC_UNSPEC_GOTOFF
+ && XINT (addr, 1) != ARC_UNSPEC_GOTOFFPC
&& XINT (addr, 1) != UNSPEC_TLS_GD
&& XINT (addr, 1) != UNSPEC_TLS_IE)
return false;
else if (!flag_pic)
return orig;
else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
- {
- /* This symbol may be referenced via a displacement from the
- PIC base address (@GOTOFF). */
+ return gen_rtx_CONST (Pmode,
+ gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+ ARC_UNSPEC_GOTOFFPC));
- /* FIXME: if we had a way to emit pc-relative adds that
- don't create a GOT entry, we could do without the use of
- the gp register. */
- crtl->uses_pic_offset_table = 1;
- pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
- pat = gen_rtx_CONST (Pmode, pat);
- pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
- }
- else
- {
- /* This symbol must be referenced via a load from the
- Global Offset Table (@GOTPC). */
- pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
- pat = gen_rtx_CONST (Pmode, pat);
- pat = gen_const_mem (Pmode, pat);
- }
+ /* This symbol must be referenced via a load from the Global
+ Offset Table (@GOTPC). */
+ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
+ pat = gen_rtx_CONST (Pmode, pat);
+ pat = gen_const_mem (Pmode, pat);
if (oldx == NULL)
oldx = gen_reg_rtx (Pmode);
if (GET_CODE (addr) == UNSPEC)
{
/* Check that the unspec is one of the ones we generate? */
+ return orig;
}
else
gcc_assert (GET_CODE (addr) == PLUS);
case ARC_UNSPEC_GOTOFF:
suffix = "@gotoff";
break;
+ case ARC_UNSPEC_GOTOFFPC:
+ suffix = "@pcl", pcrel = true;
+ break;
case ARC_UNSPEC_PLT:
suffix = "@plt";
break;
{
case ARC_UNSPEC_PLT:
case ARC_UNSPEC_GOTOFF:
+ case ARC_UNSPEC_GOTOFFPC:
case ARC_UNSPEC_GOT:
case UNSPEC_TLS_GD:
case UNSPEC_TLS_IE:
|| (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
{
if (flag_pic)
- sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
+ sprintf (buf, "add r12,pcl,@%s@pcl\n\tjl%%!%%* [r12]", fname);
else
sprintf (buf, "jl%%! @%s", fname);
}
static rtx
arc_delegitimize_address_0 (rtx x)
{
- rtx u, gp;
+ rtx u, gp, p;
if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
{
- if (XINT (u, 1) == ARC_UNSPEC_GOT)
+ if (XINT (u, 1) == ARC_UNSPEC_GOT
+ || XINT (u, 1) == ARC_UNSPEC_GOTOFFPC)
return XVECEXP (u, 0, 0);
}
+ else if (GET_CODE (x) == CONST && GET_CODE (p = XEXP (x, 0)) == PLUS
+ && GET_CODE (u = XEXP (p, 0)) == UNSPEC
+ && (XINT (u, 1) == ARC_UNSPEC_GOT
+ || XINT (u, 1) == ARC_UNSPEC_GOTOFFPC))
+ return gen_rtx_CONST
+ (GET_MODE (x),
+ gen_rtx_PLUS (GET_MODE (p), XVECEXP (u, 0, 0), XEXP (p, 1)));
else if (GET_CODE (x) == PLUS
&& ((REG_P (gp = XEXP (x, 0))
&& REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
;; UNSPEC_GOT 4 symbol to be rerenced through the GOT
;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the
;; GOTBASE.(Referenced as @GOTOFF)
+;; UNSPEC_GOTOFFPC 6 Local symbol. To be referenced pc-relative.
;; ----------------------------------------------------------------------------
(define_c_enum "unspec" [
ARC_UNSPEC_PLT
ARC_UNSPEC_GOT
ARC_UNSPEC_GOTOFF
+ ARC_UNSPEC_GOTOFFPC
UNSPEC_TLS_GD
UNSPEC_TLS_LD
UNSPEC_TLS_IE
* return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
mov%? %0,%1 ;10
add %0,%S1 ;11
- * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
+ add %0,pcl,%1@pcl ;12
mov%? %0,%S1%& ;13
mov%? %0,%S1 ;14
ld%? %0,%1%& ;15
/* ??? Can do better for when a scratch register
is known. But that would require extra testing. */
arc_clear_unalign ();
- return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0";
+ return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1@pcl\;sr r0,[3]; LP_END\;pop_s r0";
}
output_asm_insn ((size < 2048
? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),