[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 | +}
|
---|