+2002-09-20 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.md (UNSPEC_GOTNTPOFF, UNSPEC_INDNTPOFF): New.
+ * config/i386/i386.c (legitimate_pic_address_disp_p): Handle
+ UNSPEC_GOTNTPOFF and UNSPEC_INDNTPOFF like UNSPEC_GOTTPOFF.
+ (legitimate_address_p): Likewise.
+ (legitimize_address): Use @gotntpoff and @indntpoff.
+ (output_pic_addr_const): Handle UNSPEC_GOTNTPOFF and UNSPEC_INDNTPOFF.
+ (output_addr_const_extra): Likewise.
+
2002-09-20 Jim Wilson <wilson@redhat.com>
* combine.c (try_combine): When split an instruction pair, where the
case UNSPEC_GOTOFF:
return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
case UNSPEC_GOTTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_INDNTPOFF:
if (saw_plus)
return false;
return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
goto is_legitimate_pic;
case UNSPEC_GOTTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_INDNTPOFF:
case UNSPEC_NTPOFF:
case UNSPEC_DTPOFF:
break;
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
pic = pic_offset_table_rtx;
}
- else
+ else if (!TARGET_GNU_TLS)
{
pic = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (pic));
}
+ else
+ pic = NULL;
base = get_thread_pointer ();
- off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_GOTTPOFF);
+ off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
+ !TARGET_GNU_TLS
+ ? UNSPEC_GOTTPOFF
+ : flag_pic ? UNSPEC_GOTNTPOFF
+ : UNSPEC_INDNTPOFF);
off = gen_rtx_CONST (Pmode, off);
- off = gen_rtx_PLUS (Pmode, pic, off);
+ if (flag_pic || !TARGET_GNU_TLS)
+ off = gen_rtx_PLUS (Pmode, pic, off);
off = gen_rtx_MEM (Pmode, off);
RTX_UNCHANGING_P (off) = 1;
set_mem_alias_set (off, ix86_GOT_alias_set ());
-
- /* Damn Sun for specifing a set of dynamic relocations without
- considering the two-operand nature of the architecture!
- We'd be much better off with a "GOTNTPOFF" relocation that
- already contained the negated constant. */
- /* ??? Using negl and reg+reg addressing appears to be a lose
- size-wise. The negl is two bytes, just like the extra movl
- incurred by the two-operand subl, but reg+reg addressing
- uses the two-byte modrm form, unlike plain reg. */
-
dest = gen_reg_rtx (Pmode);
- emit_insn (gen_subsi3 (dest, base, off));
+
+ if (TARGET_GNU_TLS)
+ {
+ emit_move_insn (dest, off);
+ return gen_rtx_PLUS (Pmode, base, dest);
+ }
+ else
+ emit_insn (gen_subsi3 (dest, base, off));
break;
case TLS_MODEL_LOCAL_EXEC:
fputs ("@GOTPCREL(%rip)", file);
break;
case UNSPEC_GOTTPOFF:
+ /* FIXME: This might be @TPOFF in Sun ld too. */
fputs ("@GOTTPOFF", file);
break;
case UNSPEC_TPOFF:
case UNSPEC_DTPOFF:
fputs ("@DTPOFF", file);
break;
+ case UNSPEC_GOTNTPOFF:
+ fputs ("@GOTNTPOFF", file);
+ break;
+ case UNSPEC_INDNTPOFF:
+ fputs ("@INDNTPOFF", file);
+ break;
default:
output_operand_lossage ("invalid UNSPEC as operand");
break;
{
case UNSPEC_GOTTPOFF:
output_addr_const (file, op);
+ /* FIXME: This might be @TPOFF in Sun ld. */
fputs ("@GOTTPOFF", file);
break;
case UNSPEC_TPOFF:
output_addr_const (file, op);
fputs ("@DTPOFF", file);
break;
+ case UNSPEC_GOTNTPOFF:
+ output_addr_const (file, op);
+ fputs ("@GOTNTPOFF", file);
+ break;
+ case UNSPEC_INDNTPOFF:
+ output_addr_const (file, op);
+ fputs ("@INDNTPOFF", file);
+ break;
default:
return false;