]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-ft32.c
as_bad_subtract
[thirdparty/binutils-gdb.git] / gas / config / tc-ft32.c
CommitLineData
3f8107ab 1/* tc-ft32.c -- Assemble code for ft32
250d07de 2 Copyright (C) 2008-2021 Free Software Foundation, Inc.
3f8107ab
AM
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
20
21/* Contributed by Anthony Green <green@spindazzle.org>. */
22
23#include "as.h"
24#include "safe-ctype.h"
25#include "opcode/ft32.h"
26
27extern const ft32_opc_info_t ft32_opc_info[128];
28
81b42bca
JB
29/* See md_parse_option() for meanings of these options. */
30static char norelax; /* True if -norelax switch seen. */
31
3f8107ab
AM
32const char comment_chars[] = "#";
33const char line_separator_chars[] = ";";
34const char line_comment_chars[] = "#";
35
36static int pending_reloc;
629310ab 37static htab_t opcode_hash_control;
3f8107ab
AM
38
39static valueT md_chars_to_number (char * buf, int n);
40
41const pseudo_typeS md_pseudo_table[] =
42{
43 {0, 0, 0}
44};
45
46const char FLT_CHARS[] = "rRsSfFdDxXpP";
47const char EXP_CHARS[] = "eE";
48
49/* This function is called once, at assembler startup time. It sets
50 up the hash table with all the opcodes in it, and also initializes
51 some aliases for compatibility with other assemblers. */
52
53void
54md_begin (void)
55{
56 const ft32_opc_info_t *opcode;
629310ab 57 opcode_hash_control = str_htab_create ();
3f8107ab
AM
58
59 /* Insert names into hash table. */
60 for (opcode = ft32_opc_info; opcode->name; opcode++)
fe0e921f 61 str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
3f8107ab
AM
62
63 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
81b42bca
JB
64 if (!norelax)
65 linkrelax = 1;
3f8107ab
AM
66}
67
68/* Parse an expression and then restore the input line pointer. */
69
70static char *
71parse_exp_save_ilp (char *s, expressionS *op)
72{
73 char *save = input_line_pointer;
74
75 input_line_pointer = s;
76 expression (op);
77 s = input_line_pointer;
78 input_line_pointer = save;
79 return s;
80}
81
82static int
83parse_condition (char **ptr)
84{
85 char *s = *ptr;
81b42bca
JB
86 static const struct
87 {
e0471c16 88 const char *name;
3f8107ab 89 int bits;
81b42bca
JB
90 }
91 ccs[] =
92 {
3f8107ab
AM
93 { "gt," , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
94 { "gte," , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
95 { "lt," , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
96 { "lte," , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
97 { "a," , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
98 { "ae," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
99 { "be," , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
100 { "b," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
101 { "nz," , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
102 { "z," , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
103 { "nc," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
104 { "c," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
105 { "no," , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
106 { "o," , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
107 { "ns," , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
108 { "s," , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
109 { NULL, 0}
110 }, *pc;
111
112 for (pc = ccs; pc->name; pc++)
113 {
114 if (memcmp(pc->name, s, strlen(pc->name)) == 0)
115 {
116 *ptr += strlen(pc->name) - 1;
117 return pc->bits;
118 }
119 }
120 return -1;
121}
122
123static int
124parse_decimal (char **ptr)
125{
126 int r = 0;
127 char *s = *ptr;
128
129 while (('0' <= *s) && (*s <= '9'))
130 {
131 r *= 10;
132 r += (*s++ - '0');
133 }
134 *ptr = s;
135 return r;
136}
137
138static int
139parse_register_operand (char **ptr)
140{
141 int reg;
142 char *s = *ptr;
143
144 if (*s != '$')
145 {
146 as_bad (_("expecting register"));
147 ignore_rest_of_line ();
148 return -1;
149 }
150 if ((s[1] == 's') && (s[2] == 'p'))
151 {
152 reg = 31;
153 }
154 else if ((s[1] == 'c') && (s[2] == 'c'))
155 {
156 reg = 30;
157 }
158 else if ((s[1] == 'f') && (s[2] == 'p'))
159 {
160 reg = 29;
161 }
162 else if (s[1] == 'r')
163 {
164 reg = s[2] - '0';
165 if ((reg < 0) || (reg > 9))
166 {
167 as_bad (_("illegal register number"));
168 ignore_rest_of_line ();
169 return -1;
170 }
171 if ((reg == 1) || (reg == 2) || (reg == 3))
172 {
173 int r2 = s[3] - '0';
174 if ((r2 >= 0) && (r2 <= 9))
175 {
176 reg = (reg * 10) + r2;
177 *ptr += 1;
178 }
179 }
180 }
181 else
182 {
183 as_bad (_("illegal register number"));
184 ignore_rest_of_line ();
185 return -1;
186 }
187
188 *ptr += 3;
189
190 return reg;
191}
192
193/* This is the guts of the machine-dependent assembler. STR points to
194 a machine dependent instruction. This function is supposed to emit
195 the frags/bytes it assembles to. */
196
197void
198md_assemble (char *str)
199{
200 char *op_start;
201 char *op_end;
3f8107ab
AM
202 ft32_opc_info_t *opcode;
203 char *output;
204 int idx = 0;
205 char pend;
3f8107ab 206 int nlen = 0;
3f8107ab
AM
207 unsigned int b;
208 int f;
3f8107ab 209 expressionS arg;
5b7c81bd 210 bool fixed = false;
81b42bca 211 unsigned int sc;
5b7c81bd 212 bool can_sc;
3f8107ab
AM
213
214 /* Drop leading whitespace. */
215 while (*str == ' ')
216 str++;
217
218 /* Find the op code end. */
219 op_start = str;
220 for (op_end = str;
81b42bca
JB
221 *op_end
222 && !is_end_of_line[*op_end & 0xff]
223 && *op_end != ' '
224 && *op_end != '.';
3f8107ab
AM
225 op_end++)
226 nlen++;
227
228 pend = *op_end;
229 *op_end = 0;
230
231 if (nlen == 0)
232 as_bad (_("can't find opcode "));
233
629310ab 234 opcode = (ft32_opc_info_t *) str_hash_find (opcode_hash_control, op_start);
3f8107ab
AM
235 *op_end = pend;
236
237 if (opcode == NULL)
238 {
239 as_bad (_("unknown opcode %s"), op_start);
240 return;
241 }
242
243 b = opcode->bits;
244 f = opcode->fields;
245
246 if (opcode->dw)
247 {
248 int dw;
81b42bca 249
3f8107ab
AM
250 if (*op_end == '.')
251 {
252 switch (op_end[1])
253 {
254 case 'b':
255 dw = 0;
256 break;
257 case 's':
258 dw = 1;
259 break;
260 case 'l':
261 dw = 2;
262 break;
263 default:
264 as_bad (_("unknown width specifier '.%c'"), op_end[1]);
265 return;
266 }
267 op_end += 2;
268 }
269 else
270 {
271 dw = 2; /* default is ".l" */
272 }
273 b |= dw << FT32_FLD_DW_BIT;
274 }
275
276 while (ISSPACE (*op_end))
277 op_end++;
278
279 output = frag_more (4);
280
281 while (f)
282 {
283 int lobit = f & -f;
81b42bca 284
3f8107ab
AM
285 if (f & lobit)
286 {
287 switch (lobit)
81b42bca
JB
288 {
289 case FT32_FLD_CBCRCV:
290 b |= parse_condition( &op_end);
291 break;
292 case FT32_FLD_CB:
293 b |= parse_decimal (&op_end) << FT32_FLD_CB_BIT;
294 break;
295 case FT32_FLD_R_D:
296 b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT;
297 break;
298 case FT32_FLD_CR:
299 b |= (parse_register_operand (&op_end) - 28) << FT32_FLD_CR_BIT;
300 break;
301 case FT32_FLD_CV:
302 b |= parse_decimal (&op_end) << FT32_FLD_CV_BIT;
303 break;
304 case FT32_FLD_R_1:
305 b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT;
306 break;
307 case FT32_FLD_RIMM:
308 if (*op_end == '$')
309 {
310 b |= parse_register_operand (&op_end) << FT32_FLD_RIMM_BIT;
311 }
312 else
313 {
314 b |= 0x400 << FT32_FLD_RIMM_BIT;
315 op_end = parse_exp_save_ilp (op_end, &arg);
5b7c81bd 316 fixed = true;
81b42bca
JB
317 fix_new_exp (frag_now,
318 (output - frag_now->fr_literal),
319 2,
320 &arg,
321 0,
322 BFD_RELOC_FT32_10);
323 }
324 break;
325 case FT32_FLD_R_2:
326 b |= parse_register_operand (&op_end) << FT32_FLD_R_2_BIT;
327 break;
328 case FT32_FLD_K20:
329 op_end = parse_exp_save_ilp (op_end, &arg);
5b7c81bd 330 fixed = true;
81b42bca
JB
331 fix_new_exp (frag_now,
332 (output - frag_now->fr_literal),
333 3,
334 &arg,
335 0,
336 BFD_RELOC_FT32_20);
337 break;
338 case FT32_FLD_PA:
339 op_end = parse_exp_save_ilp (op_end, &arg);
5b7c81bd 340 fixed = true;
81b42bca
JB
341 fix_new_exp (frag_now,
342 (output - frag_now->fr_literal),
343 3,
344 &arg,
345 0,
346 BFD_RELOC_FT32_18);
347 break;
348 case FT32_FLD_AA:
349 op_end = parse_exp_save_ilp (op_end, &arg);
5b7c81bd 350 fixed = true;
81b42bca
JB
351 fix_new_exp (frag_now,
352 (output - frag_now->fr_literal),
353 3,
354 &arg,
355 0,
356 BFD_RELOC_FT32_17);
357 break;
358 case FT32_FLD_K16:
359 op_end = parse_exp_save_ilp (op_end, &arg);
5b7c81bd 360 fixed = true;
81b42bca
JB
361 fix_new_exp (frag_now,
362 (output - frag_now->fr_literal),
363 2,
364 &arg,
365 0,
366 BFD_RELOC_16);
367 break;
368 case FT32_FLD_K15:
369 op_end = parse_exp_save_ilp (op_end, &arg);
370 if (arg.X_add_number & 0x80)
371 arg.X_add_number ^= 0x7f00;
5b7c81bd 372 fixed = true;
81b42bca
JB
373 fix_new_exp (frag_now,
374 (output - frag_now->fr_literal),
375 2,
376 &arg,
377 0,
378 BFD_RELOC_FT32_15);
379 break;
380 case FT32_FLD_R_D_POST:
381 b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT;
382 break;
383 case FT32_FLD_R_1_POST:
384 b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT;
385 break;
386 default:
387 as_bad (_("internal error in argument parsing"));
388 break;
389 }
390
3f8107ab 391 f &= ~lobit;
81b42bca 392
3f8107ab
AM
393 if (f)
394 {
395 while (ISSPACE (*op_end))
396 op_end++;
397
398 if (*op_end != ',')
399 {
400 as_bad (_("expected comma separator"));
401 ignore_rest_of_line ();
402 }
403
404 op_end++;
405 while (ISSPACE (*op_end))
406 op_end++;
407 }
408 }
409 }
81b42bca 410
3f8107ab
AM
411 if (*op_end != 0)
412 as_warn (_("extra stuff on line ignored"));
413
81b42bca
JB
414 can_sc = ft32_shortcode (b, &sc);
415
416 if (!fixed && can_sc)
417 {
418 arg.X_op = O_constant;
419 arg.X_add_number = 0;
420 arg.X_add_symbol = NULL;
421 arg.X_op_symbol = NULL;
422 fix_new_exp (frag_now,
423 (output - frag_now->fr_literal),
424 2,
425 &arg,
426 0,
427 BFD_RELOC_FT32_RELAX);
428 }
429
3f8107ab
AM
430 output[idx++] = 0xff & (b >> 0);
431 output[idx++] = 0xff & (b >> 8);
432 output[idx++] = 0xff & (b >> 16);
433 output[idx++] = 0xff & (b >> 24);
434
3ee6e4fb
NC
435 dwarf2_emit_insn (4);
436
3f8107ab
AM
437 while (ISSPACE (*op_end))
438 op_end++;
439
440 if (*op_end != 0)
441 as_warn ("extra stuff on line ignored");
442
443 if (pending_reloc)
444 as_bad ("Something forgot to clean up\n");
445}
446
447/* Turn a string in input_line_pointer into a floating point constant
448 of type type, and store the appropriate bytes in *LITP. The number
449 of LITTLENUMS emitted is stored in *SIZEP . An error message is
450 returned, or NULL on OK. */
451
6d4af3c2 452const char *
3f8107ab
AM
453md_atof (int type, char *litP, int *sizeP)
454{
455 int prec;
456 LITTLENUM_TYPE words[4];
457 char *t;
458 int i;
459
460 switch (type)
461 {
462 case 'f':
463 prec = 2;
464 break;
465
466 case 'd':
467 prec = 4;
468 break;
469
470 default:
471 *sizeP = 0;
472 return _("bad call to md_atof");
473 }
474
475 t = atof_ieee (input_line_pointer, type, words);
476 if (t)
477 input_line_pointer = t;
478
479 *sizeP = prec * 2;
480
481 for (i = prec - 1; i >= 0; i--)
482 {
483 md_number_to_chars (litP, (valueT) words[i], 2);
484 litP += 2;
485 }
486
487 return NULL;
488}
489\f
490const char *md_shortopts = "";
491
492struct option md_longopts[] =
493{
81b42bca
JB
494#define OPTION_NORELAX (OPTION_MD_BASE)
495 {"norelax", no_argument, NULL, OPTION_NORELAX},
496 {"no-relax", no_argument, NULL, OPTION_NORELAX},
3f8107ab
AM
497 {NULL, no_argument, NULL, 0}
498};
499size_t md_longopts_size = sizeof (md_longopts);
500
501/* We have no target specific options yet, so these next
502 two functions are empty. */
503int
17b9d67d 504md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
3f8107ab 505{
81b42bca
JB
506 switch (c)
507 {
508 case OPTION_NORELAX:
509 norelax = 1;
510 break;
511
512 default:
513 return 0;
514 }
515
516 return 1;
3f8107ab
AM
517}
518
519void
520md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
521{
81b42bca
JB
522 fprintf (stream, _("FT32 options:\n"));
523 fprintf (stream, _("\n\
524-no-relax don't relax relocations\n\
525 \n"));
3f8107ab
AM
526}
527
528/* Convert from target byte order to host byte order. */
529
530static valueT
531md_chars_to_number (char * buf, int n)
532{
533 valueT result = 0;
534 unsigned char * where = (unsigned char *) buf;
535
536 while (n--)
537 {
538 result <<= 8;
539 result |= (where[n] & 255);
540 }
541
542 return result;
543}
81b42bca 544
3f8107ab
AM
545/* Apply a fixup to the object file. */
546
547void
548md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
549 valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
550{
551 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
552 long val = *valP;
553 long newval;
554
81b42bca
JB
555 if (linkrelax && fixP->fx_subsy)
556 {
557 /* For a subtraction relocation expression, generate one
558 of the DIFF relocs, with the value being the difference.
559 Note that a sym1 - sym2 expression is adjusted into a
560 section_start_sym + sym4_offset_from_section_start - sym1
561 expression. fixP->fx_addsy holds the section start symbol,
562 fixP->fx_offset holds sym2's offset, and fixP->fx_subsy
563 holds sym1. Calculate the current difference and write value,
564 but leave fx_offset as is - during relaxation,
565 fx_offset - value gives sym1's value. */
566
567 switch (fixP->fx_r_type)
568 {
569 case BFD_RELOC_32:
570 fixP->fx_r_type = BFD_RELOC_FT32_DIFF32;
571 break;
572 default:
4bf09429 573 as_bad_subtract (fixP);
81b42bca
JB
574 break;
575 }
576
577 val = S_GET_VALUE (fixP->fx_addsy) +
578 fixP->fx_offset - S_GET_VALUE (fixP->fx_subsy);
579 *valP = val;
580
581 fixP->fx_subsy = NULL;
582 }
583
584 /* We don't actually support subtracting a symbol. */
585 if (fixP->fx_subsy != (symbolS *) NULL)
4bf09429 586 as_bad_subtract (fixP);
81b42bca 587
3f8107ab
AM
588 switch (fixP->fx_r_type)
589 {
81b42bca 590 case BFD_RELOC_FT32_DIFF32:
3f8107ab
AM
591 case BFD_RELOC_32:
592 buf[3] = val >> 24;
593 buf[2] = val >> 16;
594 buf[1] = val >> 8;
595 buf[0] = val >> 0;
596 break;
597
598 case BFD_RELOC_16:
599 buf[1] = val >> 8;
600 buf[0] = val >> 0;
601 break;
602
603 case BFD_RELOC_8:
604 *buf = val;
605 break;
606
607 case BFD_RELOC_FT32_10:
608 if (!val)
609 break;
610 newval = md_chars_to_number (buf, 2);
611 newval |= (val & ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT;
612 md_number_to_chars (buf, newval, 2);
613 break;
614
615 case BFD_RELOC_FT32_20:
616 if (!val)
617 break;
618 newval = md_chars_to_number (buf, 3);
619 newval |= val & ((1 << 20) - 1);
620 md_number_to_chars (buf, newval, 3);
621 break;
622
3b4b0a62
JB
623 case BFD_RELOC_FT32_15:
624 if (!val)
625 break;
626 newval = md_chars_to_number (buf, 2);
627 newval |= val & ((1 << 15) - 1);
628 md_number_to_chars (buf, newval, 2);
629 break;
630
3f8107ab
AM
631 case BFD_RELOC_FT32_17:
632 if (!val)
633 break;
634 newval = md_chars_to_number (buf, 3);
635 newval |= val & ((1 << 17) - 1);
636 md_number_to_chars (buf, newval, 3);
637 break;
638
639 case BFD_RELOC_FT32_18:
640 if (!val)
641 break;
642 newval = md_chars_to_number (buf, 4);
643 newval |= (val >> 2) & ((1 << 18) - 1);
644 md_number_to_chars (buf, newval, 4);
645 break;
646
81b42bca
JB
647 case BFD_RELOC_FT32_RELAX:
648 break;
649
3f8107ab
AM
650 default:
651 abort ();
652 }
653
654 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
655 fixP->fx_done = 1;
3f8107ab
AM
656}
657
658void
659md_number_to_chars (char *ptr, valueT use, int nbytes)
660{
661 number_to_chars_littleendian (ptr, use, nbytes);
662}
663
664/* Generate a machine-dependent relocation. */
81b42bca 665
3f8107ab
AM
666arelent *
667tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
668{
669 arelent *relP;
670 bfd_reloc_code_real_type code;
671
672 switch (fixP->fx_r_type)
673 {
674 case BFD_RELOC_32:
675 case BFD_RELOC_16:
676 case BFD_RELOC_8:
677 case BFD_RELOC_FT32_10:
678 case BFD_RELOC_FT32_20:
3b4b0a62 679 case BFD_RELOC_FT32_15:
3f8107ab
AM
680 case BFD_RELOC_FT32_17:
681 case BFD_RELOC_FT32_18:
81b42bca
JB
682 case BFD_RELOC_FT32_RELAX:
683 case BFD_RELOC_FT32_DIFF32:
3f8107ab
AM
684 code = fixP->fx_r_type;
685 break;
686 default:
687 as_bad_where (fixP->fx_file, fixP->fx_line,
81b42bca
JB
688 _("Semantics error. This type of operand can not be "
689 "relocated, it must be an assembly-time constant"));
690 return NULL;
3f8107ab
AM
691 }
692
325801bd 693 relP = XNEW (arelent);
3f8107ab 694 gas_assert (relP != 0);
325801bd 695 relP->sym_ptr_ptr = XNEW (asymbol *);
3f8107ab
AM
696 *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
697 relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
698
699 relP->addend = fixP->fx_offset;
700
701 relP->howto = bfd_reloc_type_lookup (stdoutput, code);
702 if (! relP->howto)
703 {
704 const char *name;
705
706 name = S_GET_NAME (fixP->fx_addsy);
707 if (name == NULL)
708 name = _("<unknown>");
709 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
710 name, bfd_get_reloc_code_name (code));
711 }
712
713 return relP;
714}
81b42bca
JB
715
716/* TC_FORCE_RELOCATION hook */
717
5b7c81bd 718static bool
81b42bca
JB
719relaxable_section (asection *sec)
720{
721 return ((sec->flags & SEC_DEBUGGING) == 0
722 && (sec->flags & SEC_CODE) != 0
723 && (sec->flags & SEC_ALLOC) != 0);
724}
725
726/* Does whatever the xtensa port does. */
727
728int
729ft32_validate_fix_sub (fixS *fix)
730{
731 segT add_symbol_segment, sub_symbol_segment;
732
733 /* The difference of two symbols should be resolved by the assembler when
734 linkrelax is not set. If the linker may relax the section containing
735 the symbols, then an Xtensa DIFF relocation must be generated so that
736 the linker knows to adjust the difference value. */
737 if (!linkrelax || fix->fx_addsy == NULL)
738 return 0;
739
740 /* Make sure both symbols are in the same segment, and that segment is
741 "normal" and relaxable. If the segment is not "normal", then the
742 fix is not valid. If the segment is not "relaxable", then the fix
743 should have been handled earlier. */
744 add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
745 if (! SEG_NORMAL (add_symbol_segment) ||
746 ! relaxable_section (add_symbol_segment))
747 return 0;
748
749 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
750 return (sub_symbol_segment == add_symbol_segment);
751}
752
753/* TC_FORCE_RELOCATION hook */
754
755/* If linkrelax is turned on, and the symbol to relocate
756 against is in a relaxable segment, don't compute the value -
757 generate a relocation instead. */
758
759int
760ft32_force_relocation (fixS *fix)
761{
762 if (linkrelax && fix->fx_addsy
763 && relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
764 {
765 return 1;
766 }
767
768 return generic_force_reloc (fix);
769}
770
5b7c81bd 771bool
81b42bca
JB
772ft32_allow_local_subtract (expressionS * left,
773 expressionS * right,
774 segT section)
775{
776 /* If we are not in relaxation mode, subtraction is OK. */
777 if (!linkrelax)
5b7c81bd 778 return true;
81b42bca
JB
779
780 /* If the symbols are not in a code section then they are OK. */
781 if ((section->flags & SEC_CODE) == 0)
5b7c81bd 782 return true;
81b42bca
JB
783
784 if (left->X_add_symbol == right->X_add_symbol)
5b7c81bd 785 return true;
81b42bca
JB
786
787 /* We have to assume that there may be instructions between the
788 two symbols and that relaxation may increase the distance between
789 them. */
5b7c81bd 790 return false;
81b42bca 791}