1 /* GAS interface for targets using CGEN: Cpu tools GENerator.
2 Copyright (C) 1996, 1997 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 2, or (at your option)
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.
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 /* Callback to insert a register into the symbol table.
27 A target may choose to let GAS parse the registers.
28 ??? Not currently used. */
31 cgen_asm_record_register (name, number)
35 /* Use symbol_create here instead of symbol_new so we don't try to
36 output registers into the object file's symbol table. */
37 symbol_table_insert (symbol_create (name, reg_section,
38 number, &zero_address_frag));
41 /* We need to keep a list of fixups. We can't simply generate them as
42 we go, because that would require us to first create the frag, and
43 that would screw up references to ``.''.
45 This is used by cpu's with simple operands. It keeps knowledge of what
46 an `expressionS' is and what a `fixup' is out of CGEN which for the time
49 OPINDEX is the index in the operand table.
50 OPINFO is something the caller chooses to help in reloc determination. */
61 static struct fixup fixups[MAX_FIXUPS];
62 static int num_fixups;
65 cgen_asm_init_parse ()
73 cgen_queue_fixup (opindex, opinfo, expP)
77 /* We need to generate a fixup for this expression. */
78 if (num_fixups >= MAX_FIXUPS)
79 as_fatal ("too many fixups");
80 fixups[num_fixups].exp = *expP;
81 fixups[num_fixups].opindex = opindex;
82 fixups[num_fixups].opinfo = opinfo;
86 /* Default routine to record a fixup.
87 This is a cover function to fix_new.
88 It exists because we record INSN with the fixup.
90 FRAG and WHERE are their respective arguments to fix_new_exp.
92 OPINFO is something the caller chooses to help in reloc determination.
94 At this point we do not use a bfd_reloc_code_real_type for
95 operands residing in the insn, but instead just use the
96 operand index. This lets us easily handle fixups for any
97 operand type. We pick a BFD reloc type in md_apply_fix. */
100 cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
103 const struct cgen_insn *insn;
105 const struct cgen_operand *operand;
112 /* It may seem strange to use operand->attrs and not insn->attrs here,
113 but it is the operand that has a pc relative relocation. */
115 fixP = fix_new (frag, where, length / 8, symbol, offset,
116 CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0,
117 (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand)));
118 fixP->tc_fix_data.insn = (PTR) insn;
119 fixP->tc_fix_data.opinfo = opinfo;
124 /* Default routine to record a fixup given an expression.
125 This is a cover function to fix_new_exp.
126 It exists because we record INSN with the fixup.
128 FRAG and WHERE are their respective arguments to fix_new_exp.
130 OPINFO is something the caller chooses to help in reloc determination.
132 At this point we do not use a bfd_reloc_code_real_type for
133 operands residing in the insn, but instead just use the
134 operand index. This lets us easily handle fixups for any
135 operand type. We pick a BFD reloc type in md_apply_fix. */
138 cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
141 const struct cgen_insn *insn;
143 const struct cgen_operand *operand;
149 /* It may seem strange to use operand->attrs and not insn->attrs here,
150 but it is the operand that has a pc relative relocation. */
152 fixP = fix_new_exp (frag, where, length / 8, exp,
153 CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0,
154 (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand)));
155 fixP->tc_fix_data.insn = (PTR) insn;
156 fixP->tc_fix_data.opinfo = opinfo;
161 /* Callback for cgen interface. Parse the expression at *STRP.
162 The result is an error message or NULL for success (in which case
163 *STRP is advanced past the parsed text).
164 An enum cgen_asm_result is stored in RESULTP.
165 OPINFO is something the caller chooses to help in reloc determination.
166 The resulting value is stored in VALUEP. */
169 cgen_asm_parse_operand (strP, opindex, opinfo, resultP, valueP)
173 enum cgen_asm_result *resultP;
177 const char *errmsg = NULL;
180 hold = input_line_pointer;
181 input_line_pointer = (char *) *strP;
183 *strP = input_line_pointer;
184 input_line_pointer = hold;
189 errmsg = "illegal operand";
190 *resultP = CGEN_ASM_ERROR;
193 errmsg = "missing operand";
194 *resultP = CGEN_ASM_ERROR;
197 *valueP = exp.X_add_number;
198 *resultP = CGEN_ASM_NUMBER;
201 *valueP = exp.X_add_number;
202 *resultP = CGEN_ASM_REGISTER;
205 cgen_queue_fixup (opindex, opinfo, &exp);
207 *resultP = CGEN_ASM_QUEUED;
214 /* Finish assembling instruction INSN.
215 BUF contains what we've built up so far.
216 LENGTH is the size of the insn in bits. */
219 cgen_asm_finish_insn (insn, buf, length)
220 const struct cgen_insn *insn;
224 int i, relax_operand;
226 unsigned int byte_len = length / 8;
228 /* ??? Target foo issues various warnings here, so one might want to provide
229 a hook here. However, our caller is defined in tc-foo.c so there
230 shouldn't be a need for a hook. */
232 /* Write out the instruction.
233 It is important to fetch enough space in one call to `frag_more'.
234 We use (f - frag_now->fr_literal) to compute where we are and we
235 don't want frag_now to change between calls.
237 Relaxable instructions: We need to ensure we allocate enough
238 space for the largest insn. */
240 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
241 abort (); /* These currently shouldn't get here. */
243 /* Is there a relaxable insn with the relaxable operand needing a fixup? */
246 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0)
248 /* Scan the fixups for the operand affected by relaxing
249 (i.e. the branch address). */
251 for (i = 0; i < num_fixups; ++i)
253 if (CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
254 CGEN_OPERAND_RELAX) != 0)
262 if (relax_operand != -1)
267 #ifdef TC_CGEN_MAX_RELAX
268 max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
270 max_len = CGEN_MAX_INSN_SIZE;
272 /* Ensure variable part and fixed part are in same fragment. */
273 /* FIXME: Having to do this seems like a hack. */
275 /* Allocate space for the fixed part. */
276 f = frag_more (byte_len);
277 /* Create a relaxable fragment for this instruction. */
279 frag_var (rs_machine_dependent,
280 max_len - byte_len /* max chars */,
281 0 /* variable part already allocated */,
282 /* FIXME: When we machine generate the relax table,
283 machine generate a macro to compute subtype. */
285 fixups[relax_operand].exp.X_add_symbol,
286 fixups[relax_operand].exp.X_add_number,
288 /* Record the operand number with the fragment so md_convert_frag
289 can use cgen_md_record_fixup to record the appropriate reloc. */
290 /* FIXME: fr_targ.cgen is used pending deciding whether to
291 allow a target to add members to fragS. For more info
292 see the comment above fr_targ in as.h. */
293 old_frag->fr_targ.cgen.insn = insn;
294 old_frag->fr_targ.cgen.opindex = fixups[relax_operand].opindex;
295 old_frag->fr_targ.cgen.opinfo = fixups[relax_operand].opinfo;
298 f = frag_more (byte_len);
300 /* If we're recording insns as numbers (rather than a string of bytes),
301 target byte order handling is deferred until now. */
302 #if 0 /*def CGEN_INT_INSN*/
306 if (cgen_big_endian_p)
307 bfd_putb16 ((bfd_vma) *buf, f);
309 bfd_putl16 ((bfd_vma) *buf, f);
312 if (cgen_big_endian_p)
313 bfd_putb32 ((bfd_vma) *buf, f);
315 bfd_putl32 ((bfd_vma) *buf, f);
321 memcpy (f, buf, byte_len);
324 /* Create any fixups. */
325 for (i = 0; i < num_fixups; ++i)
327 /* Don't create fixups for these. That's done during relaxation.
328 We don't need to test for CGEN_INSN_RELAX as they can't get here
330 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0
331 && CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
332 CGEN_OPERAND_RELAX) != 0)
335 #ifndef md_cgen_record_fixup_exp
336 #define md_cgen_record_fixup_exp cgen_record_fixup_exp
339 md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
341 & CGEN_SYM (operand_table) [fixups[i].opindex],
347 /* Apply a fixup to the object code. This is called for all the
348 fixups we generated by the call to fix_new_exp, above. In the call
349 above we used a reloc code which was the largest legal reloc code
350 plus the operand index. Here we undo that to recover the operand
351 index. At this point all symbol values should be fully resolved,
352 and we attempt to completely resolve the reloc. If we can not do
353 that, we determine the correct reloc code and put it back in the fixup. */
355 /* FIXME: This function handles some of the fixups and bfd_install_relocation
356 handles the rest. bfd_install_relocation (or some other bfd function)
357 should handle them all. */
360 cgen_md_apply_fix3 (fixP, valueP, seg)
365 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
368 /* FIXME FIXME FIXME: The value we are passed in *valuep includes
369 the symbol values. Since we are using BFD_ASSEMBLER, if we are
370 doing this relocation the code in write.c is going to call
371 bfd_install_relocation, which is also going to use the symbol
372 value. That means that if the reloc is fully resolved we want to
373 use *valuep since bfd_install_relocation is not being used.
374 However, if the reloc is not fully resolved we do not want to use
375 *valuep, and must use fx_offset instead. However, if the reloc
376 is PC relative, we do want to use *valuep since it includes the
377 result of md_pcrel_from. This is confusing. */
379 if (fixP->fx_addsy == (symbolS *) NULL)
384 else if (fixP->fx_pcrel)
388 value = fixP->fx_offset;
389 if (fixP->fx_subsy != (symbolS *) NULL)
391 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
392 value -= S_GET_VALUE (fixP->fx_subsy);
395 /* We don't actually support subtracting a symbol. */
396 as_bad_where (fixP->fx_file, fixP->fx_line,
397 "expression too complex");
402 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
404 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
405 const struct cgen_operand *operand = & CGEN_SYM (operand_table) [opindex];
407 bfd_reloc_code_real_type reloc_type;
408 struct cgen_fields fields;
409 const struct cgen_insn *insn = (struct cgen_insn *) fixP->tc_fix_data.insn;
411 /* If the reloc has been fully resolved finish the operand here. */
412 /* FIXME: This duplicates the capabilities of code in BFD. */
414 /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
415 finish the job. Testing for pcrel is a temporary hack. */
418 /* This may seem like overkill, and using bfd_install_relocation or
419 some such may be preferable, but this is simple. */
420 CGEN_FIELDS_BITSIZE (&fields) = CGEN_INSN_BITSIZE (insn);
421 CGEN_SYM (set_operand) (opindex, &value, &fields);
422 errmsg = CGEN_SYM (validate_operand) (opindex, &fields);
424 as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg);
425 CGEN_SYM (insert_operand) (opindex, &fields, where);
431 /* The operand isn't fully resolved. Determine a BFD reloc value
432 based on the operand information and leave it to
433 bfd_install_relocation. Note that this doesn't work when
434 partial_inplace == false. */
436 reloc_type = CGEN_SYM (lookup_reloc) (insn, operand, fixP);
437 if (reloc_type != BFD_RELOC_NONE)
439 fixP->fx_r_type = reloc_type;
443 as_bad_where (fixP->fx_file, fixP->fx_line,
444 "unresolved expression that must be resolved");
449 else if (fixP->fx_done)
451 /* We're finished with this fixup. Install it because
452 bfd_install_relocation won't be called to do it. */
453 switch (fixP->fx_r_type)
456 md_number_to_chars (where, value, 1);
459 md_number_to_chars (where, value, 2);
462 md_number_to_chars (where, value, 4);
464 /* FIXME: later add support for 64 bits. */
471 /* bfd_install_relocation will be called to finish things up. */
474 /* Tuck `value' away for use by tc_gen_reloc.
475 See the comment describing fx_addnumber in write.h.
476 This field is misnamed (or misused :-). */
477 fixP->fx_addnumber = value;
482 /* Translate internal representation of relocation info to BFD target format.
484 FIXME: To what extent can we get all relevant targets to use this? */
487 cgen_tc_gen_reloc (section, fixP)
493 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
495 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
496 if (reloc->howto == (reloc_howto_type *) NULL)
498 as_bad_where (fixP->fx_file, fixP->fx_line,
499 "internal error: can't export reloc type %d (`%s')",
500 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
504 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
506 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
507 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
508 reloc->addend = fixP->fx_addnumber;