[PATCH 5/57][Arm][GAS] Add support for MVE instructions: vmull{b,t}
[binutils-gdb.git] / gas / cgen.c
blob5c4a194f1f9a598121279ff5b71e60135a1b6a30
1 /* GAS interface for targets using CGEN: Cpu tools GENerator.
2 Copyright (C) 1996-2019 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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.
11 GAS is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
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 the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20 #include "as.h"
21 #include <setjmp.h>
22 #include "symcat.h"
23 #include "cgen-desc.h"
24 #include "subsegs.h"
25 #include "cgen.h"
26 #include "dwarf2dbg.h"
28 #include "symbols.h"
30 #ifdef OBJ_COMPLEX_RELC
31 static expressionS * make_right_shifted_expr
32 (expressionS *, const int, const int);
34 static unsigned long gas_cgen_encode_addend
35 (const unsigned long, const unsigned long, const unsigned long, \
36 const unsigned long, const unsigned long, const unsigned long, \
37 const unsigned long);
39 static const char * weak_operand_overflow_check
40 (const expressionS *, const CGEN_OPERAND *);
42 static void queue_fixup_recursively
43 (const int, const int, expressionS *, \
44 const CGEN_MAYBE_MULTI_IFLD *, const int, const int);
46 static int rightshift = 0;
47 #endif
48 static void queue_fixup (int, int, expressionS *);
50 /* Opcode table descriptor, must be set by md_begin. */
52 CGEN_CPU_DESC gas_cgen_cpu_desc;
54 /* Callback to insert a register into the symbol table.
55 A target may choose to let GAS parse the registers.
56 ??? Not currently used. */
58 void
59 cgen_asm_record_register (char *name, int number)
61 /* Use symbol_create here instead of symbol_new so we don't try to
62 output registers into the object file's symbol table. */
63 symbol_table_insert (symbol_create (name, reg_section,
64 number, &zero_address_frag));
67 /* We need to keep a list of fixups. We can't simply generate them as
68 we go, because that would require us to first create the frag, and
69 that would screw up references to ``.''.
71 This is used by cpu's with simple operands. It keeps knowledge of what
72 an `expressionS' is and what a `fixup' is out of CGEN which for the time
73 being is preferable.
75 OPINDEX is the index in the operand table.
76 OPINFO is something the caller chooses to help in reloc determination. */
78 struct fixup
80 int opindex;
81 int opinfo;
82 expressionS exp;
83 struct cgen_maybe_multi_ifield * field;
84 int msb_field_p;
87 static struct fixup fixups[GAS_CGEN_MAX_FIXUPS];
88 static int num_fixups;
90 /* Prepare to parse an instruction.
91 ??? May wish to make this static and delete calls in md_assemble. */
93 void
94 gas_cgen_init_parse (void)
96 num_fixups = 0;
99 /* Queue a fixup. */
101 static void
102 queue_fixup (int opindex, int opinfo, expressionS *expP)
104 /* We need to generate a fixup for this expression. */
105 if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
106 as_fatal (_("too many fixups"));
107 fixups[num_fixups].exp = *expP;
108 fixups[num_fixups].opindex = opindex;
109 fixups[num_fixups].opinfo = opinfo;
110 ++ num_fixups;
113 /* The following functions allow fixup chains to be stored, retrieved,
114 and swapped. They are a generalization of a pre-existing scheme
115 for storing, restoring and swapping fixup chains that was used by
116 the m32r port. The functionality is essentially the same, only
117 instead of only being able to store a single fixup chain, an entire
118 array of fixup chains can be stored. It is the user's responsibility
119 to keep track of how many fixup chains have been stored and which
120 elements of the array they are in.
122 The algorithms used are the same as in the old scheme. Other than the
123 "array-ness" of the whole thing, the functionality is identical to the
124 old scheme.
126 gas_cgen_initialize_saved_fixups_array():
127 Sets num_fixups_in_chain to 0 for each element. Call this from
128 md_begin() if you plan to use these functions and you want the
129 fixup count in each element to be set to 0 initially. This is
130 not necessary, but it's included just in case. It performs
131 the same function for each element in the array of fixup chains
132 that gas_init_parse() performs for the current fixups.
134 gas_cgen_save_fixups (element):
135 element - element number of the array you wish to store the fixups
136 to. No mechanism is built in for tracking what element
137 was last stored to.
139 gas_cgen_restore_fixups (element):
140 element - element number of the array you wish to restore the fixups
141 from.
143 gas_cgen_swap_fixups(int element):
144 element - swap the current fixups with those in this element number.
147 struct saved_fixups
149 struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
150 int num_fixups_in_chain;
153 static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
155 void
156 gas_cgen_initialize_saved_fixups_array (void)
158 int i = 0;
160 while (i < MAX_SAVED_FIXUP_CHAINS)
161 stored_fixups[i++].num_fixups_in_chain = 0;
164 void
165 gas_cgen_save_fixups (int i)
167 if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
169 as_fatal ("index into stored_fixups[] out of bounds");
170 return;
173 stored_fixups[i].num_fixups_in_chain = num_fixups;
174 memcpy (stored_fixups[i].fixup_chain, fixups,
175 sizeof (fixups[0]) * num_fixups);
176 num_fixups = 0;
179 void
180 gas_cgen_restore_fixups (int i)
182 if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
184 as_fatal ("index into stored_fixups[] out of bounds");
185 return;
188 num_fixups = stored_fixups[i].num_fixups_in_chain;
189 memcpy (fixups, stored_fixups[i].fixup_chain,
190 (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
191 stored_fixups[i].num_fixups_in_chain = 0;
194 void
195 gas_cgen_swap_fixups (int i)
197 if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
199 as_fatal ("index into stored_fixups[] out of bounds");
200 return;
203 if (num_fixups == 0)
204 gas_cgen_restore_fixups (i);
206 else if (stored_fixups[i].num_fixups_in_chain == 0)
207 gas_cgen_save_fixups (i);
209 else
211 int tmp;
212 struct fixup tmp_fixup;
214 tmp = stored_fixups[i].num_fixups_in_chain;
215 stored_fixups[i].num_fixups_in_chain = num_fixups;
216 num_fixups = tmp;
218 for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
220 tmp_fixup = stored_fixups[i].fixup_chain [tmp];
221 stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
222 fixups [tmp] = tmp_fixup;
227 /* Default routine to record a fixup.
228 This is a cover function to fix_new.
229 It exists because we record INSN with the fixup.
231 FRAG and WHERE are their respective arguments to fix_new_exp.
232 LENGTH is in bits.
233 OPINFO is something the caller chooses to help in reloc determination.
235 At this point we do not use a bfd_reloc_code_real_type for
236 operands residing in the insn, but instead just use the
237 operand index. This lets us easily handle fixups for any
238 operand type. We pick a BFD reloc type in md_apply_fix. */
240 fixS *
241 gas_cgen_record_fixup (fragS *frag, int where, const CGEN_INSN *insn,
242 int length, const CGEN_OPERAND *operand, int opinfo,
243 symbolS *symbol, offsetT offset)
245 fixS *fixP;
247 /* It may seem strange to use operand->attrs and not insn->attrs here,
248 but it is the operand that has a pc relative relocation. */
249 fixP = fix_new (frag, where, length / 8, symbol, offset,
250 CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
251 (bfd_reloc_code_real_type)
252 ((int) BFD_RELOC_UNUSED
253 + (int) operand->type));
254 fixP->fx_cgen.insn = insn;
255 fixP->fx_cgen.opinfo = opinfo;
256 fixP->fx_cgen.field = NULL;
257 fixP->fx_cgen.msb_field_p = 0;
259 return fixP;
262 /* Default routine to record a fixup given an expression.
263 This is a cover function to fix_new_exp.
264 It exists because we record INSN with the fixup.
266 FRAG and WHERE are their respective arguments to fix_new_exp.
267 LENGTH is in bits.
268 OPINFO is something the caller chooses to help in reloc determination.
270 At this point we do not use a bfd_reloc_code_real_type for
271 operands residing in the insn, but instead just use the
272 operand index. This lets us easily handle fixups for any
273 operand type. We pick a BFD reloc type in md_apply_fix. */
275 fixS *
276 gas_cgen_record_fixup_exp (fragS *frag, int where, const CGEN_INSN *insn,
277 int length, const CGEN_OPERAND *operand, int opinfo,
278 expressionS *exp)
280 fixS *fixP;
282 /* It may seem strange to use operand->attrs and not insn->attrs here,
283 but it is the operand that has a pc relative relocation. */
284 fixP = fix_new_exp (frag, where, length / 8, exp,
285 CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
286 (bfd_reloc_code_real_type)
287 ((int) BFD_RELOC_UNUSED
288 + (int) operand->type));
289 fixP->fx_cgen.insn = insn;
290 fixP->fx_cgen.opinfo = opinfo;
291 fixP->fx_cgen.field = NULL;
292 fixP->fx_cgen.msb_field_p = 0;
294 return fixP;
297 #ifdef OBJ_COMPLEX_RELC
298 static symbolS *
299 expr_build_binary (operatorT op, symbolS * s1, symbolS * s2)
301 expressionS e;
303 e.X_op = op;
304 e.X_add_symbol = s1;
305 e.X_op_symbol = s2;
306 e.X_add_number = 0;
307 return make_expr_symbol (& e);
309 #endif
311 /* Used for communication between the next two procedures. */
312 static jmp_buf expr_jmp_buf;
313 static int expr_jmp_buf_p;
315 /* Callback for cgen interface. Parse the expression at *STRP.
316 The result is an error message or NULL for success (in which case
317 *STRP is advanced past the parsed text).
318 WANT is an indication of what the caller is looking for.
319 If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match
320 a table entry with the insn, reset the queued fixups counter.
321 An enum cgen_parse_operand_result is stored in RESULTP.
322 OPINDEX is the operand's table entry index.
323 OPINFO is something the caller chooses to help in reloc determination.
324 The resulting value is stored in VALUEP. */
326 const char *
327 gas_cgen_parse_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
328 enum cgen_parse_operand_type want, const char **strP,
329 int opindex, int opinfo,
330 enum cgen_parse_operand_result *resultP,
331 bfd_vma *valueP)
333 #ifdef __STDC__
334 /* These are volatile to survive the setjmp. */
335 char * volatile hold;
336 enum cgen_parse_operand_result * volatile resultP_1;
337 volatile int opinfo_1;
338 #else
339 static char *hold;
340 static enum cgen_parse_operand_result *resultP_1;
341 int opinfo_1;
342 #endif
343 const char *errmsg;
344 expressionS exp;
346 #ifdef OBJ_COMPLEX_RELC
347 volatile int signed_p = 0;
348 symbolS * stmp = NULL;
349 bfd_reloc_code_real_type reloc_type;
350 const CGEN_OPERAND * operand;
351 fixS dummy_fixup;
352 #endif
353 if (want == CGEN_PARSE_OPERAND_INIT)
355 gas_cgen_init_parse ();
356 return NULL;
359 resultP_1 = resultP;
360 hold = input_line_pointer;
361 input_line_pointer = (char *) *strP;
362 opinfo_1 = opinfo;
364 /* We rely on md_operand to longjmp back to us.
365 This is done via gas_cgen_md_operand. */
366 if (setjmp (expr_jmp_buf) != 0)
368 expr_jmp_buf_p = 0;
369 input_line_pointer = (char *) hold;
370 *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
371 return _("illegal operand");
374 expr_jmp_buf_p = 1;
375 expression (&exp);
376 expr_jmp_buf_p = 0;
377 errmsg = NULL;
379 *strP = input_line_pointer;
380 input_line_pointer = hold;
382 #ifdef TC_CGEN_PARSE_FIX_EXP
383 opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
384 #endif
386 /* FIXME: Need to check `want'. */
388 switch (exp.X_op)
390 case O_illegal:
391 errmsg = _("illegal operand");
392 *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
393 break;
394 case O_absent:
395 errmsg = _("missing operand");
396 *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
397 break;
398 case O_constant:
399 if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
400 goto de_fault;
401 *valueP = exp.X_add_number;
402 *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
403 break;
404 case O_register:
405 *valueP = exp.X_add_number;
406 *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
407 break;
408 de_fault:
409 default:
410 #ifdef OBJ_COMPLEX_RELC
411 /* Look up operand, check to see if there's an obvious
412 overflow (this helps disambiguate some insn parses). */
413 operand = cgen_operand_lookup_by_num (cd, opindex);
414 errmsg = weak_operand_overflow_check (& exp, operand);
416 if (! errmsg)
418 asymbol *bsym;
420 /* Fragment the expression as necessary, and queue a reloc. */
421 memset (& dummy_fixup, 0, sizeof (fixS));
423 reloc_type = md_cgen_lookup_reloc (0, operand, & dummy_fixup);
425 if (exp.X_op == O_symbol
426 && reloc_type == BFD_RELOC_RELC
427 && symbol_constant_p (exp.X_add_symbol)
428 && (!symbol_symbolS (exp.X_add_symbol)
429 || (bsym = symbol_get_bfdsym (exp.X_add_symbol)) == NULL
430 || (bsym->section != expr_section
431 && bsym->section != absolute_section
432 && bsym->section != undefined_section)))
434 /* Local labels will have been (eagerly) turned into constants
435 by now, due to the inappropriately deep insight of the
436 expression parser. Unfortunately make_expr_symbol
437 prematurely dives into the symbol evaluator, and in this
438 case it gets a bad answer, so we manually create the
439 expression symbol we want here. */
440 stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
441 & zero_address_frag);
442 symbol_set_value_expression (stmp, & exp);
444 else
445 stmp = make_expr_symbol (& exp);
447 /* If this is a pc-relative RELC operand, we
448 need to subtract "." from the expression. */
449 if (reloc_type == BFD_RELOC_RELC
450 && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
451 stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ());
453 /* FIXME: this is not a perfect heuristic for figuring out
454 whether an operand is signed: it only works when the operand
455 is an immediate. it's not terribly likely that any other
456 values will be signed relocs, but it's possible. */
457 if (operand && (operand->hw_type == HW_H_SINT))
458 signed_p = 1;
460 if (symbol_symbolS (stmp)
461 && (bsym = symbol_get_bfdsym (stmp)) != NULL
462 && bsym->section == expr_section
463 && ! S_IS_LOCAL (stmp))
465 if (signed_p)
466 bsym->flags |= BSF_SRELC;
467 else
468 bsym->flags |= BSF_RELC;
471 /* Now package it all up for the fixup emitter. */
472 exp.X_op = O_symbol;
473 exp.X_op_symbol = 0;
474 exp.X_add_symbol = stmp;
475 exp.X_add_number = 0;
477 /* Re-init rightshift quantity, just in case. */
478 rightshift = operand->length;
479 queue_fixup_recursively (opindex, opinfo_1, & exp,
480 (reloc_type == BFD_RELOC_RELC) ?
481 & (operand->index_fields) : 0,
482 signed_p, -1);
484 * resultP = errmsg
485 ? CGEN_PARSE_OPERAND_RESULT_ERROR
486 : CGEN_PARSE_OPERAND_RESULT_QUEUED;
487 *valueP = 0;
488 #else
489 queue_fixup (opindex, opinfo_1, &exp);
490 *valueP = 0;
491 *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
492 #endif
493 break;
496 return errmsg;
499 /* md_operand handler to catch unrecognized expressions and halt the
500 parsing process so the next entry can be tried.
502 ??? This could be done differently by adding code to `expression'. */
504 void
505 gas_cgen_md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
507 /* Don't longjmp if we're not called from within cgen_parse_operand(). */
508 if (expr_jmp_buf_p)
509 longjmp (expr_jmp_buf, 1);
512 /* Finish assembling instruction INSN.
513 BUF contains what we've built up so far.
514 LENGTH is the size of the insn in bits.
515 RELAX_P is non-zero if relaxable insns should be emitted as such.
516 Otherwise they're emitted in non-relaxable forms.
517 The "result" is stored in RESULT if non-NULL. */
519 void
520 gas_cgen_finish_insn (const CGEN_INSN *insn, CGEN_INSN_BYTES_PTR buf,
521 unsigned int length, int relax_p, finished_insnS *result)
523 int i;
524 int relax_operand;
525 char *f;
526 unsigned int byte_len = length / 8;
528 /* ??? Target foo issues various warnings here, so one might want to provide
529 a hook here. However, our caller is defined in tc-foo.c so there
530 shouldn't be a need for a hook. */
532 /* Write out the instruction.
533 It is important to fetch enough space in one call to `frag_more'.
534 We use (f - frag_now->fr_literal) to compute where we are and we
535 don't want frag_now to change between calls.
537 Relaxable instructions: We need to ensure we allocate enough
538 space for the largest insn. */
540 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
541 /* These currently shouldn't get here. */
542 abort ();
544 /* Is there a relaxable insn with the relaxable operand needing a fixup? */
546 relax_operand = -1;
547 if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
549 /* Scan the fixups for the operand affected by relaxing
550 (i.e. the branch address). */
552 for (i = 0; i < num_fixups; ++i)
554 if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
555 CGEN_OPERAND_RELAX))
557 relax_operand = i;
558 break;
563 if (relax_operand != -1)
565 int max_len;
566 fragS *old_frag;
567 expressionS *exp;
568 symbolS *sym;
569 offsetT off;
571 #ifdef TC_CGEN_MAX_RELAX
572 max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
573 #else
574 max_len = CGEN_MAX_INSN_SIZE;
575 #endif
576 /* Ensure variable part and fixed part are in same fragment. */
577 /* FIXME: Having to do this seems like a hack. */
578 frag_grow (max_len);
580 /* Allocate space for the fixed part. */
581 f = frag_more (byte_len);
583 /* Create a relaxable fragment for this instruction. */
584 old_frag = frag_now;
586 exp = &fixups[relax_operand].exp;
587 sym = exp->X_add_symbol;
588 off = exp->X_add_number;
589 if (exp->X_op != O_constant && exp->X_op != O_symbol)
591 /* Handle complex expressions. */
592 sym = make_expr_symbol (exp);
593 off = 0;
596 frag_var (rs_machine_dependent,
597 max_len - byte_len /* max chars */,
598 0 /* variable part already allocated */,
599 /* FIXME: When we machine generate the relax table,
600 machine generate a macro to compute subtype. */
601 1 /* subtype */,
602 sym,
603 off,
606 /* Record the operand number with the fragment so md_convert_frag
607 can use gas_cgen_md_record_fixup to record the appropriate reloc. */
608 old_frag->fr_cgen.insn = insn;
609 old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
610 old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
611 if (result)
612 result->frag = old_frag;
614 else
616 f = frag_more (byte_len);
617 if (result)
618 result->frag = frag_now;
621 /* If we're recording insns as numbers (rather than a string of bytes),
622 target byte order handling is deferred until now. */
623 #if CGEN_INT_INSN_P
624 cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf);
625 #else
626 memcpy (f, buf, byte_len);
627 #endif
629 /* Emit DWARF2 debugging information. */
630 dwarf2_emit_insn (byte_len);
632 /* Create any fixups. */
633 for (i = 0; i < num_fixups; ++i)
635 fixS *fixP;
636 const CGEN_OPERAND *operand =
637 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex);
639 /* Don't create fixups for these. That's done during relaxation.
640 We don't need to test for CGEN_INSN_RELAXED as they can't get here
641 (see above). */
642 if (relax_p
643 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE)
644 && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_RELAX))
645 continue;
647 #ifndef md_cgen_record_fixup_exp
648 #define md_cgen_record_fixup_exp gas_cgen_record_fixup_exp
649 #endif
651 fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
652 insn, length, operand,
653 fixups[i].opinfo,
654 &fixups[i].exp);
655 fixP->fx_cgen.field = fixups[i].field;
656 fixP->fx_cgen.msb_field_p = fixups[i].msb_field_p;
657 if (result)
658 result->fixups[i] = fixP;
661 if (result)
663 result->num_fixups = num_fixups;
664 result->addr = f;
668 #ifdef OBJ_COMPLEX_RELC
669 /* Queue many fixups, recursively. If the field is a multi-ifield,
670 repeatedly queue its sub-parts, right shifted to fit into the field (we
671 assume here multi-fields represent a left-to-right, MSB0-LSB0
672 reading). */
674 static void
675 queue_fixup_recursively (const int opindex,
676 const int opinfo,
677 expressionS * expP,
678 const CGEN_MAYBE_MULTI_IFLD * field,
679 const int signed_p,
680 const int part_of_multi)
682 if (field && field->count)
684 int i;
686 for (i = 0; i < field->count; ++ i)
687 queue_fixup_recursively (opindex, opinfo, expP,
688 & (field->val.multi[i]), signed_p, i);
690 else
692 expressionS * new_exp = expP;
694 #ifdef DEBUG
695 printf ("queueing fixup for field %s\n",
696 (field ? field->val.leaf->name : "??"));
697 print_symbol_value (expP->X_add_symbol);
698 #endif
699 if (field && part_of_multi != -1)
701 rightshift -= field->val.leaf->length;
703 /* Shift reloc value by number of bits remaining after this
704 field. */
705 if (rightshift)
706 new_exp = make_right_shifted_expr (expP, rightshift, signed_p);
709 /* Truncate reloc values to length, *after* leftmost one. */
710 fixups[num_fixups].msb_field_p = (part_of_multi <= 0);
711 fixups[num_fixups].field = (CGEN_MAYBE_MULTI_IFLD *) field;
713 queue_fixup (opindex, opinfo, new_exp);
717 /* Encode the self-describing RELC reloc format's addend. */
719 static unsigned long
720 gas_cgen_encode_addend (const unsigned long start, /* in bits */
721 const unsigned long len, /* in bits */
722 const unsigned long oplen, /* in bits */
723 const unsigned long wordsz, /* in bytes */
724 const unsigned long chunksz, /* in bytes */
725 const unsigned long signed_p,
726 const unsigned long trunc_p)
728 unsigned long res = 0L;
730 res |= start & 0x3F;
731 res |= (oplen & 0x3F) << 6;
732 res |= (len & 0x3F) << 12;
733 res |= (wordsz & 0xF) << 18;
734 res |= (chunksz & 0xF) << 22;
735 res |= (CGEN_INSN_LSB0_P ? 1 : 0) << 27;
736 res |= signed_p << 28;
737 res |= trunc_p << 29;
739 return res;
742 /* Purpose: make a weak check that the expression doesn't overflow the
743 operand it's to be inserted into.
745 Rationale: some insns used to use %operators to disambiguate during a
746 parse. when these %operators are translated to expressions by the macro
747 expander, the ambiguity returns. we attempt to disambiguate by field
748 size.
750 Method: check to see if the expression's top node is an O_and operator,
751 and the mask is larger than the operand length. This would be an
752 overflow, so signal it by returning an error string. Any other case is
753 ambiguous, so we assume it's OK and return NULL. */
755 static const char *
756 weak_operand_overflow_check (const expressionS * exp,
757 const CGEN_OPERAND * operand)
759 const unsigned long len = operand->length;
760 unsigned long mask;
761 unsigned long opmask = (((1L << (len - 1)) - 1) << 1) | 1;
763 if (!exp)
764 return NULL;
766 if (exp->X_op != O_bit_and)
768 /* Check for implicit overflow flag. */
769 if (CGEN_OPERAND_ATTR_VALUE
770 (operand, CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW))
771 return _("a reloc on this operand implies an overflow");
772 return NULL;
775 mask = exp->X_add_number;
777 if (exp->X_add_symbol
778 && symbol_constant_p (exp->X_add_symbol))
779 mask |= *symbol_X_add_number (exp->X_add_symbol);
781 if (exp->X_op_symbol
782 && symbol_constant_p (exp->X_op_symbol))
783 mask |= *symbol_X_add_number (exp->X_op_symbol);
785 /* Want to know if mask covers more bits than opmask.
786 this is the same as asking if mask has any bits not in opmask,
787 or whether (mask & ~opmask) is nonzero. */
788 if (mask && (mask & ~opmask))
790 #ifdef DEBUG
791 printf ("overflow: (mask = %8.8x, ~opmask = %8.8x, AND = %8.8x)\n",
792 mask, ~opmask, (mask & ~opmask));
793 #endif
794 return _("operand mask overflow");
797 return NULL;
800 static expressionS *
801 make_right_shifted_expr (expressionS * exp,
802 const int amount,
803 const int signed_p)
805 symbolS * stmp = 0;
806 expressionS * new_exp;
807 asymbol *bsym;
809 stmp = expr_build_binary (O_right_shift,
810 make_expr_symbol (exp),
811 expr_build_uconstant (amount));
812 bsym = symbol_get_bfdsym (stmp);
814 if (signed_p)
815 bsym->flags |= BSF_SRELC;
816 else
817 bsym->flags |= BSF_RELC;
819 /* Then wrap that in a "symbol expr" for good measure. */
820 new_exp = XNEW (expressionS);
821 memset (new_exp, 0, sizeof (expressionS));
822 new_exp->X_op = O_symbol;
823 new_exp->X_op_symbol = 0;
824 new_exp->X_add_symbol = stmp;
825 new_exp->X_add_number = 0;
827 return new_exp;
830 #endif
832 /* Apply a fixup to the object code. This is called for all the
833 fixups we generated by the call to fix_new_exp, above. In the call
834 above we used a reloc code which was the largest legal reloc code
835 plus the operand index. Here we undo that to recover the operand
836 index. At this point all symbol values should be fully resolved,
837 and we attempt to completely resolve the reloc. If we can not do
838 that, we determine the correct reloc code and put it back in the fixup. */
840 /* FIXME: This function handles some of the fixups and bfd_install_relocation
841 handles the rest. bfd_install_relocation (or some other bfd function)
842 should handle them all. */
844 void
845 gas_cgen_md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
847 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
848 valueT value = * valP;
849 /* Canonical name, since used a lot. */
850 CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
852 if (fixP->fx_addsy == (symbolS *) NULL)
853 fixP->fx_done = 1;
855 /* We don't actually support subtracting a symbol. */
856 if (fixP->fx_subsy != (symbolS *) NULL)
857 as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
859 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
861 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
862 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
863 const char *errmsg;
864 bfd_reloc_code_real_type reloc_type;
865 const CGEN_INSN *insn = fixP->fx_cgen.insn;
866 #ifdef OBJ_COMPLEX_RELC
867 int start;
868 int length;
869 int signed_p = 0;
871 if (fixP->fx_cgen.field)
873 /* Use the twisty little pointer path
874 back to the ifield if it exists. */
875 start = fixP->fx_cgen.field->val.leaf->start;
876 length = fixP->fx_cgen.field->val.leaf->length;
878 else
880 /* Or the far less useful operand-size guesstimate. */
881 start = operand->start;
882 length = operand->length;
885 /* FIXME: this is not a perfect heuristic for figuring out
886 whether an operand is signed: it only works when the operand
887 is an immediate. it's not terribly likely that any other
888 values will be signed relocs, but it's possible. */
889 if (operand && (operand->hw_type == HW_H_SINT))
890 signed_p = 1;
891 #endif
893 /* If the reloc has been fully resolved finish the operand here. */
894 /* FIXME: This duplicates the capabilities of code in BFD. */
895 if (fixP->fx_done
896 /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
897 finish the job. Testing for pcrel is a temporary hack. */
898 || fixP->fx_pcrel)
900 CGEN_FIELDS *fields = xmalloc (CGEN_CPU_SIZEOF_FIELDS (cd));
902 CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
903 CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
905 #if CGEN_INT_INSN_P
907 CGEN_INSN_INT insn_value =
908 cgen_get_insn_value (cd, (unsigned char *) where,
909 CGEN_INSN_BITSIZE (insn));
911 /* ??? 0 is passed for `pc'. */
912 errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
913 &insn_value, (bfd_vma) 0);
914 cgen_put_insn_value (cd, (unsigned char *) where,
915 CGEN_INSN_BITSIZE (insn), insn_value);
917 #else
918 /* ??? 0 is passed for `pc'. */
919 errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
920 (unsigned char *) where,
921 (bfd_vma) 0);
922 #endif
923 if (errmsg)
924 as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
926 free (fields);
929 if (fixP->fx_done)
930 return;
932 /* The operand isn't fully resolved. Determine a BFD reloc value
933 based on the operand information and leave it to
934 bfd_install_relocation. Note that this doesn't work when
935 partial_inplace == false. */
937 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
938 #ifdef OBJ_COMPLEX_RELC
939 if (reloc_type == BFD_RELOC_RELC)
941 /* Change addend to "self-describing" form,
942 for BFD to handle in the linker. */
943 value = gas_cgen_encode_addend (start, operand->length,
944 length, fixP->fx_size,
945 cd->insn_chunk_bitsize / 8,
946 signed_p,
947 ! (fixP->fx_cgen.msb_field_p));
949 #endif
951 if (reloc_type != BFD_RELOC_NONE)
952 fixP->fx_r_type = reloc_type;
953 else
955 as_bad_where (fixP->fx_file, fixP->fx_line,
956 _("unresolved expression that must be resolved"));
957 fixP->fx_done = 1;
958 return;
961 else if (fixP->fx_done)
963 /* We're finished with this fixup. Install it because
964 bfd_install_relocation won't be called to do it. */
965 switch (fixP->fx_r_type)
967 case BFD_RELOC_8:
968 md_number_to_chars (where, value, 1);
969 break;
970 case BFD_RELOC_16:
971 md_number_to_chars (where, value, 2);
972 break;
973 case BFD_RELOC_32:
974 md_number_to_chars (where, value, 4);
975 break;
976 case BFD_RELOC_64:
977 md_number_to_chars (where, value, 8);
978 break;
979 default:
980 as_bad_where (fixP->fx_file, fixP->fx_line,
981 _("internal error: can't install fix for reloc type %d (`%s')"),
982 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
983 break;
986 /* else
987 bfd_install_relocation will be called to finish things up. */
989 /* Tuck `value' away for use by tc_gen_reloc.
990 See the comment describing fx_addnumber in write.h.
991 This field is misnamed (or misused :-). */
992 fixP->fx_addnumber = value;
995 bfd_reloc_code_real_type
996 gas_cgen_pcrel_r_type (bfd_reloc_code_real_type r)
998 switch (r)
1000 case BFD_RELOC_8: r = BFD_RELOC_8_PCREL; break;
1001 case BFD_RELOC_16: r = BFD_RELOC_16_PCREL; break;
1002 case BFD_RELOC_24: r = BFD_RELOC_24_PCREL; break;
1003 case BFD_RELOC_32: r = BFD_RELOC_32_PCREL; break;
1004 case BFD_RELOC_64: r = BFD_RELOC_64_PCREL; break;
1005 default:
1006 break;
1008 return r;
1011 /* Translate internal representation of relocation info to BFD target format.
1013 FIXME: To what extent can we get all relevant targets to use this? */
1015 arelent *
1016 gas_cgen_tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
1018 bfd_reloc_code_real_type r_type = fixP->fx_r_type;
1019 arelent *reloc;
1021 reloc = XNEW (arelent);
1023 #ifdef GAS_CGEN_PCREL_R_TYPE
1024 if (fixP->fx_pcrel)
1025 r_type = GAS_CGEN_PCREL_R_TYPE (r_type);
1026 #endif
1027 reloc->howto = bfd_reloc_type_lookup (stdoutput, r_type);
1029 if (reloc->howto == (reloc_howto_type *) NULL)
1031 as_bad_where (fixP->fx_file, fixP->fx_line,
1032 _("relocation is not supported"));
1033 return NULL;
1036 gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1038 reloc->sym_ptr_ptr = XNEW (asymbol *);
1039 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1041 /* Use fx_offset for these cases. */
1042 if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
1043 || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
1044 reloc->addend = fixP->fx_offset;
1045 else
1046 reloc->addend = fixP->fx_addnumber;
1048 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1049 return reloc;
1052 /* Perform any cgen specific initialisation.
1053 Called after gas_cgen_cpu_desc has been created. */
1055 void
1056 gas_cgen_begin (void)
1058 if (flag_signed_overflow_ok)
1059 cgen_set_signed_overflow_ok (gas_cgen_cpu_desc);
1060 else
1061 cgen_clear_signed_overflow_ok (gas_cgen_cpu_desc);