@@ -487,12 +487,17 @@ arc64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
487487 if ((GET_CODE (x ) == PRE_MODIFY || GET_CODE (x ) == POST_MODIFY ))
488488 return true;
489489
490- /* PIC address. */
490+ /* PIC address (LARGE) . */
491491 if (GET_CODE (x ) == LO_SUM
492492 && REG_P (XEXP (x , 0 ))
493493 && GET_CODE (XEXP (x , 1 )) == UNSPEC )
494494 return true;
495495
496+ /* PIC address (small). */
497+ if (GET_CODE (x ) == UNSPEC
498+ && XINT (x , 1 ) == ARC64_UNSPEC_GOT32 )
499+ return true;
500+
496501 return false;
497502}
498503
@@ -1062,15 +1067,21 @@ arc64_print_operand_address (FILE *file , machine_mode mode, rtx addr)
10621067 output_address (VOIDmode , XEXP (addr , 1 ));
10631068 break ;
10641069
1065- /* This type of address can be only accepted by LD instructions. */
10661070 case LO_SUM :
1071+ /* This type of address can be only accepted by LD instructions. */
10671072 base = XEXP (addr , 0 );
10681073 index = XEXP (addr , 1 );
10691074 arc64_print_operand_address (file , mode , base );
10701075 fputc (',' , file );
10711076 output_addr_const (file , index );
10721077 break ;
10731078
1079+ case UNSPEC :
1080+ /* Small PIC. */
1081+ fputs ("pcl," , file );
1082+ output_addr_const (file , addr );
1083+ break ;
1084+
10741085 case CONST_INT :
10751086 output_addr_const (file , addr );
10761087 break ;
@@ -1107,6 +1118,7 @@ arc64_output_addr_const_extra (FILE *file, rtx x)
11071118 fputs ("@pcl" , file );
11081119 break ;
11091120
1121+ case ARC64_UNSPEC_GOT32 :
11101122 case ARC64_UNSPEC_GOT :
11111123 fputs ("@gotpc" , file );
11121124 break ;
@@ -1159,9 +1171,17 @@ arc64_legitimize_address_1 (rtx x, rtx scratch)
11591171 base = gen_sym_unspec (x , ARC64_UNSPEC_GOTOFF );
11601172 return base ;
11611173 }
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+ }
11621181 else
11631182 {
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). */
11651185 base = gen_sym_unspec (x , ARC64_UNSPEC_GOT );
11661186 emit_insn (gen_rtx_SET (t1 , gen_rtx_HIGH (Pmode , base )));
11671187 t1 = gen_rtx_LO_SUM (Pmode , t1 , copy_rtx (base ));
@@ -1381,11 +1401,35 @@ arc64_output_function_prologue (FILE *f)
13811401 }
13821402}
13831403
1384-
13851404/*
13861405 Global functions.
13871406*/
13881407
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+
13891433/* X and Y are two things to compare using CODE. Emit the compare insn and
13901434 return the rtx for the cc reg in the proper mode. */
13911435
@@ -1596,8 +1640,8 @@ arc64_expand_call (rtx result, rtx mem, bool sibcall)
15961640 /* Decide if we should generate indirect calls by loading the
15971641 address of the callee into a register before performing the
15981642 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 );
16011645
16021646 call = gen_rtx_CALL (VOIDmode , mem , const0_rtx );
16031647
0 commit comments