aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2002-09-21 00:08:34 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2002-09-21 00:08:34 +0200
commitdea7379019da21674e38abaa27917a8596c5780f (patch)
treed0271508321ac598f9e4d438784724f40b107553 /gcc/config
parenta9b2f059741b06195e3272143f9a609459d8ca78 (diff)
downloadgcc-dea7379019da21674e38abaa27917a8596c5780f.zip
gcc-dea7379019da21674e38abaa27917a8596c5780f.tar.gz
gcc-dea7379019da21674e38abaa27917a8596c5780f.tar.bz2
i386.md (UNSPEC_GOTNTPOFF, [...]): New.
* 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. From-SVN: r57373
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c52
-rw-r--r--gcc/config/i386/i386.md2
2 files changed, 40 insertions, 14 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0926ef6..f36206c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5077,6 +5077,8 @@ legitimate_pic_address_disp_p (disp)
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);
@@ -5258,6 +5260,8 @@ legitimate_address_p (mode, addr, strict)
goto is_legitimate_pic;
case UNSPEC_GOTTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_INDNTPOFF:
case UNSPEC_NTPOFF:
case UNSPEC_DTPOFF:
break;
@@ -5664,32 +5668,36 @@ legitimize_address (x, oldx, mode)
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:
@@ -5970,6 +5978,7 @@ output_pic_addr_const (file, x, code)
fputs ("@GOTPCREL(%rip)", file);
break;
case UNSPEC_GOTTPOFF:
+ /* FIXME: This might be @TPOFF in Sun ld too. */
fputs ("@GOTTPOFF", file);
break;
case UNSPEC_TPOFF:
@@ -5981,6 +5990,12 @@ output_pic_addr_const (file, x, code)
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;
@@ -6890,6 +6905,7 @@ output_addr_const_extra (file, x)
{
case UNSPEC_GOTTPOFF:
output_addr_const (file, op);
+ /* FIXME: This might be @TPOFF in Sun ld. */
fputs ("@GOTTPOFF", file);
break;
case UNSPEC_TPOFF:
@@ -6904,6 +6920,14 @@ output_addr_const_extra (file, x)
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;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index eb74fb5..02e4ee8 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -61,6 +61,8 @@
(UNSPEC_TPOFF 4)
(UNSPEC_NTPOFF 5)
(UNSPEC_DTPOFF 6)
+ (UNSPEC_GOTNTPOFF 7)
+ (UNSPEC_INDNTPOFF 8)
; Prologue support
(UNSPEC_STACK_PROBE 10)