diff options
author | Jakub Jelinek <jakub@redhat.com> | 2002-09-21 00:08:34 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2002-09-21 00:08:34 +0200 |
commit | dea7379019da21674e38abaa27917a8596c5780f (patch) | |
tree | d0271508321ac598f9e4d438784724f40b107553 /gcc/config | |
parent | a9b2f059741b06195e3272143f9a609459d8ca78 (diff) | |
download | gcc-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.c | 52 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 2 |
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) |