@@ -1958,6 +1958,9 @@ riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value)
19581958 case BFD_RELOC_RISCV_LO12_I :
19591959 return ENCODE_ITYPE_IMM (value );
19601960
1961+ case BFD_RELOC_RISCV_LPAD :
1962+ return ENCODE_UTYPE_IMM (value << RISCV_IMM_BITS );
1963+
19611964 default :
19621965 abort ();
19631966 }
@@ -3680,6 +3683,16 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
36803683 * imm_reloc = BFD_RELOC_RISCV_HI20 ;
36813684 imm_expr -> X_add_number <<= RISCV_IMM_BITS ;
36823685 }
3686+ {
3687+ bool is_lpad = strcmp (str , "lpad" ) == 0 ;
3688+ if (is_lpad )
3689+ {
3690+ /* Always insert a lpad relocation for lpad instruction. */
3691+ * imm_reloc = BFD_RELOC_RISCV_LPAD ;
3692+ /* And recover the immediate format to unshift value. */
3693+ imm_expr -> X_add_number >>= RISCV_IMM_BITS ;
3694+ }
3695+ }
36833696 asarg = expr_parse_end ;
36843697 continue ;
36853698
@@ -4673,6 +4686,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
46734686
46744687 switch (fixP -> fx_r_type )
46754688 {
4689+ case BFD_RELOC_RISCV_LPAD :
4690+ bfd_putl32 (riscv_apply_const_reloc (fixP -> fx_r_type , * valP )
4691+ | bfd_getl32 (buf ), buf );
4692+ fixP -> fx_done = false;
4693+ fixP -> fx_addnumber = 0 ;
4694+ fixP -> fx_offset = 0 ;
4695+ relaxable = true;
4696+ break ;
46764697 case BFD_RELOC_RISCV_HI20 :
46774698 case BFD_RELOC_RISCV_LO12_I :
46784699 case BFD_RELOC_RISCV_LO12_S :
@@ -4998,8 +5019,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
49985019 if (fixP -> fx_subsy != NULL )
49995020 as_bad_subtract (fixP );
50005021
5001- /* Add an R_RISCV_RELAX reloc if the reloc is relaxable. */
5002- if (relaxable && fixP -> fx_tcbit && fixP -> fx_addsy != NULL )
5022+ /* Add an R_RISCV_RELAX reloc if the reloc is relaxable,
5023+ and we need that for R_RISCV_LPAD as well. */
5024+ if (relaxable && fixP -> fx_tcbit
5025+ && (fixP -> fx_addsy != NULL
5026+ || (fixP -> fx_r_type == BFD_RELOC_RISCV_LPAD )))
50035027 {
50045028 fixP -> fx_next = xmemdup (fixP , sizeof (* fixP ), sizeof (* fixP ));
50055029 fixP -> fx_next -> fx_addsy = fixP -> fx_next -> fx_subsy = NULL ;
0 commit comments