@@ -1123,6 +1123,18 @@ arc64_output_addr_const_extra (FILE *file, rtx x)
1123
1123
fputs ("@gotpc" , file );
1124
1124
break ;
1125
1125
1126
+ case ARC64_UNSPEC_TLS_GD :
1127
+ fputs ("@tlsgd" , file );
1128
+ break ;
1129
+
1130
+ case ARC64_UNSPEC_TLS_IE :
1131
+ fputs ("@tlsie" , file );
1132
+ break ;
1133
+
1134
+ case ARC64_UNSPEC_TLS_OFF :
1135
+ fputs ("@tpoff" , file );
1136
+ break ;
1137
+
1126
1138
default :
1127
1139
gcc_unreachable ();
1128
1140
}
@@ -1140,6 +1152,94 @@ gen_sym_unspec (rtx x, int kind)
1140
1152
return gen_rtx_UNSPEC (Pmode , gen_rtvec (1 , x ), kind );
1141
1153
}
1142
1154
1155
+ /* The __tls_get_attr symbol. */
1156
+ static GTY (( )) rtx arc_tls_symbol ;
1157
+
1158
+ /* Emit a call to __tls_get_addr. TI is the argument to this function.
1159
+ RET is an RTX for the return value location. The entire insn sequence
1160
+ is returned. */
1161
+
1162
+ static void
1163
+ arc64_tls_call (rtx dest , rtx arg )
1164
+ {
1165
+ if (!arc_tls_symbol )
1166
+ arc_tls_symbol = init_one_libfunc ("__tls_get_addr" );
1167
+
1168
+ emit_library_call_value (arc_tls_symbol , dest , LCT_CONST , Pmode ,
1169
+ arg , Pmode );
1170
+ }
1171
+
1172
+ /* Create a legitimate mov instruction for the given BASE (unspec). */
1173
+
1174
+ static rtx
1175
+ arc64_legit_unspec (rtx base )
1176
+ {
1177
+ rtx t1 , ret ;
1178
+ gcc_assert (can_create_pseudo_p ());
1179
+
1180
+ switch (arc64_cmodel_var )
1181
+ {
1182
+ case ARC64_CMODEL_SMALL :
1183
+ case ARC64_CMODEL_MEDIUM :
1184
+ return base ;
1185
+
1186
+ case ARC64_CMODEL_LARGE :
1187
+ t1 = gen_reg_rtx (Pmode );
1188
+ ret = gen_reg_rtx (Pmode );
1189
+ emit_insn (gen_rtx_SET (t1 , gen_rtx_HIGH (Pmode , base )));
1190
+ emit_insn (gen_rtx_SET (ret , gen_rtx_LO_SUM (Pmode , t1 , base )));
1191
+ return ret ;
1192
+
1193
+ default :
1194
+ break ;
1195
+ }
1196
+ gcc_unreachable ();
1197
+ }
1198
+
1199
+ /* Return a legitimized TLS address to access ADDR, which is a
1200
+ SYMBOL_REF. */
1201
+
1202
+ static rtx
1203
+ arc64_legitimize_tls_address (rtx addr )
1204
+ {
1205
+ rtx t1 , t2 ;
1206
+ rtx base ;
1207
+ enum tls_model model = SYMBOL_REF_TLS_MODEL (addr );
1208
+
1209
+ gcc_assert (can_create_pseudo_p ());
1210
+
1211
+ switch (model )
1212
+ {
1213
+ case TLS_MODEL_LOCAL_DYNAMIC :
1214
+ case TLS_MODEL_GLOBAL_DYNAMIC :
1215
+ /* Gen:
1216
+ addl r0,pcl,@ADDR@tlsgd
1217
+ bl __tls_get_addr@plt */
1218
+ t2 = gen_reg_rtx (Pmode );
1219
+ base = gen_sym_unspec (addr , ARC64_UNSPEC_TLS_GD );
1220
+ t1 = arc64_legit_unspec (base );
1221
+ arc64_tls_call (t2 , t1 );
1222
+ return t2 ;
1223
+
1224
+ case TLS_MODEL_INITIAL_EXEC :
1225
+ /* Gen:
1226
+ ldl rx,[pcl,@ADDR@tlsie]
1227
+ addl rx,rx,r30 */
1228
+ addr = arc64_legit_unspec (gen_sym_unspec (addr , ARC64_UNSPEC_TLS_IE ));
1229
+ addr = copy_to_mode_reg (Pmode , gen_const_mem (Pmode , addr ));
1230
+ return gen_rtx_PLUS (Pmode , addr , gen_rtx_REG (Pmode , R30_REGNUM ));
1231
+
1232
+ case TLS_MODEL_LOCAL_EXEC :
1233
+ /* Gen:
1234
+ addl rx,r30,@ADDR@tpoff */
1235
+ addr = arc64_legit_unspec (gen_sym_unspec (addr , ARC64_UNSPEC_TLS_OFF ));
1236
+ return gen_rtx_PLUS (Pmode , gen_rtx_REG (Pmode , R30_REGNUM ), addr );
1237
+
1238
+ default :
1239
+ gcc_unreachable ();
1240
+ }
1241
+ }
1242
+
1143
1243
/* Helper function. Returns a valid ARC64 RTX that represents the
1144
1244
argument X which is an invalid address RTX. The argument SCRATCH
1145
1245
may be used as a temp when building affresses. */
@@ -1154,6 +1254,8 @@ arc64_legitimize_address_1 (rtx x, rtx scratch)
1154
1254
{
1155
1255
case SYMBOL_REF :
1156
1256
is_local = SYMBOL_REF_LOCAL_P (x );
1257
+ if (SYMBOL_REF_TLS_MODEL (x ))
1258
+ return arc64_legitimize_tls_address (x );
1157
1259
/* FALLTHRU */
1158
1260
1159
1261
case LABEL_REF :
@@ -1934,6 +2036,12 @@ arc64_limm_addr_p (rtx op)
1934
2036
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1935
2037
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA arc64_output_addr_const_extra
1936
2038
2039
+ /* Having TLS support, we turn R30 fixed as well. */
2040
+ #ifdef HAVE_AS_TLS
2041
+ #undef TARGET_HAVE_TLS
2042
+ #define TARGET_HAVE_TLS HAVE_AS_TLS
2043
+ #endif
2044
+
1937
2045
struct gcc_target targetm = TARGET_INITIALIZER ;
1938
2046
1939
2047
#include "gt-arc64.h"
0 commit comments