| [69cde8d] | 1 | Submitted By: Jim Gifford (patches at jg555 dot com)
|
|---|
| 2 | Date: 2005-09-12
|
|---|
| 3 | Initial Package Version: 4.0.1
|
|---|
| 4 | Origin: Daniel Jacobowitz
|
|---|
| 5 | Upstream Status: GCC Dev Mailling lists
|
|---|
| 6 | Description: Adds support for TLS on MIPS
|
|---|
| 7 |
|
|---|
| 8 | diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips-protos.h gcc-4.0.1/gcc/config/mips/mips-protos.h
|
|---|
| 9 | --- gcc-4.0.1.orig/gcc/config/mips/mips-protos.h 2004-12-30 03:07:56.000000000 +0000
|
|---|
| 10 | +++ gcc-4.0.1/gcc/config/mips/mips-protos.h 2005-09-12 23:27:07.000000000 +0000
|
|---|
| 11 | @@ -61,6 +61,17 @@
|
|---|
| 12 | An UNSPEC wrapper around a function's address. It represents the
|
|---|
| 13 | offset of _gp from the start of the function.
|
|---|
| 14 |
|
|---|
| 15 | + SYMBOL_TLS
|
|---|
| 16 | + A thread-local symbol.
|
|---|
| 17 | +
|
|---|
| 18 | + SYMBOL_TLSGD
|
|---|
| 19 | + SYMBOL_TLSLDM
|
|---|
| 20 | + SYMBOL_DTPREL
|
|---|
| 21 | + SYMBOL_GOTTPREL
|
|---|
| 22 | + SYMBOL_TPREL
|
|---|
| 23 | + UNSPEC wrappers around SYMBOL_TLS, corresponding to the
|
|---|
| 24 | + thread-local storage relocation operators.
|
|---|
| 25 | +
|
|---|
| 26 | SYMBOL_64_HIGH
|
|---|
| 27 | For a 64-bit symbolic address X, this is the value of
|
|---|
| 28 | (%highest(X) << 16) + %higher(X).
|
|---|
| 29 | @@ -82,6 +93,12 @@
|
|---|
| 30 | SYMBOL_GOTOFF_GLOBAL,
|
|---|
| 31 | SYMBOL_GOTOFF_CALL,
|
|---|
| 32 | SYMBOL_GOTOFF_LOADGP,
|
|---|
| 33 | + SYMBOL_TLS,
|
|---|
| 34 | + SYMBOL_TLSGD,
|
|---|
| 35 | + SYMBOL_TLSLDM,
|
|---|
| 36 | + SYMBOL_DTPREL,
|
|---|
| 37 | + SYMBOL_GOTTPREL,
|
|---|
| 38 | + SYMBOL_TPREL,
|
|---|
| 39 | SYMBOL_64_HIGH,
|
|---|
| 40 | SYMBOL_64_MID,
|
|---|
| 41 | SYMBOL_64_LOW
|
|---|
| 42 | diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips.c gcc-4.0.1/gcc/config/mips/mips.c
|
|---|
| 43 | --- gcc-4.0.1.orig/gcc/config/mips/mips.c 2005-05-08 11:56:53.000000000 +0000
|
|---|
| 44 | +++ gcc-4.0.1/gcc/config/mips/mips.c 2005-09-12 23:27:07.000000000 +0000
|
|---|
| 45 | @@ -236,6 +236,7 @@
|
|---|
| 46 | static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
|
|---|
| 47 | static bool mips_classify_address (struct mips_address_info *, rtx,
|
|---|
| 48 | enum machine_mode, int);
|
|---|
| 49 | +static bool mips_cannot_force_const_mem (rtx);
|
|---|
| 50 | static int mips_symbol_insns (enum mips_symbol_type);
|
|---|
| 51 | static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
|
|---|
| 52 | static rtx mips_force_temporary (rtx, rtx);
|
|---|
| 53 | @@ -601,7 +602,7 @@
|
|---|
| 54 | /* Map hard register number to register class */
|
|---|
| 55 | const enum reg_class mips_regno_to_class[] =
|
|---|
| 56 | {
|
|---|
| 57 | - LEA_REGS, LEA_REGS, M16_NA_REGS, M16_NA_REGS,
|
|---|
| 58 | + LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG,
|
|---|
| 59 | M16_REGS, M16_REGS, M16_REGS, M16_REGS,
|
|---|
| 60 | LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
|
|---|
| 61 | LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
|
|---|
| 62 | @@ -817,6 +818,12 @@
|
|---|
| 63 | #undef TARGET_EXPAND_BUILTIN
|
|---|
| 64 | #define TARGET_EXPAND_BUILTIN mips_expand_builtin
|
|---|
| 65 |
|
|---|
| 66 | +#undef TARGET_HAVE_TLS
|
|---|
| 67 | +#define TARGET_HAVE_TLS HAVE_AS_TLS
|
|---|
| 68 | +
|
|---|
| 69 | +#undef TARGET_CANNOT_FORCE_CONST_MEM
|
|---|
| 70 | +#define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem
|
|---|
| 71 | +
|
|---|
| 72 | struct gcc_target targetm = TARGET_INITIALIZER;
|
|---|
| 73 | |
|---|
| 74 |
|
|---|
| 75 | /* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */
|
|---|
| 76 | @@ -835,6 +842,9 @@
|
|---|
| 77 |
|
|---|
| 78 | gcc_assert (GET_CODE (x) == SYMBOL_REF);
|
|---|
| 79 |
|
|---|
| 80 | + if (SYMBOL_REF_TLS_MODEL (x))
|
|---|
| 81 | + return SYMBOL_TLS;
|
|---|
| 82 | +
|
|---|
| 83 | if (CONSTANT_POOL_ADDRESS_P (x))
|
|---|
| 84 | {
|
|---|
| 85 | if (TARGET_MIPS16)
|
|---|
| 86 | @@ -943,7 +953,11 @@
|
|---|
| 87 | if (UNSPEC_ADDRESS_P (x))
|
|---|
| 88 | *symbol_type = UNSPEC_ADDRESS_TYPE (x);
|
|---|
| 89 | else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
|
|---|
| 90 | - *symbol_type = mips_classify_symbol (x);
|
|---|
| 91 | + {
|
|---|
| 92 | + *symbol_type = mips_classify_symbol (x);
|
|---|
| 93 | + if (*symbol_type == SYMBOL_TLS)
|
|---|
| 94 | + return false;
|
|---|
| 95 | + }
|
|---|
| 96 | else
|
|---|
| 97 | return false;
|
|---|
| 98 |
|
|---|
| 99 | @@ -993,6 +1007,12 @@
|
|---|
| 100 | case SYMBOL_GOTOFF_GLOBAL:
|
|---|
| 101 | case SYMBOL_GOTOFF_CALL:
|
|---|
| 102 | case SYMBOL_GOTOFF_LOADGP:
|
|---|
| 103 | + case SYMBOL_TLSGD:
|
|---|
| 104 | + case SYMBOL_TLSLDM:
|
|---|
| 105 | + case SYMBOL_DTPREL:
|
|---|
| 106 | + case SYMBOL_TPREL:
|
|---|
| 107 | + case SYMBOL_GOTTPREL:
|
|---|
| 108 | + case SYMBOL_TLS:
|
|---|
| 109 | return false;
|
|---|
| 110 | }
|
|---|
| 111 | gcc_unreachable ();
|
|---|
| 112 | @@ -1090,6 +1110,14 @@
|
|---|
| 113 | /* The address will have to be loaded from the GOT first. */
|
|---|
| 114 | return false;
|
|---|
| 115 |
|
|---|
| 116 | + case SYMBOL_TLSGD:
|
|---|
| 117 | + case SYMBOL_TLSLDM:
|
|---|
| 118 | + case SYMBOL_DTPREL:
|
|---|
| 119 | + case SYMBOL_TPREL:
|
|---|
| 120 | + case SYMBOL_GOTTPREL:
|
|---|
| 121 | + case SYMBOL_TLS:
|
|---|
| 122 | + return false;
|
|---|
| 123 | +
|
|---|
| 124 | case SYMBOL_GOTOFF_PAGE:
|
|---|
| 125 | case SYMBOL_GOTOFF_GLOBAL:
|
|---|
| 126 | case SYMBOL_GOTOFF_CALL:
|
|---|
| 127 | @@ -1102,6 +1130,33 @@
|
|---|
| 128 | gcc_unreachable ();
|
|---|
| 129 | }
|
|---|
| 130 |
|
|---|
| 131 | +/* Return true if X is a thread-local symbol. */
|
|---|
| 132 | +
|
|---|
| 133 | +static bool
|
|---|
| 134 | +mips_tls_operand_p (rtx x)
|
|---|
| 135 | +{
|
|---|
| 136 | + return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
|
|---|
| 137 | +}
|
|---|
| 138 | +
|
|---|
| 139 | +/* Return true if X can not be forced into a constant pool. */
|
|---|
| 140 | +
|
|---|
| 141 | +static int
|
|---|
| 142 | +mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
|
|---|
| 143 | +{
|
|---|
| 144 | + return mips_tls_operand_p (*x);
|
|---|
| 145 | +}
|
|---|
| 146 | +
|
|---|
| 147 | +/* Return true if X can not be forced into a constant pool. */
|
|---|
| 148 | +
|
|---|
| 149 | +static bool
|
|---|
| 150 | +mips_cannot_force_const_mem (rtx x)
|
|---|
| 151 | +{
|
|---|
| 152 | + if (! TARGET_HAVE_TLS)
|
|---|
| 153 | + return false;
|
|---|
| 154 | +
|
|---|
| 155 | + return for_each_rtx (&x, &mips_tls_symbol_ref_1, 0);
|
|---|
| 156 | +}
|
|---|
| 157 | +
|
|---|
| 158 |
|
|---|
| 159 | /* Return true if X is a valid address for machine mode MODE. If it is,
|
|---|
| 160 | fill in INFO appropriately. STRICT is true if we should only accept
|
|---|
| 161 | @@ -1223,8 +1278,19 @@
|
|---|
| 162 | case SYMBOL_64_HIGH:
|
|---|
| 163 | case SYMBOL_64_MID:
|
|---|
| 164 | case SYMBOL_64_LOW:
|
|---|
| 165 | + case SYMBOL_TLSGD:
|
|---|
| 166 | + case SYMBOL_TLSLDM:
|
|---|
| 167 | + case SYMBOL_DTPREL:
|
|---|
| 168 | + case SYMBOL_GOTTPREL:
|
|---|
| 169 | + case SYMBOL_TPREL:
|
|---|
| 170 | /* Check whether the offset is a 16- or 32-bit value. */
|
|---|
| 171 | return mips_split_p[type] ? 2 : 1;
|
|---|
| 172 | +
|
|---|
| 173 | + case SYMBOL_TLS:
|
|---|
| 174 | + /* We don't treat a bare TLS symbol as a constant. */
|
|---|
| 175 | + return 0;
|
|---|
| 176 | +
|
|---|
| 177 | + return 1;
|
|---|
| 178 | }
|
|---|
| 179 | gcc_unreachable ();
|
|---|
| 180 | }
|
|---|
| 181 | @@ -1521,6 +1587,114 @@
|
|---|
| 182 | return plus_constant (reg, offset);
|
|---|
| 183 | }
|
|---|
| 184 |
|
|---|
| 185 | +/* Emit a call to __tls_get_addr. SYM is the TLS symbol we are
|
|---|
| 186 | + referencing, and TYPE is the symbol type to use (either global
|
|---|
| 187 | + dynamic or local dynamic). V0 is an RTX for the return value
|
|---|
| 188 | + location. The entire insn sequence is returned. */
|
|---|
| 189 | +
|
|---|
| 190 | +static GTY(()) rtx mips_tls_symbol;
|
|---|
| 191 | +
|
|---|
| 192 | +static rtx
|
|---|
| 193 | +mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
|
|---|
| 194 | +{
|
|---|
| 195 | + rtx insn, loc, tga, a0;
|
|---|
| 196 | +
|
|---|
| 197 | + a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
|
|---|
| 198 | +
|
|---|
| 199 | + if (!mips_tls_symbol)
|
|---|
| 200 | + mips_tls_symbol = init_one_libfunc ("__tls_get_addr");
|
|---|
| 201 | +
|
|---|
| 202 | + loc = mips_unspec_address (sym, type);
|
|---|
| 203 | +
|
|---|
| 204 | + start_sequence ();
|
|---|
| 205 | +
|
|---|
| 206 | + emit_insn (gen_rtx_SET (Pmode, a0,
|
|---|
| 207 | + gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
|
|---|
| 208 | + tga = gen_rtx_MEM (Pmode, mips_tls_symbol);
|
|---|
| 209 | + insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx));
|
|---|
| 210 | + CONST_OR_PURE_CALL_P (insn) = 1;
|
|---|
| 211 | + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0);
|
|---|
| 212 | + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
|
|---|
| 213 | + insn = get_insns ();
|
|---|
| 214 | +
|
|---|
| 215 | + end_sequence ();
|
|---|
| 216 | +
|
|---|
| 217 | + return insn;
|
|---|
| 218 | +}
|
|---|
| 219 | +
|
|---|
| 220 | +/* Generate the code to access LOC, a thread local SYMBOL_REF. The
|
|---|
| 221 | + return value will be a valid address and move_operand (either a REG
|
|---|
| 222 | + or a LO_SUM). */
|
|---|
| 223 | +
|
|---|
| 224 | +static rtx
|
|---|
| 225 | +mips_legitimize_tls_address (rtx loc)
|
|---|
| 226 | +{
|
|---|
| 227 | + rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
|
|---|
| 228 | + enum tls_model model;
|
|---|
| 229 | +
|
|---|
| 230 | + v0 = gen_rtx_REG (Pmode, GP_RETURN);
|
|---|
| 231 | + v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
|
|---|
| 232 | +
|
|---|
| 233 | + model = SYMBOL_REF_TLS_MODEL (loc);
|
|---|
| 234 | +
|
|---|
| 235 | + switch (model)
|
|---|
| 236 | + {
|
|---|
| 237 | + case TLS_MODEL_GLOBAL_DYNAMIC:
|
|---|
| 238 | + insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
|
|---|
| 239 | + dest = gen_reg_rtx (Pmode);
|
|---|
| 240 | + emit_libcall_block (insn, dest, v0, loc);
|
|---|
| 241 | + break;
|
|---|
| 242 | +
|
|---|
| 243 | + case TLS_MODEL_LOCAL_DYNAMIC:
|
|---|
| 244 | + insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
|
|---|
| 245 | + tmp1 = gen_reg_rtx (Pmode);
|
|---|
| 246 | +
|
|---|
| 247 | + /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
|
|---|
| 248 | + share the LDM result with other LD model accesses. */
|
|---|
| 249 | + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
|
|---|
| 250 | + UNSPEC_TLS_LDM);
|
|---|
| 251 | + emit_libcall_block (insn, tmp1, v0, eqv);
|
|---|
| 252 | +
|
|---|
| 253 | + tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
|
|---|
| 254 | + dest = gen_rtx_LO_SUM (Pmode, tmp2,
|
|---|
| 255 | + mips_unspec_address (loc, SYMBOL_DTPREL));
|
|---|
| 256 | + break;
|
|---|
| 257 | +
|
|---|
| 258 | + case TLS_MODEL_INITIAL_EXEC:
|
|---|
| 259 | + tmp1 = gen_reg_rtx (Pmode);
|
|---|
| 260 | + tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
|
|---|
| 261 | + if (Pmode == DImode)
|
|---|
| 262 | + {
|
|---|
| 263 | + emit_insn (gen_tls_get_tp_di (v1));
|
|---|
| 264 | + emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
|
|---|
| 265 | + }
|
|---|
| 266 | + else
|
|---|
| 267 | + {
|
|---|
| 268 | + emit_insn (gen_tls_get_tp_si (v1));
|
|---|
| 269 | + emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
|
|---|
| 270 | + }
|
|---|
| 271 | + dest = gen_reg_rtx (Pmode);
|
|---|
| 272 | + emit_insn (gen_add3_insn (dest, tmp1, v1));
|
|---|
| 273 | + break;
|
|---|
| 274 | +
|
|---|
| 275 | + case TLS_MODEL_LOCAL_EXEC:
|
|---|
| 276 | +
|
|---|
| 277 | + if (Pmode == DImode)
|
|---|
| 278 | + emit_insn (gen_tls_get_tp_di (v1));
|
|---|
| 279 | + else
|
|---|
| 280 | + emit_insn (gen_tls_get_tp_si (v1));
|
|---|
| 281 | +
|
|---|
| 282 | + tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
|
|---|
| 283 | + dest = gen_rtx_LO_SUM (Pmode, tmp1,
|
|---|
| 284 | + mips_unspec_address (loc, SYMBOL_TPREL));
|
|---|
| 285 | + break;
|
|---|
| 286 | +
|
|---|
| 287 | + default:
|
|---|
| 288 | + abort ();
|
|---|
| 289 | + }
|
|---|
| 290 | +
|
|---|
| 291 | + return dest;
|
|---|
| 292 | +}
|
|---|
| 293 |
|
|---|
| 294 | /* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can
|
|---|
| 295 | be legitimized in a way that the generic machinery might not expect,
|
|---|
| 296 | @@ -1532,6 +1706,12 @@
|
|---|
| 297 | {
|
|---|
| 298 | enum mips_symbol_type symbol_type;
|
|---|
| 299 |
|
|---|
| 300 | + if (mips_tls_operand_p (*xloc))
|
|---|
| 301 | + {
|
|---|
| 302 | + *xloc = mips_legitimize_tls_address (*xloc);
|
|---|
| 303 | + return true;
|
|---|
| 304 | + }
|
|---|
| 305 | +
|
|---|
| 306 | /* See if the address can split into a high part and a LO_SUM. */
|
|---|
| 307 | if (mips_symbolic_constant_p (*xloc, &symbol_type)
|
|---|
| 308 | && mips_symbolic_address_p (symbol_type, mode)
|
|---|
| 309 | @@ -1707,6 +1887,12 @@
|
|---|
| 310 | return;
|
|---|
| 311 | }
|
|---|
| 312 |
|
|---|
| 313 | + if (mips_tls_operand_p (src))
|
|---|
| 314 | + {
|
|---|
| 315 | + emit_move_insn (dest, mips_legitimize_tls_address (src));
|
|---|
| 316 | + return;
|
|---|
| 317 | + }
|
|---|
| 318 | +
|
|---|
| 319 | /* See if the symbol can be split. For mips16, this is often worse than
|
|---|
| 320 | forcing it in the constant pool since it needs the single-register form
|
|---|
| 321 | of addiu or daddiu. */
|
|---|
| 322 | @@ -4321,6 +4507,7 @@
|
|---|
| 323 | GR_REGS);
|
|---|
| 324 | mips_char_to_class['e'] = LEA_REGS;
|
|---|
| 325 | mips_char_to_class['j'] = PIC_FN_ADDR_REG;
|
|---|
| 326 | + mips_char_to_class['v'] = V1_REG;
|
|---|
| 327 | mips_char_to_class['y'] = GR_REGS;
|
|---|
| 328 | mips_char_to_class['z'] = ST_REGS;
|
|---|
| 329 | mips_char_to_class['B'] = COP0_REGS;
|
|---|
| 330 | @@ -4509,6 +4696,22 @@
|
|---|
| 331 | mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | + /* Thread-local relocation operators. */
|
|---|
| 335 | + mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
|
|---|
| 336 | + mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
|
|---|
| 337 | + mips_split_p[SYMBOL_DTPREL] = 1;
|
|---|
| 338 | + mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
|
|---|
| 339 | + mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
|
|---|
| 340 | + mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
|
|---|
| 341 | + mips_split_p[SYMBOL_TPREL] = 1;
|
|---|
| 342 | + mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
|
|---|
| 343 | + mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
|
|---|
| 344 | +
|
|---|
| 345 | + /* We don't have a thread pointer access instruction on MIPS16, or
|
|---|
| 346 | + appropriate TLS relocations. */
|
|---|
| 347 | + if (TARGET_MIPS16)
|
|---|
| 348 | + targetm.have_tls = false;
|
|---|
| 349 | +
|
|---|
| 350 | /* Default to working around R4000 errata only if the processor
|
|---|
| 351 | was selected explicitly. */
|
|---|
| 352 | if ((target_flags_explicit & MASK_FIX_R4000) == 0
|
|---|
| 353 | diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips.h gcc-4.0.1/gcc/config/mips/mips.h
|
|---|
| 354 | --- gcc-4.0.1.orig/gcc/config/mips/mips.h 2005-04-15 07:00:18.000000000 +0000
|
|---|
| 355 | +++ gcc-4.0.1/gcc/config/mips/mips.h 2005-09-12 23:27:07.000000000 +0000
|
|---|
| 356 | @@ -1714,6 +1714,7 @@
|
|---|
| 357 | T_REG, /* mips16 T register ($24) */
|
|---|
| 358 | M16_T_REGS, /* mips16 registers plus T register */
|
|---|
| 359 | PIC_FN_ADDR_REG, /* SVR4 PIC function address register */
|
|---|
| 360 | + V1_REG, /* Register $v1 ($3) used for TLS access. */
|
|---|
| 361 | LEA_REGS, /* Every GPR except $25 */
|
|---|
| 362 | GR_REGS, /* integer registers */
|
|---|
| 363 | FP_REGS, /* floating point registers */
|
|---|
| 364 | @@ -1752,6 +1753,7 @@
|
|---|
| 365 | "T_REG", \
|
|---|
| 366 | "M16_T_REGS", \
|
|---|
| 367 | "PIC_FN_ADDR_REG", \
|
|---|
| 368 | + "V1_REG", \
|
|---|
| 369 | "LEA_REGS", \
|
|---|
| 370 | "GR_REGS", \
|
|---|
| 371 | "FP_REGS", \
|
|---|
| 372 | @@ -1793,7 +1795,8 @@
|
|---|
| 373 | { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 T register */ \
|
|---|
| 374 | { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 and T regs */ \
|
|---|
| 375 | { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* SVR4 PIC function address register */ \
|
|---|
| 376 | - { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* Every other GPR */ \
|
|---|
| 377 | + { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* only $v1 */ \
|
|---|
| 378 | + { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* Every other GPR except $25 */ \
|
|---|
| 379 | { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* integer registers */ \
|
|---|
| 380 | { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* floating registers*/ \
|
|---|
| 381 | { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* hi register */ \
|
|---|
| 382 | @@ -1849,6 +1852,7 @@
|
|---|
| 383 | #define GR_REG_CLASS_P(CLASS) \
|
|---|
| 384 | ((CLASS) == GR_REGS || (CLASS) == M16_REGS || (CLASS) == T_REG \
|
|---|
| 385 | || (CLASS) == M16_T_REGS || (CLASS) == M16_NA_REGS \
|
|---|
| 386 | + || (CLASS) == V1_REG \
|
|---|
| 387 | || (CLASS) == PIC_FN_ADDR_REG || (CLASS) == LEA_REGS)
|
|---|
| 388 |
|
|---|
| 389 | /* This macro is also used later on in the file. */
|
|---|
| 390 | @@ -1896,6 +1900,7 @@
|
|---|
| 391 | 'f' Floating point registers
|
|---|
| 392 | 'h' Hi register
|
|---|
| 393 | 'l' Lo register
|
|---|
| 394 | + 'v' $v1 only
|
|---|
| 395 | 'x' Multiply/divide registers
|
|---|
| 396 | 'z' FP Status register
|
|---|
| 397 | 'B' Cop0 register
|
|---|
| 398 | @@ -3017,3 +3022,7 @@
|
|---|
| 399 | " TEXT_SECTION_ASM_OP);
|
|---|
| 400 | #endif
|
|---|
| 401 | #endif
|
|---|
| 402 | +
|
|---|
| 403 | +#ifndef HAVE_AS_TLS
|
|---|
| 404 | +#define HAVE_AS_TLS 0
|
|---|
| 405 | +#endif
|
|---|
| 406 | diff -Naur gcc-4.0.1.orig/gcc/config/mips/mips.md gcc-4.0.1/gcc/config/mips/mips.md
|
|---|
| 407 | --- gcc-4.0.1.orig/gcc/config/mips/mips.md 2005-05-08 11:56:58.000000000 +0000
|
|---|
| 408 | +++ gcc-4.0.1/gcc/config/mips/mips.md 2005-09-12 23:29:17.000000000 +0000
|
|---|
| 409 | @@ -45,6 +45,8 @@
|
|---|
| 410 | (UNSPEC_LOAD_GOT 24)
|
|---|
| 411 | (UNSPEC_GP 25)
|
|---|
| 412 | (UNSPEC_MFHILO 26)
|
|---|
| 413 | + (UNSPEC_TLS_LDM 27)
|
|---|
| 414 | + (UNSPEC_TLS_GET_TP 28)
|
|---|
| 415 |
|
|---|
| 416 | (UNSPEC_ADDRESS_FIRST 100)
|
|---|
| 417 |
|
|---|
| 418 | @@ -3027,12 +3029,12 @@
|
|---|
| 419 | ;; We could use MEMs, but an unspec gives more optimization
|
|---|
| 420 | ;; opportunities.
|
|---|
| 421 |
|
|---|
| 422 | -(define_insn "*load_got<mode>"
|
|---|
| 423 | +(define_insn "load_got<mode>"
|
|---|
| 424 | [(set (match_operand:P 0 "register_operand" "=d")
|
|---|
| 425 | (unspec:P [(match_operand:P 1 "register_operand" "d")
|
|---|
| 426 | (match_operand:P 2 "immediate_operand" "")]
|
|---|
| 427 | UNSPEC_LOAD_GOT))]
|
|---|
| 428 | - "TARGET_ABICALLS"
|
|---|
| 429 | + ""
|
|---|
| 430 | "<load>\t%0,%R2(%1)"
|
|---|
| 431 | [(set_attr "type" "load")
|
|---|
| 432 | (set_attr "mode" "<MODE>")
|
|---|
| 433 | @@ -5296,6 +5298,25 @@
|
|---|
| 434 | [(match_dup 0)]
|
|---|
| 435 | { operands[0] = mips_rewrite_small_data (operands[0]); })
|
|---|
| 436 | |
|---|
| 437 |
|
|---|
| 438 | +; Thread-Local Storage
|
|---|
| 439 | +
|
|---|
| 440 | +; The TLS base pointer is acessed via "rdhwr $v1, $29". No current
|
|---|
| 441 | +; MIPS architecture defines this register, and no current
|
|---|
| 442 | +; implementation provides it; instead, any OS which supports TLS is
|
|---|
| 443 | +; expected to trap and emulate this instruction. rdhwr is part of the
|
|---|
| 444 | +; MIPS 32r2 specification, but we use it on any architecture because
|
|---|
| 445 | +; we expect it to be emulated. Use .set to force the assembler to
|
|---|
| 446 | +; accept it.
|
|---|
| 447 | +
|
|---|
| 448 | +(define_insn "tls_get_tp_<mode>"
|
|---|
| 449 | + [(set (match_operand:P 0 "register_operand" "=v")
|
|---|
| 450 | + (unspec:P [(const_int 0)]
|
|---|
| 451 | + UNSPEC_TLS_GET_TP))]
|
|---|
| 452 | + "HAVE_AS_TLS && !TARGET_MIPS16"
|
|---|
| 453 | + ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop"
|
|---|
| 454 | + [(set_attr "type" "unknown")
|
|---|
| 455 | + (set_attr "mode" "<MODE>")])
|
|---|
| 456 | + |
|---|
| 457 |
|
|---|
| 458 | ; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
|
|---|
| 459 |
|
|---|
| 460 | (include "mips-ps-3d.md")
|
|---|
| 461 | diff -Naur gcc-4.0.1.orig/gcc/configure gcc-4.0.1/gcc/configure
|
|---|
| 462 | --- gcc-4.0.1.orig/gcc/configure 2005-07-07 20:44:40.000000000 +0000
|
|---|
| 463 | +++ gcc-4.0.1/gcc/configure 2005-09-12 23:27:07.000000000 +0000
|
|---|
| 464 | @@ -13779,6 +13779,23 @@
|
|---|
| 465 | tls_first_minor=13
|
|---|
| 466 | tls_as_opt=--fatal-warnings
|
|---|
| 467 | ;;
|
|---|
| 468 | + mips*-*-*)
|
|---|
| 469 | + conftest_s='
|
|---|
| 470 | + .section .tdata,"awT",@progbits
|
|---|
| 471 | +x:
|
|---|
| 472 | + .word 2
|
|---|
| 473 | + .text
|
|---|
| 474 | + addiu $4, $28, %tlsgd(x)
|
|---|
| 475 | + addiu $4, $28, %tlsldm(x)
|
|---|
| 476 | + lui $4, %dtprel_hi(x)
|
|---|
| 477 | + addiu $4, $4, %dtprel_lo(x)
|
|---|
| 478 | + lw $4, %gottprel(x)($28)
|
|---|
| 479 | + lui $4, %tprel_hi(x)
|
|---|
| 480 | + addiu $4, $4, %tprel_lo(x)'
|
|---|
| 481 | + tls_first_major=2
|
|---|
| 482 | + tls_first_minor=16
|
|---|
| 483 | + tls_as_opt='-32 --fatal-warnings'
|
|---|
| 484 | + ;;
|
|---|
| 485 | powerpc-*-*)
|
|---|
| 486 | conftest_s='
|
|---|
| 487 | .section ".tdata","awT",@progbits
|
|---|
| 488 | diff -Naur gcc-4.0.1.orig/gcc/configure.ac gcc-4.0.1/gcc/configure.ac
|
|---|
| 489 | --- gcc-4.0.1.orig/gcc/configure.ac 2005-06-01 08:14:33.000000000 +0000
|
|---|
| 490 | +++ gcc-4.0.1/gcc/configure.ac 2005-09-12 23:27:07.000000000 +0000
|
|---|
| 491 | @@ -2349,6 +2349,23 @@
|
|---|
| 492 | tls_first_minor=13
|
|---|
| 493 | tls_as_opt=--fatal-warnings
|
|---|
| 494 | ;;
|
|---|
| 495 | + mips*-*-*)
|
|---|
| 496 | + conftest_s='
|
|---|
| 497 | + .section .tdata,"awT",@progbits
|
|---|
| 498 | +x:
|
|---|
| 499 | + .word 2
|
|---|
| 500 | + .text
|
|---|
| 501 | + addiu $4, $28, %tlsgd(x)
|
|---|
| 502 | + addiu $4, $28, %tlsldm(x)
|
|---|
| 503 | + lui $4, %dtprel_hi(x)
|
|---|
| 504 | + addiu $4, $4, %dtprel_lo(x)
|
|---|
| 505 | + lw $4, %gottprel(x)($28)
|
|---|
| 506 | + lui $4, %tprel_hi(x)
|
|---|
| 507 | + addiu $4, $4, %tprel_lo(x)'
|
|---|
| 508 | + tls_first_major=2
|
|---|
| 509 | + tls_first_minor=16
|
|---|
| 510 | + tls_as_opt='-32 --fatal-warnings'
|
|---|
| 511 | + ;;
|
|---|
| 512 | powerpc-*-*)
|
|---|
| 513 | conftest_s='
|
|---|
| 514 | .section ".tdata","awT",@progbits
|
|---|
| 515 | diff -Naur gcc-4.0.1.orig/gcc/testsuite/gcc.dg/tls/offset-1.c gcc-4.0.1/gcc/testsuite/gcc.dg/tls/offset-1.c
|
|---|
| 516 | --- gcc-4.0.1.orig/gcc/testsuite/gcc.dg/tls/offset-1.c 1970-01-01 00:00:00.000000000 +0000
|
|---|
| 517 | +++ gcc-4.0.1/gcc/testsuite/gcc.dg/tls/offset-1.c 2005-09-12 23:27:07.000000000 +0000
|
|---|
| 518 | @@ -0,0 +1,15 @@
|
|---|
| 519 | +/* { dg-do link } */
|
|---|
| 520 | +/* Test that we do not emit a TLS reference into a constant pool. */
|
|---|
| 521 | +
|
|---|
| 522 | +__thread int x[2];
|
|---|
| 523 | +
|
|---|
| 524 | +int * __attribute__((noinline))
|
|---|
| 525 | +foo (void)
|
|---|
| 526 | +{
|
|---|
| 527 | + return &x[1];
|
|---|
| 528 | +}
|
|---|
| 529 | +
|
|---|
| 530 | +int main (void)
|
|---|
| 531 | +{
|
|---|
| 532 | + return *foo ();
|
|---|
| 533 | +}
|
|---|