@@ -487,12 +487,17 @@ arc64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
487
487
if ((GET_CODE (x ) == PRE_MODIFY || GET_CODE (x ) == POST_MODIFY ))
488
488
return true;
489
489
490
- /* PIC address. */
490
+ /* PIC address (LARGE) . */
491
491
if (GET_CODE (x ) == LO_SUM
492
492
&& REG_P (XEXP (x , 0 ))
493
493
&& GET_CODE (XEXP (x , 1 )) == UNSPEC )
494
494
return true;
495
495
496
+ /* PIC address (small). */
497
+ if (GET_CODE (x ) == UNSPEC
498
+ && XINT (x , 1 ) == ARC64_UNSPEC_GOT32 )
499
+ return true;
500
+
496
501
return false;
497
502
}
498
503
@@ -1062,15 +1067,21 @@ arc64_print_operand_address (FILE *file , machine_mode mode, rtx addr)
1062
1067
output_address (VOIDmode , XEXP (addr , 1 ));
1063
1068
break ;
1064
1069
1065
- /* This type of address can be only accepted by LD instructions. */
1066
1070
case LO_SUM :
1071
+ /* This type of address can be only accepted by LD instructions. */
1067
1072
base = XEXP (addr , 0 );
1068
1073
index = XEXP (addr , 1 );
1069
1074
arc64_print_operand_address (file , mode , base );
1070
1075
fputc (',' , file );
1071
1076
output_addr_const (file , index );
1072
1077
break ;
1073
1078
1079
+ case UNSPEC :
1080
+ /* Small PIC. */
1081
+ fputs ("pcl," , file );
1082
+ output_addr_const (file , addr );
1083
+ break ;
1084
+
1074
1085
case CONST_INT :
1075
1086
output_addr_const (file , addr );
1076
1087
break ;
@@ -1107,6 +1118,7 @@ arc64_output_addr_const_extra (FILE *file, rtx x)
1107
1118
fputs ("@pcl" , file );
1108
1119
break ;
1109
1120
1121
+ case ARC64_UNSPEC_GOT32 :
1110
1122
case ARC64_UNSPEC_GOT :
1111
1123
fputs ("@gotpc" , file );
1112
1124
break ;
@@ -1159,9 +1171,17 @@ arc64_legitimize_address_1 (rtx x, rtx scratch)
1159
1171
base = gen_sym_unspec (x , ARC64_UNSPEC_GOTOFF );
1160
1172
return base ;
1161
1173
}
1174
+ else if (flag_pic == 1 )
1175
+ {
1176
+ /* Global symbol, we access it via a load from the GOT
1177
+ (small model). */
1178
+ base = gen_sym_unspec (x , ARC64_UNSPEC_GOT32 );
1179
+ return gen_const_mem (Pmode , base );
1180
+ }
1162
1181
else
1163
1182
{
1164
- /* Global symbol, we access it via a load from the GOT. */
1183
+ /* Global symbol, we access it via a load from the GOT
1184
+ (LARGE model). */
1165
1185
base = gen_sym_unspec (x , ARC64_UNSPEC_GOT );
1166
1186
emit_insn (gen_rtx_SET (t1 , gen_rtx_HIGH (Pmode , base )));
1167
1187
t1 = gen_rtx_LO_SUM (Pmode , t1 , copy_rtx (base ));
@@ -1381,11 +1401,35 @@ arc64_output_function_prologue (FILE *f)
1381
1401
}
1382
1402
}
1383
1403
1384
-
1385
1404
/*
1386
1405
Global functions.
1387
1406
*/
1388
1407
1408
+ /* Returns TRUE if CALLEE should be treated as long-calls (i.e. called
1409
+ via a register). */
1410
+
1411
+ bool
1412
+ arc64_is_long_call_p (rtx sym )
1413
+ {
1414
+ const_tree decl ;
1415
+
1416
+ if (!SYMBOL_REF_P (sym ))
1417
+ return false;
1418
+
1419
+ /* If my memory model is small everything can go via usual bl/jl
1420
+ instructions. */
1421
+ if (arc64_cmodel_var == ARC64_CMODEL_SMALL )
1422
+ return false;
1423
+
1424
+ decl = SYMBOL_REF_DECL (sym );
1425
+ if (flag_pic
1426
+ && decl
1427
+ && !targetm .binds_local_p (decl ))
1428
+ return true;
1429
+
1430
+ return false;
1431
+ }
1432
+
1389
1433
/* X and Y are two things to compare using CODE. Emit the compare insn and
1390
1434
return the rtx for the cc reg in the proper mode. */
1391
1435
@@ -1596,8 +1640,8 @@ arc64_expand_call (rtx result, rtx mem, bool sibcall)
1596
1640
/* Decide if we should generate indirect calls by loading the
1597
1641
address of the callee into a register before performing the
1598
1642
branch-and-link. */
1599
- // FIXME! if (arc64_is_long_call_p (callee) && !REG_P (callee))
1600
- // FIXME! XEXP (mem, 0) = force_reg (mode, callee);
1643
+ if (arc64_is_long_call_p (callee ) && !REG_P (callee ))
1644
+ XEXP (mem , 0 ) = force_reg (mode , callee );
1601
1645
1602
1646
call = gen_rtx_CALL (VOIDmode , mem , const0_rtx );
1603
1647
0 commit comments