elfxx-loongarch.c revision 1.1.1.1 1 1.1 christos /* LoongArch-specific support for ELF.
2 1.1 christos Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 1.1 christos Contributed by Loongson Ltd.
4 1.1 christos
5 1.1 christos Based on RISC-V target.
6 1.1 christos
7 1.1 christos This file is part of BFD, the Binary File Descriptor library.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program; see the file COPYING3. If not,
21 1.1 christos see <http://www.gnu.org/licenses/>. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include "bfd.h"
25 1.1 christos #include "libbfd.h"
26 1.1 christos #include "elf-bfd.h"
27 1.1 christos #include "elf/loongarch.h"
28 1.1 christos #include "elfxx-loongarch.h"
29 1.1 christos
30 1.1 christos #define ALL_ONES (~ (bfd_vma) 0)
31 1.1 christos
32 1.1 christos typedef struct loongarch_reloc_howto_type_struct
33 1.1 christos {
34 1.1 christos /* The first must be reloc_howto_type! */
35 1.1 christos reloc_howto_type howto;
36 1.1 christos bfd_reloc_code_real_type bfd_type;
37 1.1 christos bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
38 1.1 christos }loongarch_reloc_howto_type;
39 1.1 christos
40 1.1 christos #define LOONGARCH_DEFAULT_HOWTO(r_name) \
41 1.1 christos { HOWTO (R_LARCH_##r_name, 0, 4, 32, false, 0, complain_overflow_signed, \
42 1.1 christos bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES, \
43 1.1 christos false), BFD_RELOC_LARCH_##r_name, NULL }
44 1.1 christos
45 1.1 christos #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \
46 1.1 christos name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc) \
47 1.1 christos { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \
48 1.1 christos inplace, src_mask, dst_mask, pcrel_off), btype, afunc }
49 1.1 christos
50 1.1 christos #define LOONGARCH_EMPTY_HOWTO(C) \
51 1.1 christos { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL }
52 1.1 christos
53 1.1 christos bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *val);
54 1.1 christos bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
55 1.1 christos bfd_vma *fix_val);
56 1.1 christos bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
57 1.1 christos bfd_vma *val);
58 1.1 christos
59 1.1 christos
60 1.1 christos /* This does not include any relocation information, but should be
61 1.1 christos good enough for GDB or objdump to read the file. */
62 1.1 christos static loongarch_reloc_howto_type loongarch_howto_table[] =
63 1.1 christos {
64 1.1 christos /* No relocation. */
65 1.1 christos LOONGARCH_HOWTO (R_LARCH_NONE, /* type (0). */
66 1.1 christos 0, /* rightshift */
67 1.1 christos 0, /* size */
68 1.1 christos 0, /* bitsize */
69 1.1 christos false, /* pc_relative */
70 1.1 christos 0, /* bitpos */
71 1.1 christos complain_overflow_dont, /* complain_on_overflow */
72 1.1 christos bfd_elf_generic_reloc, /* special_function */
73 1.1 christos "R_LARCH_NONE", /* name */
74 1.1 christos false, /* partial_inplace */
75 1.1 christos 0, /* src_mask */
76 1.1 christos 0, /* dst_mask */
77 1.1 christos false, /* pcrel_offset */
78 1.1 christos BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
79 1.1 christos NULL), /* adjust_reloc_bits */
80 1.1 christos
81 1.1 christos /* 32 bit relocation. */
82 1.1 christos LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */
83 1.1 christos 0, /* rightshift */
84 1.1 christos 4, /* size */
85 1.1 christos 32, /* bitsize */
86 1.1 christos false, /* pc_relative */
87 1.1 christos 0, /* bitpos */
88 1.1 christos complain_overflow_dont, /* complain_on_overflow */
89 1.1 christos bfd_elf_generic_reloc, /* special_function */
90 1.1 christos "R_LARCH_32", /* name */
91 1.1 christos false, /* partial_inplace */
92 1.1 christos 0, /* src_mask */
93 1.1 christos ALL_ONES, /* dst_mask */
94 1.1 christos false, /* pcrel_offset */
95 1.1 christos BFD_RELOC_32, /* bfd_reloc_code_real_type */
96 1.1 christos NULL), /* adjust_reloc_bits */
97 1.1 christos
98 1.1 christos /* 64 bit relocation. */
99 1.1 christos LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */
100 1.1 christos 0, /* rightshift */
101 1.1 christos 8, /* size */
102 1.1 christos 64, /* bitsize */
103 1.1 christos false, /* pc_relative */
104 1.1 christos 0, /* bitpos */
105 1.1 christos complain_overflow_dont, /* complain_on_overflow */
106 1.1 christos bfd_elf_generic_reloc, /* special_function */
107 1.1 christos "R_LARCH_64", /* name */
108 1.1 christos false, /* partial_inplace */
109 1.1 christos 0, /* src_mask */
110 1.1 christos ALL_ONES, /* dst_mask */
111 1.1 christos false, /* pcrel_offset */
112 1.1 christos BFD_RELOC_64, /* bfd_reloc_code_real_type */
113 1.1 christos NULL), /* adjust_reloc_bits */
114 1.1 christos
115 1.1 christos LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */
116 1.1 christos 0, /* rightshift */
117 1.1 christos 4, /* size */
118 1.1 christos 32, /* bitsize */
119 1.1 christos false, /* pc_relative */
120 1.1 christos 0, /* bitpos */
121 1.1 christos complain_overflow_dont, /* complain_on_overflow */
122 1.1 christos bfd_elf_generic_reloc, /* special_function */
123 1.1 christos "R_LARCH_RELATIVE", /* name */
124 1.1 christos false, /* partial_inplace */
125 1.1 christos 0, /* src_mask */
126 1.1 christos ALL_ONES, /* dst_mask */
127 1.1 christos false, /* pcrel_offset */
128 1.1 christos BFD_RELOC_NONE, /* undefined? */
129 1.1 christos NULL), /* adjust_reloc_bits */
130 1.1 christos
131 1.1 christos LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */
132 1.1 christos 0, /* rightshift */
133 1.1 christos 0, /* this one is variable size */
134 1.1 christos 0, /* bitsize */
135 1.1 christos false, /* pc_relative */
136 1.1 christos 0, /* bitpos */
137 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
138 1.1 christos bfd_elf_generic_reloc, /* special_function */
139 1.1 christos "R_LARCH_COPY", /* name */
140 1.1 christos false, /* partial_inplace */
141 1.1 christos 0, /* src_mask */
142 1.1 christos 0, /* dst_mask */
143 1.1 christos false, /* pcrel_offset */
144 1.1 christos BFD_RELOC_NONE, /* undefined? */
145 1.1 christos NULL), /* adjust_reloc_bits */
146 1.1 christos
147 1.1 christos LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */
148 1.1 christos 0, /* rightshift */
149 1.1 christos 8, /* size */
150 1.1 christos 64, /* bitsize */
151 1.1 christos false, /* pc_relative */
152 1.1 christos 0, /* bitpos */
153 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
154 1.1 christos bfd_elf_generic_reloc, /* special_function */
155 1.1 christos "R_LARCH_JUMP_SLOT", /* name */
156 1.1 christos false, /* partial_inplace */
157 1.1 christos 0, /* src_mask */
158 1.1 christos 0, /* dst_mask */
159 1.1 christos false, /* pcrel_offset */
160 1.1 christos BFD_RELOC_NONE, /* undefined? */
161 1.1 christos NULL), /* adjust_reloc_bits */
162 1.1 christos
163 1.1 christos /* Dynamic TLS relocations. */
164 1.1 christos LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */
165 1.1 christos 0, /* rightshift */
166 1.1 christos 4, /* size */
167 1.1 christos 32, /* bitsize */
168 1.1 christos false, /* pc_relative */
169 1.1 christos 0, /* bitpos */
170 1.1 christos complain_overflow_dont, /* complain_on_overflow */
171 1.1 christos bfd_elf_generic_reloc, /* special_function */
172 1.1 christos "R_LARCH_TLS_DTPMOD32", /* name */
173 1.1 christos false, /* partial_inplace */
174 1.1 christos 0, /* src_mask */
175 1.1 christos ALL_ONES, /* dst_mask */
176 1.1 christos false, /* pcrel_offset */
177 1.1 christos BFD_RELOC_LARCH_TLS_DTPMOD32, /* bfd_reloc_code_real_type */
178 1.1 christos NULL), /* adjust_reloc_bits */
179 1.1 christos
180 1.1 christos LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */
181 1.1 christos 0, /* rightshift */
182 1.1 christos 8, /* size */
183 1.1 christos 64, /* bitsize */
184 1.1 christos false, /* pc_relative */
185 1.1 christos 0, /* bitpos */
186 1.1 christos complain_overflow_dont, /* complain_on_overflow */
187 1.1 christos bfd_elf_generic_reloc, /* special_function */
188 1.1 christos "R_LARCH_TLS_DTPMOD64", /* name */
189 1.1 christos false, /* partial_inplace */
190 1.1 christos 0, /* src_mask */
191 1.1 christos ALL_ONES, /* dst_mask */
192 1.1 christos false, /* pcrel_offset */
193 1.1 christos BFD_RELOC_LARCH_TLS_DTPMOD64, /* bfd_reloc_code_real_type */
194 1.1 christos NULL), /* adjust_reloc_bits */
195 1.1 christos
196 1.1 christos LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */
197 1.1 christos 0, /* rightshift */
198 1.1 christos 4, /* size */
199 1.1 christos 32, /* bitsize */
200 1.1 christos false, /* pc_relative */
201 1.1 christos 0, /* bitpos */
202 1.1 christos complain_overflow_dont, /* complain_on_overflow */
203 1.1 christos bfd_elf_generic_reloc, /* special_function */
204 1.1 christos "R_LARCH_TLS_DTPREL32", /* name */
205 1.1 christos true, /* partial_inplace */
206 1.1 christos 0, /* src_mask */
207 1.1 christos ALL_ONES, /* dst_mask */
208 1.1 christos false, /* pcrel_offset */
209 1.1 christos BFD_RELOC_LARCH_TLS_DTPREL32, /* bfd_reloc_code_real_type */
210 1.1 christos NULL), /* adjust_reloc_bits */
211 1.1 christos
212 1.1 christos LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */
213 1.1 christos 0, /* rightshift */
214 1.1 christos 8, /* size */
215 1.1 christos 64, /* bitsize */
216 1.1 christos false, /* pc_relative */
217 1.1 christos 0, /* bitpos */
218 1.1 christos complain_overflow_dont, /* complain_on_overflow */
219 1.1 christos bfd_elf_generic_reloc, /* special_function */
220 1.1 christos "R_LARCH_TLS_DTPREL64", /* name */
221 1.1 christos true, /* partial_inplace */
222 1.1 christos 0, /* src_mask */
223 1.1 christos ALL_ONES, /* dst_mask */
224 1.1 christos false, /* pcrel_offset */
225 1.1 christos BFD_RELOC_LARCH_TLS_DTPREL64, /* bfd_reloc_code_real_type */
226 1.1 christos NULL), /* adjust_reloc_bits */
227 1.1 christos
228 1.1 christos LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */
229 1.1 christos 0, /* rightshift */
230 1.1 christos 4, /* size */
231 1.1 christos 32, /* bitsize */
232 1.1 christos false, /* pc_relative */
233 1.1 christos 0, /* bitpos */
234 1.1 christos complain_overflow_dont, /* complain_on_overflow */
235 1.1 christos bfd_elf_generic_reloc, /* special_function */
236 1.1 christos "R_LARCH_TLS_TPREL32", /* name */
237 1.1 christos false, /* partial_inplace */
238 1.1 christos 0, /* src_mask */
239 1.1 christos ALL_ONES, /* dst_mask */
240 1.1 christos false, /* pcrel_offset */
241 1.1 christos BFD_RELOC_LARCH_TLS_TPREL32, /* bfd_reloc_code_real_type */
242 1.1 christos NULL), /* adjust_reloc_bits */
243 1.1 christos
244 1.1 christos LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */
245 1.1 christos 0, /* rightshift */
246 1.1 christos 8, /* size */
247 1.1 christos 64, /* bitsize */
248 1.1 christos false, /* pc_relative */
249 1.1 christos 0, /* bitpos */
250 1.1 christos complain_overflow_dont, /* complain_on_overflow */
251 1.1 christos bfd_elf_generic_reloc, /* special_function */
252 1.1 christos "R_LARCH_TLS_TPREL64", /* name */
253 1.1 christos false, /* partial_inplace */
254 1.1 christos 0, /* src_mask */
255 1.1 christos ALL_ONES, /* dst_mask */
256 1.1 christos false, /* pcrel_offset */
257 1.1 christos BFD_RELOC_LARCH_TLS_TPREL64, /* bfd_reloc_code_real_type */
258 1.1 christos NULL), /* adjust_reloc_bits */
259 1.1 christos
260 1.1 christos LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */
261 1.1 christos 0, /* rightshift */
262 1.1 christos 4, /* size */
263 1.1 christos 32, /* bitsize */
264 1.1 christos false, /* pc_relative */
265 1.1 christos 0, /* bitpos */
266 1.1 christos complain_overflow_dont, /* complain_on_overflow */
267 1.1 christos bfd_elf_generic_reloc, /* special_function */
268 1.1 christos "R_LARCH_IRELATIVE", /* name */
269 1.1 christos false, /* partial_inplace */
270 1.1 christos 0, /* src_mask */
271 1.1 christos ALL_ONES, /* dst_mask */
272 1.1 christos false, /* pcrel_offset */
273 1.1 christos BFD_RELOC_NONE, /* undefined? */
274 1.1 christos NULL), /* adjust_reloc_bits */
275 1.1 christos
276 1.1 christos LOONGARCH_EMPTY_HOWTO(13),
277 1.1 christos LOONGARCH_EMPTY_HOWTO(14),
278 1.1 christos LOONGARCH_EMPTY_HOWTO(15),
279 1.1 christos LOONGARCH_EMPTY_HOWTO(16),
280 1.1 christos LOONGARCH_EMPTY_HOWTO(17),
281 1.1 christos LOONGARCH_EMPTY_HOWTO(18),
282 1.1 christos LOONGARCH_EMPTY_HOWTO(19),
283 1.1 christos
284 1.1 christos LOONGARCH_HOWTO (R_LARCH_MARK_LA, /* type (20). */
285 1.1 christos 0, /* rightshift. */
286 1.1 christos 0, /* size. */
287 1.1 christos 0, /* bitsize. */
288 1.1 christos false, /* pc_relative. */
289 1.1 christos 0, /* bitpos. */
290 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
291 1.1 christos bfd_elf_generic_reloc, /* special_function. */
292 1.1 christos "R_LARCH_MARK_LA", /* name. */
293 1.1 christos false, /* partial_inplace. */
294 1.1 christos 0, /* src_mask. */
295 1.1 christos 0, /* dst_mask. */
296 1.1 christos false, /* pcrel_offset */
297 1.1 christos BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */
298 1.1 christos NULL), /* adjust_reloc_bits */
299 1.1 christos
300 1.1 christos LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
301 1.1 christos 0, /* rightshift. */
302 1.1 christos 0, /* size. */
303 1.1 christos 0, /* bitsize. */
304 1.1 christos false, /* pc_relative. */
305 1.1 christos 0, /* bitpos. */
306 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
307 1.1 christos bfd_elf_generic_reloc, /* special_function. */
308 1.1 christos "R_LARCH_MARK_PCREL", /* name. */
309 1.1 christos false, /* partial_inplace. */
310 1.1 christos 0, /* src_mask. */
311 1.1 christos 0, /* dst_mask. */
312 1.1 christos false, /* pcrel_offset */
313 1.1 christos BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */
314 1.1 christos NULL), /* adjust_reloc_bits */
315 1.1 christos
316 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
317 1.1 christos 2, /* rightshift. */
318 1.1 christos 4, /* size. */
319 1.1 christos 32, /* bitsize. */
320 1.1 christos true /* FIXME: somewhat use this. */, /* pc_relative. */
321 1.1 christos 0, /* bitpos. */
322 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
323 1.1 christos bfd_elf_generic_reloc, /* special_function. */
324 1.1 christos "R_LARCH_SOP_PUSH_PCREL", /* name. */
325 1.1 christos false, /* partial_inplace. */
326 1.1 christos 0x03ffffff, /* src_mask. */
327 1.1 christos 0x03ffffff, /* dst_mask. */
328 1.1 christos false, /* pcrel_offset */
329 1.1 christos BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */
330 1.1 christos NULL), /* adjust_reloc_bits */
331 1.1 christos
332 1.1 christos /* type 23-37. */
333 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
334 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP),
335 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL),
336 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL),
337 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT),
338 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD),
339 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL),
340 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT),
341 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_NOT),
342 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_SUB),
343 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_SL),
344 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_SR),
345 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_ADD),
346 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_AND),
347 1.1 christos LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
348 1.1 christos
349 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */
350 1.1 christos 0, /* rightshift. */
351 1.1 christos 4, /* size. */
352 1.1 christos 5, /* bitsize. */
353 1.1 christos false, /* pc_relative. */
354 1.1 christos 10, /* bitpos. */
355 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
356 1.1 christos bfd_elf_generic_reloc, /* special_function. */
357 1.1 christos "R_LARCH_SOP_POP_32_S_10_5", /* name. */
358 1.1 christos false, /* partial_inplace. */
359 1.1 christos 0, /* src_mask */
360 1.1 christos 0x7c00, /* dst_mask */
361 1.1 christos false, /* pcrel_offset */
362 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_10_5, /* bfd_reloc_code_real_type */
363 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
364 1.1 christos
365 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */
366 1.1 christos 0, /* rightshift. */
367 1.1 christos 4, /* size. */
368 1.1 christos 12, /* bitsize. */
369 1.1 christos false, /* pc_relative. */
370 1.1 christos 10, /* bitpos. */
371 1.1 christos complain_overflow_unsigned, /* complain_on_overflow. */
372 1.1 christos bfd_elf_generic_reloc, /* special_function. */
373 1.1 christos "R_LARCH_SOP_POP_32_U_10_12", /* name. */
374 1.1 christos false, /* partial_inplace. */
375 1.1 christos 0, /* src_mask */
376 1.1 christos 0x3ffc00, /* dst_mask */
377 1.1 christos false, /* pcrel_offset */
378 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_U_10_12, /* bfd_reloc_code_real_type */
379 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
380 1.1 christos
381 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */
382 1.1 christos 0, /* rightshift. */
383 1.1 christos 4, /* size. */
384 1.1 christos 12, /* bitsize. */
385 1.1 christos false, /* pc_relative. */
386 1.1 christos 10, /* bitpos. */
387 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
388 1.1 christos bfd_elf_generic_reloc, /* special_function. */
389 1.1 christos "R_LARCH_SOP_POP_32_S_10_12", /* name. */
390 1.1 christos false, /* partial_inplace. */
391 1.1 christos 0, /* src_mask */
392 1.1 christos 0x3ffc00, /* dst_mask */
393 1.1 christos false, /* pcrel_offset */
394 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_10_12, /* bfd_reloc_code_real_type */
395 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
396 1.1 christos
397 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */
398 1.1 christos 0, /* rightshift. */
399 1.1 christos 4, /* size. */
400 1.1 christos 16, /* bitsize. */
401 1.1 christos false, /* pc_relative. */
402 1.1 christos 10, /* bitpos. */
403 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
404 1.1 christos bfd_elf_generic_reloc, /* special_function. */
405 1.1 christos "R_LARCH_SOP_POP_32_S_10_16", /* name. */
406 1.1 christos false, /* partial_inplace. */
407 1.1 christos 0, /* src_mask */
408 1.1 christos 0x3fffc00, /* dst_mask */
409 1.1 christos false, /* pcrel_offset */
410 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_10_16, /* bfd_reloc_code_real_type */
411 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
412 1.1 christos
413 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */
414 1.1 christos 2, /* rightshift. */
415 1.1 christos 4, /* size. */
416 1.1 christos 16, /* bitsize. */
417 1.1 christos false, /* pc_relative. */
418 1.1 christos 10, /* bitpos. */
419 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
420 1.1 christos bfd_elf_generic_reloc, /* special_function. */
421 1.1 christos "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */
422 1.1 christos false, /* partial_inplace. */
423 1.1 christos 0, /* src_mask */
424 1.1 christos 0x3fffc00, /* dst_mask */
425 1.1 christos false, /* pcrel_offset */
426 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2, /* bfd_reloc_code_real_type */
427 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
428 1.1 christos
429 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */
430 1.1 christos 0, /* rightshift. */
431 1.1 christos 4, /* size. */
432 1.1 christos 20, /* bitsize. */
433 1.1 christos false, /* pc_relative. */
434 1.1 christos 5, /* bitpos. */
435 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
436 1.1 christos bfd_elf_generic_reloc, /* special_function. */
437 1.1 christos "R_LARCH_SOP_POP_32_S_5_20", /* name. */
438 1.1 christos false, /* partial_inplace. */
439 1.1 christos 0, /* src_mask */
440 1.1 christos 0x1ffffe0, /* dst_mask */
441 1.1 christos false, /* pcrel_offset */
442 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_5_20, /* bfd_reloc_code_real_type */
443 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
444 1.1 christos
445 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
446 1.1 christos /* type (44). */
447 1.1 christos 2, /* rightshift. */
448 1.1 christos 4, /* size. */
449 1.1 christos 21, /* bitsize. */
450 1.1 christos false, /* pc_relative. */
451 1.1 christos 0, /* bitpos. */
452 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
453 1.1 christos bfd_elf_generic_reloc, /* special_function. */
454 1.1 christos "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */
455 1.1 christos false, /* partial_inplace. */
456 1.1 christos 0xfc0003e0, /* src_mask */
457 1.1 christos 0xfc0003e0, /* dst_mask */
458 1.1 christos false, /* pcrel_offset */
459 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
460 1.1 christos /* bfd_reloc_code_real_type */
461 1.1 christos loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */
462 1.1 christos
463 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
464 1.1 christos 2, /* rightshift. */
465 1.1 christos 4, /* size. */
466 1.1 christos 26, /* bitsize. */
467 1.1 christos false, /* pc_relative. */
468 1.1 christos 0, /* bitpos. */
469 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
470 1.1 christos bfd_elf_generic_reloc, /* special_function. */
471 1.1 christos "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", /* name. */
472 1.1 christos false, /* partial_inplace. */
473 1.1 christos 0xfc000000, /* src_mask */
474 1.1 christos 0xfc000000, /* dst_mask */
475 1.1 christos false, /* pcrel_offset */
476 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
477 1.1 christos /* bfd_reloc_code_real_type */
478 1.1 christos loongarch_adjust_reloc_bits_l16_h10), /* adjust_reloc_bits */
479 1.1 christos
480 1.1 christos LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
481 1.1 christos 0, /* rightshift. */
482 1.1 christos 4, /* size. */
483 1.1 christos 32, /* bitsize. */
484 1.1 christos false, /* pc_relative. */
485 1.1 christos 0, /* bitpos. */
486 1.1 christos complain_overflow_unsigned, /* complain_on_overflow. */
487 1.1 christos bfd_elf_generic_reloc, /* special_function. */
488 1.1 christos "R_LARCH_SOP_POP_32_S_U", /* name. */
489 1.1 christos false, /* partial_inplace. */
490 1.1 christos 0xffffffff00000000, /* src_mask */
491 1.1 christos 0x00000000ffffffff, /* dst_mask */
492 1.1 christos false, /* pcrel_offset */
493 1.1 christos BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */
494 1.1 christos loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
495 1.1 christos
496 1.1 christos LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
497 1.1 christos 0, /* rightshift. */
498 1.1 christos 4, /* size. */
499 1.1 christos 8, /* bitsize. */
500 1.1 christos false, /* pc_relative. */
501 1.1 christos 0, /* bitpos. */
502 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
503 1.1 christos bfd_elf_generic_reloc, /* special_function. */
504 1.1 christos "R_LARCH_ADD8", /* name. */
505 1.1 christos false, /* partial_inplace. */
506 1.1 christos 0, /* src_mask */
507 1.1 christos ALL_ONES, /* dst_mask */
508 1.1 christos false, /* pcrel_offset */
509 1.1 christos BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type */
510 1.1 christos NULL), /* adjust_reloc_bits */
511 1.1 christos
512 1.1 christos LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
513 1.1 christos 0, /* rightshift. */
514 1.1 christos 4, /* size. */
515 1.1 christos 16, /* bitsize. */
516 1.1 christos false, /* pc_relative. */
517 1.1 christos 0, /* bitpos. */
518 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
519 1.1 christos bfd_elf_generic_reloc, /* special_function. */
520 1.1 christos "R_LARCH_ADD16", /* name. */
521 1.1 christos false, /* partial_inplace. */
522 1.1 christos 0, /* src_mask */
523 1.1 christos ALL_ONES, /* dst_mask */
524 1.1 christos false, /* pcrel_offset */
525 1.1 christos BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type */
526 1.1 christos NULL), /* adjust_reloc_bits */
527 1.1 christos
528 1.1 christos LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
529 1.1 christos 0, /* rightshift. */
530 1.1 christos 4, /* size. */
531 1.1 christos 24, /* bitsize. */
532 1.1 christos false, /* pc_relative. */
533 1.1 christos 0, /* bitpos. */
534 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
535 1.1 christos bfd_elf_generic_reloc, /* special_function. */
536 1.1 christos "R_LARCH_ADD24", /* name. */
537 1.1 christos false, /* partial_inplace. */
538 1.1 christos 0, /* src_mask */
539 1.1 christos ALL_ONES, /* dst_mask */
540 1.1 christos false, /* pcrel_offset */
541 1.1 christos BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type */
542 1.1 christos NULL), /* adjust_reloc_bits */
543 1.1 christos
544 1.1 christos LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
545 1.1 christos 0, /* rightshift. */
546 1.1 christos 4, /* size. */
547 1.1 christos 32, /* bitsize. */
548 1.1 christos false, /* pc_relative. */
549 1.1 christos 0, /* bitpos. */
550 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
551 1.1 christos bfd_elf_generic_reloc, /* special_function. */
552 1.1 christos "R_LARCH_ADD32", /* name. */
553 1.1 christos false, /* partial_inplace. */
554 1.1 christos 0, /* src_mask */
555 1.1 christos ALL_ONES, /* dst_mask */
556 1.1 christos false, /* pcrel_offset */
557 1.1 christos BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type */
558 1.1 christos NULL), /* adjust_reloc_bits */
559 1.1 christos
560 1.1 christos LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
561 1.1 christos 0, /* rightshift. */
562 1.1 christos 8, /* size. */
563 1.1 christos 64, /* bitsize. */
564 1.1 christos false, /* pc_relative. */
565 1.1 christos 0, /* bitpos. */
566 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
567 1.1 christos bfd_elf_generic_reloc, /* special_function. */
568 1.1 christos "R_LARCH_ADD64", /* name. */
569 1.1 christos false, /* partial_inplace. */
570 1.1 christos 0, /* src_mask */
571 1.1 christos ALL_ONES, /* dst_mask */
572 1.1 christos false, /* pcrel_offset */
573 1.1 christos BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type */
574 1.1 christos NULL), /* adjust_reloc_bits */
575 1.1 christos
576 1.1 christos LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
577 1.1 christos 0, /* rightshift. */
578 1.1 christos 4, /* size. */
579 1.1 christos 8, /* bitsize. */
580 1.1 christos false, /* pc_relative. */
581 1.1 christos 0, /* bitpos. */
582 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
583 1.1 christos bfd_elf_generic_reloc, /* special_function. */
584 1.1 christos "R_LARCH_SUB8", /* name. */
585 1.1 christos false, /* partial_inplace. */
586 1.1 christos 0, /* src_mask */
587 1.1 christos ALL_ONES, /* dst_mask */
588 1.1 christos false, /* pcrel_offset */
589 1.1 christos BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type */
590 1.1 christos NULL), /* adjust_reloc_bits */
591 1.1 christos
592 1.1 christos LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
593 1.1 christos 0, /* rightshift. */
594 1.1 christos 4, /* size. */
595 1.1 christos 16, /* bitsize. */
596 1.1 christos false, /* pc_relative. */
597 1.1 christos 0, /* bitpos. */
598 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
599 1.1 christos bfd_elf_generic_reloc, /* special_function. */
600 1.1 christos "R_LARCH_SUB16", /* name. */
601 1.1 christos false, /* partial_inplace. */
602 1.1 christos 0, /* src_mask */
603 1.1 christos ALL_ONES, /* dst_mask */
604 1.1 christos false, /* pcrel_offset */
605 1.1 christos BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type */
606 1.1 christos NULL), /* adjust_reloc_bits */
607 1.1 christos
608 1.1 christos LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
609 1.1 christos 0, /* rightshift. */
610 1.1 christos 4, /* size. */
611 1.1 christos 24, /* bitsize. */
612 1.1 christos false, /* pc_relative. */
613 1.1 christos 0, /* bitpos. */
614 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
615 1.1 christos bfd_elf_generic_reloc, /* special_function. */
616 1.1 christos "R_LARCH_SUB24", /* name. */
617 1.1 christos false, /* partial_inplace. */
618 1.1 christos 0, /* src_mask */
619 1.1 christos ALL_ONES, /* dst_mask */
620 1.1 christos false, /* pcrel_offset */
621 1.1 christos BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type */
622 1.1 christos NULL), /* adjust_reloc_bits */
623 1.1 christos
624 1.1 christos LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
625 1.1 christos 0, /* rightshift. */
626 1.1 christos 4, /* size. */
627 1.1 christos 32, /* bitsize. */
628 1.1 christos false, /* pc_relative. */
629 1.1 christos 0, /* bitpos. */
630 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
631 1.1 christos bfd_elf_generic_reloc, /* special_function. */
632 1.1 christos "R_LARCH_SUB32", /* name. */
633 1.1 christos false, /* partial_inplace. */
634 1.1 christos 0, /* src_mask */
635 1.1 christos ALL_ONES, /* dst_mask */
636 1.1 christos false, /* pcrel_offset */
637 1.1 christos BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type */
638 1.1 christos NULL), /* adjust_reloc_bits */
639 1.1 christos
640 1.1 christos LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
641 1.1 christos 0, /* rightshift. */
642 1.1 christos 8, /* size. */
643 1.1 christos 64, /* bitsize. */
644 1.1 christos false, /* pc_relative. */
645 1.1 christos 0, /* bitpos. */
646 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
647 1.1 christos bfd_elf_generic_reloc, /* special_function. */
648 1.1 christos "R_LARCH_SUB64", /* name. */
649 1.1 christos false, /* partial_inplace. */
650 1.1 christos 0, /* src_mask */
651 1.1 christos ALL_ONES, /* dst_mask */
652 1.1 christos false, /* pcrel_offset */
653 1.1 christos BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type */
654 1.1 christos NULL), /* adjust_reloc_bits */
655 1.1 christos
656 1.1 christos LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
657 1.1 christos 0, /* rightshift. */
658 1.1 christos 0, /* size. */
659 1.1 christos 0, /* bitsize. */
660 1.1 christos false, /* pc_relative. */
661 1.1 christos 0, /* bitpos. */
662 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
663 1.1 christos bfd_elf_generic_reloc, /* special_function. */
664 1.1 christos "R_LARCH_GNU_VTINHERIT", /* name. */
665 1.1 christos false, /* partial_inplace. */
666 1.1 christos 0, /* src_mask */
667 1.1 christos 0, /* dst_mask */
668 1.1 christos false, /* pcrel_offset */
669 1.1 christos BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
670 1.1 christos NULL), /* adjust_reloc_bits */
671 1.1 christos
672 1.1 christos LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
673 1.1 christos 0, /* rightshift. */
674 1.1 christos 0, /* size. */
675 1.1 christos 0, /* bitsize. */
676 1.1 christos false, /* pc_relative. */
677 1.1 christos 0, /* bitpos. */
678 1.1 christos complain_overflow_signed, /* complain_on_overflow. */
679 1.1 christos NULL, /* special_function. */
680 1.1 christos "R_LARCH_GNU_VTENTRY", /* name. */
681 1.1 christos false, /* partial_inplace. */
682 1.1 christos 0, /* src_mask */
683 1.1 christos 0, /* dst_mask */
684 1.1 christos false, /* pcrel_offset */
685 1.1 christos BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
686 1.1 christos NULL), /* adjust_reloc_bits */
687 1.1 christos };
688 1.1 christos
689 1.1 christos reloc_howto_type *
690 1.1 christos loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
691 1.1 christos {
692 1.1 christos if(r_type < R_LARCH_count)
693 1.1 christos {
694 1.1 christos /* For search table fast. */
695 1.1 christos BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
696 1.1 christos
697 1.1 christos if (loongarch_howto_table[r_type].howto.type == r_type)
698 1.1 christos return (reloc_howto_type *)&loongarch_howto_table[r_type];
699 1.1 christos
700 1.1 christos BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type);
701 1.1 christos
702 1.1 christos for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
703 1.1 christos if (loongarch_howto_table[i].howto.type == r_type)
704 1.1 christos return (reloc_howto_type *)&loongarch_howto_table[i];
705 1.1 christos }
706 1.1 christos
707 1.1 christos (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
708 1.1 christos abfd, r_type);
709 1.1 christos bfd_set_error (bfd_error_bad_value);
710 1.1 christos return NULL;
711 1.1 christos }
712 1.1 christos
713 1.1 christos reloc_howto_type *
714 1.1 christos loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
715 1.1 christos {
716 1.1 christos BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
717 1.1 christos
718 1.1 christos for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
719 1.1 christos if (loongarch_howto_table[i].howto.name
720 1.1 christos && strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0)
721 1.1 christos return (reloc_howto_type *)&loongarch_howto_table[i];
722 1.1 christos
723 1.1 christos (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"),
724 1.1 christos abfd, r_name);
725 1.1 christos bfd_set_error (bfd_error_bad_value);
726 1.1 christos
727 1.1 christos return NULL;
728 1.1 christos }
729 1.1 christos
730 1.1 christos /* Cost so much. */
731 1.1 christos reloc_howto_type *
732 1.1 christos loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
733 1.1 christos bfd_reloc_code_real_type code)
734 1.1 christos {
735 1.1 christos BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
736 1.1 christos
737 1.1 christos for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
738 1.1 christos if (loongarch_howto_table[i].bfd_type == code)
739 1.1 christos return (reloc_howto_type *)&loongarch_howto_table[i];
740 1.1 christos
741 1.1 christos (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"),
742 1.1 christos abfd, code);
743 1.1 christos bfd_set_error (bfd_error_bad_value);
744 1.1 christos
745 1.1 christos return NULL;
746 1.1 christos }
747 1.1 christos
748 1.1 christos #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
749 1.1 christos (~((((bfd_vma)0x1) << (bitsize)) - 1))
750 1.1 christos
751 1.1 christos /* Adjust val to perform insn
752 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_S_10_5
753 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_S_10_12
754 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_U_10_12
755 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_S_10_16
756 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
757 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_S_5_20
758 1.1 christos * BFD_RELOC_LARCH_SOP_POP_32_U.
759 1.1 christos */
760 1.1 christos
761 1.1 christos bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
762 1.1 christos {
763 1.1 christos bfd_vma val = *fix_val;
764 1.1 christos /* Check val low bits if rightshift != 0, before rightshift */
765 1.1 christos if (howto->rightshift
766 1.1 christos && (((0x1UL << howto->rightshift) - 1) & val))
767 1.1 christos return false;
768 1.1 christos
769 1.1 christos int bitsize = howto->bitsize + howto->rightshift;
770 1.1 christos
771 1.1 christos /* Return false if overflow. */
772 1.1 christos if (howto->complain_on_overflow == complain_overflow_signed)
773 1.1 christos {
774 1.1 christos bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
775 1.1 christos /* If val < 0. */
776 1.1 christos if (sig_bit)
777 1.1 christos {
778 1.1 christos if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
779 1.1 christos != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
780 1.1 christos return false;
781 1.1 christos }
782 1.1 christos else
783 1.1 christos {
784 1.1 christos if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
785 1.1 christos return false;
786 1.1 christos }
787 1.1 christos }
788 1.1 christos else if (howto->complain_on_overflow == complain_overflow_unsigned)
789 1.1 christos {
790 1.1 christos if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
791 1.1 christos return false;
792 1.1 christos }
793 1.1 christos else
794 1.1 christos return false;
795 1.1 christos
796 1.1 christos /* Perform insn bits field. */
797 1.1 christos val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
798 1.1 christos val <<= howto->bitpos;
799 1.1 christos
800 1.1 christos *fix_val = val;
801 1.1 christos
802 1.1 christos return true;
803 1.1 christos }
804 1.1 christos
805 1.1 christos /* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2. */
806 1.1 christos bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
807 1.1 christos bfd_vma *fix_val)
808 1.1 christos {
809 1.1 christos bfd_vma val = *fix_val;
810 1.1 christos /* Check val low bits if rightshift != 0, before rightshift */
811 1.1 christos if (howto->rightshift
812 1.1 christos && (((0x1UL << howto->rightshift) - 1) & val))
813 1.1 christos return false;
814 1.1 christos
815 1.1 christos /* Return false if overflow. */
816 1.1 christos if (howto->complain_on_overflow != complain_overflow_signed)
817 1.1 christos return false;
818 1.1 christos
819 1.1 christos int bitsize = howto->bitsize + howto->rightshift;
820 1.1 christos bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
821 1.1 christos /* If val < 0. */
822 1.1 christos if (sig_bit)
823 1.1 christos {
824 1.1 christos if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
825 1.1 christos != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
826 1.1 christos return false;
827 1.1 christos }
828 1.1 christos else
829 1.1 christos {
830 1.1 christos if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
831 1.1 christos return false;
832 1.1 christos }
833 1.1 christos
834 1.1 christos /* Perform insn bits field. */
835 1.1 christos val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
836 1.1 christos
837 1.1 christos /* Perform insn bits field. 20:16>>16, 15:0<<10 */
838 1.1 christos val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
839 1.1 christos
840 1.1 christos *fix_val = val;
841 1.1 christos
842 1.1 christos return true;
843 1.1 christos }
844 1.1 christos
845 1.1 christos /* Reloc type R_LARCH_SOP_POP_32_S_0_10_10_16_S2. */
846 1.1 christos bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
847 1.1 christos bfd_vma *fix_val)
848 1.1 christos {
849 1.1 christos bfd_vma val = *fix_val;
850 1.1 christos /* Check val low bits if rightshift != 0, before rightshift */
851 1.1 christos if (howto->rightshift
852 1.1 christos && (((0x1UL << howto->rightshift) - 1) & val))
853 1.1 christos return false;
854 1.1 christos
855 1.1 christos /* Return false if overflow. */
856 1.1 christos if (howto->complain_on_overflow != complain_overflow_signed)
857 1.1 christos return false;
858 1.1 christos
859 1.1 christos int bitsize = howto->bitsize + howto->rightshift;
860 1.1 christos bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
861 1.1 christos /* If val < 0. */
862 1.1 christos if (sig_bit)
863 1.1 christos {
864 1.1 christos if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
865 1.1 christos != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
866 1.1 christos return false;
867 1.1 christos }
868 1.1 christos else
869 1.1 christos {
870 1.1 christos if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
871 1.1 christos return false;
872 1.1 christos }
873 1.1 christos
874 1.1 christos /* Perform insn bits field. */
875 1.1 christos val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
876 1.1 christos
877 1.1 christos /* Perform insn bits field. 25:16>>16, 15:0<<10 */
878 1.1 christos val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
879 1.1 christos
880 1.1 christos *fix_val = val;
881 1.1 christos
882 1.1 christos return true;
883 1.1 christos }
884 1.1 christos
885 1.1 christos bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
886 1.1 christos bfd_vma *fix_val)
887 1.1 christos {
888 1.1 christos BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
889 1.1 christos return ((loongarch_reloc_howto_type *)
890 1.1 christos howto)->adjust_reloc_bits(howto, fix_val);
891 1.1 christos }
892