allow '/' in addition to '.' in dest spec
[deliverable/binutils-gdb.git] / gas / config / tc-txvu.c
CommitLineData
209fb346 1/* tc-txvu.c -- Assembler for the TX VU.
f7306261 2 Copyright (C) 1997, 1998 Free Software Foundation.
209fb346
DE
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 2, 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include <stdio.h>
22#include <ctype.h>
23#include "as.h"
f6428b86
DE
24#include "subsegs.h"
25/* Needed by opcode/txvu.h. */
26#include "dis-asm.h"
27#include "opcode/txvu.h"
28#include "elf/txvu.h"
209fb346 29
020ba60b
DE
30static TXVU_INSN txvu_insert_operand
31 PARAMS ((TXVU_INSN, const struct txvu_operand *, int, offsetT,
32 char *, unsigned int));
33
209fb346
DE
34const char comment_chars[] = ";";
35const char line_comment_chars[] = "#";
36const char line_separator_chars[] = "!";
37const char EXP_CHARS[] = "eE";
38const char FLT_CHARS[] = "dD";
b5d20cf6
DE
39
40/* Non-zero if in vu-mode. */
41static int vu_mode_p;
42
f7306261 43/* Non-zero if packing pke instructions in dma tags. */
b5d20cf6 44static int dma_pack_pke_p;
209fb346
DE
45\f
46const char *md_shortopts = "";
47
48struct option md_longopts[] =
49{
50 /* insert options here */
51
52 {NULL, no_argument, NULL, 0}
53};
54size_t md_longopts_size = sizeof(md_longopts);
55
56int
57md_parse_option (c, arg)
58 int c;
59 char *arg;
60{
61 return 0;
62}
63
64void
65md_show_usage (stream)
66 FILE *stream;
67{
68#if 0
69 fprintf (stream, "TX VU options:\n");
70#endif
71}
72
73/* Set by md_assemble for use by txvu_fill_insn. */
74static subsegT prev_subseg;
75static segT prev_seg;
76
b5d20cf6
DE
77static void s_dmadata PARAMS ((int));
78static void s_dmapackpke PARAMS ((int));
79static void s_enddirect PARAMS ((int));
b5d20cf6
DE
80static void s_endgpuif PARAMS ((int));
81static void s_endmpg PARAMS ((int));
82static void s_endunpack PARAMS ((int));
83static void s_vu PARAMS ((int));
84
209fb346
DE
85/* The target specific pseudo-ops which we support. */
86const pseudo_typeS md_pseudo_table[] =
87{
63589bf4 88 { "dmadata", s_dmadata, 1 },
b5d20cf6
DE
89 { "dmapackpke", s_dmapackpke, 0 },
90 { "enddirect", s_enddirect, 0 },
63589bf4 91 { "enddmadata", s_dmadata, 0 },
b5d20cf6
DE
92 { "endgpuif", s_endgpuif, 0 },
93 { "endmpg", s_endmpg, 0 },
94 { "endunpack", s_endunpack, 0 },
95 /* .vu,.endvu added to simplify debugging */
96 { "vu", s_vu, 1 },
97 { "endvu", s_vu, 0 },
209fb346
DE
98 { NULL, NULL, 0 }
99};
100\f
101void
102md_begin ()
103{
104 flagword applicable;
105 segT seg;
106 subsegT subseg;
107
108 /* Save the current subseg so we can restore it [it's the default one and
109 we don't want the initial section to be .sbss. */
110 seg = now_seg;
111 subseg = now_subseg;
112
113 subseg_set (seg, subseg);
f6428b86
DE
114
115 /* Initialize the opcode tables.
116 This involves computing the hash chains. */
117 txvu_opcode_init_tables (0);
b5d20cf6
DE
118
119 vu_mode_p = 0;
120 dma_pack_pke_p = 0;
209fb346 121}
f7306261
DE
122\f
123enum cputype { CPU_VUUP, CPU_VULO, CPU_DMA, CPU_PKE, CPU_GPUIF };
209fb346 124
f6428b86
DE
125/* We need to keep a list of fixups. We can't simply generate them as
126 we go, because that would require us to first create the frag, and
127 that would screw up references to ``.''. */
128
129struct txvu_fixup
130{
131 /* index into `txvu_operands' */
132 int opindex;
133 expressionS exp;
134};
135
136#define MAX_FIXUPS 5
137
f7306261
DE
138static int fixup_count;
139static struct txvu_fixup fixups[MAX_FIXUPS];
140
b5d20cf6
DE
141static void assemble_dma PARAMS ((char *));
142static void assemble_gpuif PARAMS ((char *));
143static void assemble_pke PARAMS ((char *));
144static void assemble_vu PARAMS ((char *));
f7306261
DE
145static char * assemble_vu_insn PARAMS ((enum cputype,
146 const struct txvu_opcode *,
147 const struct txvu_operand *,
148 char *, char *));
149static char * assemble_one_insn PARAMS ((enum cputype,
150 const struct txvu_opcode *,
151 const struct txvu_operand *,
152 char *, TXVU_INSN *));
f6428b86 153
209fb346
DE
154void
155md_assemble (str)
156 char *str;
b5d20cf6 157{
f7306261
DE
158 /* Skip leading white space. */
159 while (isspace (*str))
160 str++;
161
b5d20cf6
DE
162 if (! vu_mode_p)
163 {
164 if (strncasecmp (str, "dma", 3) == 0)
165 assemble_dma (str);
166 else if (strncasecmp (str, "gpuif", 5) == 0)
167 assemble_gpuif (str);
168 else
169 assemble_pke (str);
170 }
171 else
172 assemble_vu (str);
173}
174
f7306261 175/* Subroutine of md_assemble to assemble DMA instructions. */
b5d20cf6
DE
176
177static void
178assemble_dma (str)
179 char *str;
180{
f7306261
DE
181 TXVU_INSN buf[4];
182
183 assemble_one_insn (CPU_DMA,
184 dma_opcode_lookup_asm (str), dma_operands,
185 str, buf);
b5d20cf6
DE
186}
187
f7306261 188/* Subroutine of md_assemble to assemble PKE instructions. */
b5d20cf6
DE
189
190static void
f7306261 191assemble_pke (str)
b5d20cf6
DE
192 char *str;
193{
f7306261
DE
194 TXVU_INSN buf[4];
195
196 assemble_one_insn (CPU_PKE,
197 pke_opcode_lookup_asm (str), pke_operands,
198 str, buf);
b5d20cf6
DE
199}
200
f7306261 201/* Subroutine of md_assemble to assemble GPUIF instructions. */
b5d20cf6
DE
202
203static void
f7306261 204assemble_gpuif (str)
b5d20cf6
DE
205 char *str;
206{
f7306261
DE
207 TXVU_INSN buf[4];
208
209 assemble_one_insn (CPU_GPUIF,
210 gpuif_opcode_lookup_asm (str), gpuif_operands,
211 str, buf);
b5d20cf6
DE
212}
213
214/* Subroutine of md_assemble to assemble VU instructions. */
215
216static void
217assemble_vu (str)
218 char *str;
209fb346 219{
020ba60b
DE
220 /* The lower instruction has the lower address.
221 Handle this by grabbing 8 bytes now, and then filling each word
222 as appropriate. */
223 char *f = frag_more (8);
224
61e09fac 225#ifdef VERTICAL_BAR_SEPARATOR
f6428b86
DE
226 char *p = strchr (str, '|');
227
228 if (p == NULL)
229 {
230 as_bad ("lower slot missing in `%s'", str);
231 return;
232 }
233
234 *p = 0;
f7306261
DE
235 assemble_vu_insn (CPU_VUUP,
236 txvu_upper_opcode_lookup_asm (str), txvu_operands,
237 str, f + 4);
f6428b86 238 *p = '|';
f7306261
DE
239 assemble_vu_insn (CPU_VULO,
240 txvu_lower_opcode_lookup_asm (str), txvu_operands,
241 p + 1, f);
61e09fac 242#else
f7306261
DE
243 str = assemble_vu_insn (CPU_VUUP,
244 txvu_upper_opcode_lookup_asm (str), txvu_operands,
245 str, f + 4);
61e09fac
DE
246 /* Don't assemble next one if we couldn't assemble the first. */
247 if (str)
f7306261
DE
248 assemble_vu_insn (CPU_VULO,
249 txvu_lower_opcode_lookup_asm (str), txvu_operands,
250 str, f);
61e09fac 251#endif
f6428b86
DE
252}
253
61e09fac 254static char *
f7306261
DE
255assemble_vu_insn (cpu, opcode, operand_table, str, buf)
256 enum cputype cpu;
257 const struct txvu_opcode *opcode;
258 const struct txvu_operand *operand_table;
f6428b86 259 char *str;
020ba60b 260 char *buf;
f6428b86 261{
f7306261 262 int i;
f6428b86
DE
263 TXVU_INSN insn;
264
f7306261
DE
265 str = assemble_one_insn (cpu, opcode, operand_table, str, &insn);
266 if (str == NULL)
267 return NULL;
f6428b86 268
f7306261
DE
269 /* Write out the instruction.
270 Reminder: it is important to fetch enough space in one call to
271 `frag_more'. We use (f - frag_now->fr_literal) to compute where
272 we are and we don't want frag_now to change between calls. */
273 md_number_to_chars (buf, insn, 4);
f6428b86 274
f7306261
DE
275 /* Create any fixups. */
276 for (i = 0; i < fixup_count; ++i)
277 {
278 int op_type, reloc_type;
279 const struct txvu_operand *operand;
280
281 /* Create a fixup for this operand.
282 At this point we do not use a bfd_reloc_code_real_type for
283 operands residing in the insn, but instead just use the
284 operand index. This lets us easily handle fixups for any
285 operand type, although that is admittedly not a very exciting
286 feature. We pick a BFD reloc type in md_apply_fix. */
287
288 op_type = fixups[i].opindex;
289 reloc_type = op_type + (int) BFD_RELOC_UNUSED;
290 operand = &txvu_operands[op_type];
291 fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
292 &fixups[i].exp,
293 (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
294 (bfd_reloc_code_real_type) reloc_type);
295 }
296
297 /* All done. */
298 return str;
299}
300
301/* Assemble one instruction.
302 CPU indicates what component we're assembling for.
303 The assembled instruction is stored in INSN_BUF.
304
305 The result is a pointer to beyond the end of the scanned insn
306 or NULL if an error occured. This is to handle the VU where two
307 instructions appear on one line. If this is the upper insn, the caller
308 can pass back to result to us parse the lower insn. */
309
310static char *
311assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
312 enum cputype cpu;
313 const struct txvu_opcode *opcode;
314 const struct txvu_operand *operand_table;
315 char *str;
316 TXVU_INSN *insn_buf;
317{
318 char *start;
f6428b86
DE
319
320 /* Keep looking until we find a match. */
321
322 start = str;
323 for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_ASM (opcode))
324 {
f7306261 325 int past_opcode_p, num_suffixes, num_operands;
f6428b86 326 const unsigned char *syn;
f6428b86
DE
327
328 /* Ensure the mnemonic part matches. */
329 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
330 if (tolower (*str) != tolower (*syn))
331 break;
332 if (*syn != '\0')
333 continue;
f6428b86
DE
334
335 /* Scan the syntax string. If it doesn't match, try the next one. */
336
337 txvu_opcode_init_parse ();
f7306261
DE
338 *insn_buf = opcode->value;
339 fixup_count = 0;
f6428b86
DE
340 past_opcode_p = 0;
341 num_suffixes = 0;
342 num_operands = 0;
343
344 /* We don't check for (*str != '\0') here because we want to parse
345 any trailing fake arguments in the syntax string. */
346 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
347 {
348 int mods,index;
349 const struct txvu_operand *operand;
350 const char *errmsg;
351
fbe2ad46
DE
352 /* Non operand chars must match exactly.
353 Operand chars that are letters are not part of symbols
354 and are case insensitive. */
f6428b86
DE
355 if (*syn < 128)
356 {
fbe2ad46 357 if (tolower (*str) == tolower (*syn))
f6428b86
DE
358 {
359 if (*syn == ' ')
360 past_opcode_p = 1;
361 ++syn;
362 ++str;
363 }
364 else
365 break;
366 continue;
367 }
368
369 /* We have a suffix or an operand. Pick out any modifiers. */
370 mods = 0;
371 index = TXVU_OPERAND_INDEX (*syn);
f7306261 372 while (TXVU_MOD_P (operand_table[index].flags))
f6428b86 373 {
f7306261 374 mods |= operand_table[index].flags & TXVU_MOD_BITS;
f6428b86
DE
375 ++syn;
376 index = TXVU_OPERAND_INDEX (*syn);
377 }
f7306261 378 operand = operand_table + index;
f6428b86
DE
379
380 if (operand->flags & TXVU_OPERAND_FAKE)
381 {
382 if (operand->insert)
383 {
f62a42d0 384 errmsg = NULL;
f7306261 385 (*operand->insert) (insn_buf, operand, mods, 0, &errmsg);
f6428b86
DE
386 /* If we get an error, go on to try the next insn. */
387 if (errmsg)
388 break;
389 }
390 ++syn;
391 }
392 /* Are we finished with suffixes? */
393 else if (!past_opcode_p)
394 {
395 int found;
396 char c;
397 char *s,*t;
398 long suf_value;
399
400 if (!(operand->flags & TXVU_OPERAND_SUFFIX))
401 as_fatal ("bad opcode table, missing suffix flag");
402
403 /* If we're at a space in the input string, we want to skip the
404 remaining suffixes. There may be some fake ones though, so
405 just go on to try the next one. */
406 if (*str == ' ')
407 {
408 ++syn;
409 continue;
410 }
411
412 s = str;
413
414 /* Pick the suffix out and parse it. */
fbe2ad46
DE
415 /* ??? Hmmm ... there may not be any need to nul-terminate the
416 string, and it may in fact complicate things. */
ee1c882e 417 for (t = (*s == '.' || *s == '/') ? s + 1 : s;
2f511a26
DE
418 *t && (isalnum (*t) || *t == '[' || *t == ']');
419 ++t)
f6428b86
DE
420 continue;
421 c = *t;
422 *t = '\0';
f7306261 423 errmsg = NULL;
f6428b86
DE
424 suf_value = (*operand->parse) (&s, &errmsg);
425 *t = c;
426 if (errmsg)
427 {
fbe2ad46
DE
428 /* This can happen, for example, in ARC's in "blle foo" and
429 we're currently using the template "b%q%.n %j". The "bl"
430 insn occurs later in the table so "lle" isn't an illegal
431 suffix. */
f6428b86
DE
432 break;
433 }
434 /* Insert the suffix's value into the insn. */
435 if (operand->insert)
f7306261
DE
436 (*operand->insert) (insn_buf, operand,
437 mods, suf_value, NULL);
f6428b86 438 else
f7306261 439 *insn_buf |= suf_value << operand->shift;
f6428b86
DE
440
441 str = t;
442 ++syn;
443 }
444 else
445 /* This is an operand, either a register or an expression of
446 some kind. */
447 {
448 char c;
449 char *hold;
450 long value = 0;
451 expressionS exp;
452
453 if (operand->flags & TXVU_OPERAND_SUFFIX)
454 as_fatal ("bad opcode table, suffix wrong");
455
5ff98e00 456#if 0 /* commas are in the syntax string now */
f6428b86
DE
457 /* If this is not the first, there must be a comma. */
458 if (num_operands > 0)
459 {
460 if (*str != ',')
461 break;
462 ++str;
463 }
5ff98e00 464#endif
f6428b86
DE
465
466 /* Is there anything left to parse?
467 We don't check for this at the top because we want to parse
468 any trailing fake arguments in the syntax string. */
fbe2ad46 469 /* ??? This doesn't allow operands with a legal value of "". */
f6428b86
DE
470 if (*str == '\0')
471 break;
472
473 /* Parse the operand. */
474 if (operand->parse)
475 {
f7306261 476 errmsg = NULL;
f6428b86 477 value = (*operand->parse) (&str, &errmsg);
71af45ec
DE
478 if (errmsg)
479 break;
f6428b86
DE
480 }
481 else
482 {
483 hold = input_line_pointer;
484 input_line_pointer = str;
485 expression (&exp);
486 str = input_line_pointer;
487 input_line_pointer = hold;
488
71af45ec
DE
489 if (exp.X_op == O_illegal
490 || exp.X_op == O_absent)
491 break;
f6428b86 492 else if (exp.X_op == O_constant)
71af45ec 493 value = exp.X_add_number;
f6428b86 494 else if (exp.X_op == O_register)
71af45ec 495 as_fatal ("got O_register");
f6428b86
DE
496 else
497 {
498 /* We need to generate a fixup for this expression. */
f7306261 499 if (fixup_count >= MAX_FIXUPS)
f6428b86 500 as_fatal ("too many fixups");
f7306261
DE
501 fixups[fixup_count].exp = exp;
502 fixups[fixup_count].opindex = index;
503 ++fixup_count;
f6428b86
DE
504 value = 0;
505 }
506 }
507
508 /* Insert the register or expression into the instruction. */
509 if (operand->insert)
510 {
511 const char *errmsg = NULL;
f7306261
DE
512 (*operand->insert) (insn_buf, operand, mods,
513 value, &errmsg);
f6428b86
DE
514 if (errmsg != (const char *) NULL)
515 break;
516 }
517 else
f7306261 518 *insn_buf |= (value & ((1 << operand->bits) - 1)) << operand->shift;
f6428b86
DE
519
520 ++syn;
521 ++num_operands;
522 }
523 }
524
525 /* If we're at the end of the syntax string, we're done. */
526 /* FIXME: try to move this to a separate function. */
527 if (*syn == '\0')
528 {
529 int i;
f6428b86
DE
530
531 /* For the moment we assume a valid `str' can only contain blanks
532 now. IE: We needn't try again with a longer version of the
533 insn and it is assumed that longer versions of insns appear
534 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
535
536 while (isspace (*str))
537 ++str;
538
61e09fac
DE
539 if (*str != '\0'
540#ifndef VERTICAL_BAR_SEPARATOR
f7306261 541 && cpu != CPU_VUUP
61e09fac
DE
542#endif
543 )
f6428b86
DE
544 as_bad ("junk at end of line: `%s'", str);
545
f7306261
DE
546 /* It's now up to the caller to emit the instruction and any
547 relocations. */
61e09fac 548 return str;
f6428b86
DE
549 }
550
551 /* Try the next entry. */
552 }
553
554 as_bad ("bad instruction `%s'", start);
61e09fac 555 return 0;
209fb346
DE
556}
557
558void
559md_operand (expressionP)
560 expressionS *expressionP;
561{
562}
563
564valueT
565md_section_align (segment, size)
566 segT segment;
567 valueT size;
568{
569 int align = bfd_get_section_alignment (stdoutput, segment);
570 return ((size + (1 << align) - 1) & (-1 << align));
571}
572
573symbolS *
574md_undefined_symbol (name)
575 char *name;
576{
577 return 0;
578}
579\f
580/* Functions concerning relocs. */
581
582/* The location from which a PC relative jump should be calculated,
583 given a PC relative reloc. */
584
585long
586md_pcrel_from_section (fixP, sec)
587 fixS *fixP;
588 segT sec;
589{
590 if (fixP->fx_addsy != (symbolS *) NULL
591 && (! S_IS_DEFINED (fixP->fx_addsy)
592 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
593 {
594 /* The symbol is undefined (or is defined but not in this section).
595 Let the linker figure it out. */
596 return 0;
597 }
598
599 /* FIXME: `& -16L'? */
020ba60b 600 return (fixP->fx_frag->fr_address + fixP->fx_where) & -8L;
209fb346
DE
601}
602
603/* Apply a fixup to the object code. This is called for all the
604 fixups we generated by calls to fix_new_exp. At this point all symbol
605 values should be fully resolved, and we attempt to completely resolve the
606 reloc. If we can not do that, we determine the correct reloc code and put
607 it back in the fixup. */
608
609int
610md_apply_fix3 (fixP, valueP, seg)
611 fixS *fixP;
612 valueT *valueP;
613 segT seg;
614{
615 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
616 valueT value;
617
020ba60b
DE
618 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
619 the symbol values. Since we are using BFD_ASSEMBLER, if we are
620 doing this relocation the code in write.c is going to call
621 bfd_perform_relocation, which is also going to use the symbol
622 value. That means that if the reloc is fully resolved we want to
623 use *valueP since bfd_perform_relocation is not being used.
624 However, if the reloc is not fully resolved we do not want to use
625 *valueP, and must use fx_offset instead. However, if the reloc
626 is PC relative, we do want to use *valueP since it includes the
627 result of md_pcrel_from. This is confusing. */
628
629 if (fixP->fx_addsy == (symbolS *) NULL)
630 {
631 value = *valueP;
632 fixP->fx_done = 1;
633 }
634 else if (fixP->fx_pcrel)
635 {
636 value = *valueP;
637 }
638 else
639 {
640 value = fixP->fx_offset;
641 if (fixP->fx_subsy != (symbolS *) NULL)
642 {
643 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
644 value -= S_GET_VALUE (fixP->fx_subsy);
645 else
646 {
647 /* We can't actually support subtracting a symbol. */
648 as_bad_where (fixP->fx_file, fixP->fx_line,
649 "expression too complex");
650 }
651 }
652 }
653
654 /* Check for txvu_operand's. These are indicated with a reloc value
655 >= BFD_RELOC_UNUSED. */
656
657 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
658 {
659 int opindex;
660 const struct txvu_operand *operand;
661 TXVU_INSN insn;
662
663 opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
664
665 operand = &txvu_operands[opindex];
666
667 /* Fetch the instruction, insert the fully resolved operand
668 value, and stuff the instruction back again. */
669 insn = bfd_getl32 ((unsigned char *) where);
670 insn = txvu_insert_operand (insn, operand, -1, (offsetT) value,
671 fixP->fx_file, fixP->fx_line);
672 bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
673
674 if (fixP->fx_done)
675 {
676 /* Nothing else to do here. */
677 return 1;
678 }
679
680 /* Determine a BFD reloc value based on the operand information.
681 We are only prepared to turn a few of the operands into relocs. */
682 /* FIXME: This test is a hack. */
683 if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
684 {
685 assert ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0
686 && operand->bits == 11
687 && operand->shift == 0);
688 fixP->fx_r_type = BFD_RELOC_TXVU_11_PCREL;
689 }
690 else
691 {
692 as_bad_where (fixP->fx_file, fixP->fx_line,
693 "unresolved expression that must be resolved");
694 fixP->fx_done = 1;
695 return 1;
696 }
697 }
698 else
699 {
700 switch (fixP->fx_r_type)
701 {
702 case BFD_RELOC_8:
703 md_number_to_chars (where, value, 1);
704 break;
705 case BFD_RELOC_16:
706 md_number_to_chars (where, value, 2);
707 break;
708 case BFD_RELOC_32:
709 md_number_to_chars (where, value, 4);
710 break;
711 default:
712 abort ();
713 }
714 }
715
716 fixP->fx_addnumber = value;
717
718 return 1;
209fb346
DE
719}
720
721/* Translate internal representation of relocation info to BFD target
722 format. */
723
724arelent *
020ba60b 725tc_gen_reloc (section, fixP)
209fb346 726 asection *section;
020ba60b 727 fixS *fixP;
209fb346 728{
020ba60b
DE
729 arelent *reloc;
730
731 reloc = (arelent *) xmalloc (sizeof (arelent));
732
733 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
734 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
735 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
736 if (reloc->howto == (reloc_howto_type *) NULL)
737 {
738 as_bad_where (fixP->fx_file, fixP->fx_line,
739 "internal error: can't export reloc type %d (`%s')",
740 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
741 return NULL;
742 }
743
744 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
745
746 reloc->addend = fixP->fx_addnumber;
747
748 return reloc;
209fb346
DE
749}
750\f
751/* Write a value out to the object file, using the appropriate endianness. */
752
753void
754md_number_to_chars (buf, val, n)
755 char *buf;
756 valueT val;
757 int n;
758{
759 if (target_big_endian)
760 number_to_chars_bigendian (buf, val, n);
761 else
762 number_to_chars_littleendian (buf, val, n);
763}
764
765/* Turn a string in input_line_pointer into a floating point constant of type
766 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
767 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
768*/
769
770/* Equal to MAX_PRECISION in atof-ieee.c */
771#define MAX_LITTLENUMS 6
772
773char *
774md_atof (type, litP, sizeP)
775 char type;
776 char *litP;
777 int *sizeP;
778{
779 int i,prec;
780 LITTLENUM_TYPE words[MAX_LITTLENUMS];
781 LITTLENUM_TYPE *wordP;
782 char *t;
783 char *atof_ieee ();
784
785 switch (type)
786 {
787 case 'f':
788 case 'F':
789 case 's':
790 case 'S':
791 prec = 2;
792 break;
793
794 case 'd':
795 case 'D':
796 case 'r':
797 case 'R':
798 prec = 4;
799 break;
800
801 /* FIXME: Some targets allow other format chars for bigger sizes here. */
802
803 default:
804 *sizeP = 0;
805 return "Bad call to md_atof()";
806 }
807
808 t = atof_ieee (input_line_pointer, type, words);
809 if (t)
810 input_line_pointer = t;
811 *sizeP = prec * sizeof (LITTLENUM_TYPE);
812
813 if (target_big_endian)
814 {
815 for (i = 0; i < prec; i++)
816 {
817 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
818 litP += sizeof (LITTLENUM_TYPE);
819 }
820 }
821 else
822 {
823 for (i = prec - 1; i >= 0; i--)
824 {
825 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
826 litP += sizeof (LITTLENUM_TYPE);
827 }
828 }
829
830 return 0;
831}
020ba60b
DE
832\f
833/* Insert an operand value into an instruction. */
834
835static TXVU_INSN
836txvu_insert_operand (insn, operand, mods, val, file, line)
837 TXVU_INSN insn;
838 const struct txvu_operand *operand;
839 int mods;
840 offsetT val;
841 char *file;
842 unsigned int line;
843{
844 if (operand->bits != 32)
845 {
846 long min, max;
847 offsetT test;
848
849 if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
850 {
851 if ((val & 7) != 0)
852 {
853 if (file == (char *) NULL)
854 as_warn ("branch to misaligned address");
855 else
856 as_warn_where (file, line, "branch to misaligned address");
857 }
858 val >>= 3;
859 }
860
861 if ((operand->flags & TXVU_OPERAND_SIGNED) != 0)
862 {
863 if ((operand->flags & TXVU_OPERAND_SIGNOPT) != 0)
864 max = (1 << operand->bits) - 1;
865 else
866 max = (1 << (operand->bits - 1)) - 1;
867 min = - (1 << (operand->bits - 1));
868 }
869 else
870 {
871 max = (1 << operand->bits) - 1;
872 min = 0;
873 }
874
875 if ((operand->flags & TXVU_OPERAND_NEGATIVE) != 0)
876 test = - val;
877 else
878 test = val;
879
880 if (test < (offsetT) min || test > (offsetT) max)
881 {
882 const char *err =
883 "operand out of range (%s not between %ld and %ld)";
884 char buf[100];
885
886 sprint_value (buf, test);
887 if (file == (char *) NULL)
888 as_warn (err, buf, min, max);
889 else
890 as_warn_where (file, line, err, buf, min, max);
891 }
892 }
893
894 if (operand->insert)
895 {
f62a42d0 896 const char *errmsg = NULL;
f7306261 897 (*operand->insert) (&insn, operand, mods, (long) val, &errmsg);
020ba60b
DE
898 if (errmsg != (const char *) NULL)
899 as_warn (errmsg);
900 }
901 else
902 insn |= (((long) val & ((1 << operand->bits) - 1))
903 << operand->shift);
904
905 return insn;
906}
b5d20cf6
DE
907\f
908static void
63589bf4
JL
909s_dmadata( type)
910 int type;
b5d20cf6 911{
63589bf4 912 static short state = 0;
5fcbec8f
JL
913 static symbolS *label; /* Points to symbol */
914 char *name;
915 const char *prevName;
63589bf4
JL
916 int temp;
917
918 switch( type) {
919 case 1: /* .DmaData */
920 if( state != 0)
921 {
922 as_bad( "DmaData blocks cannot be nested.");
923 ignore_rest_of_line();
924 state = 1;
925 break;
926 }
927 state = 1;
928
929 SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
930 name = input_line_pointer;
931
932 if( !is_name_beginner( *name) )
933 {
934 as_bad( "invalid identifier for \".DmaData\"");
935 obstack_1grow (&cond_obstack, 0);
936 ignore_rest_of_line();
937 break;
938 }
939 else
940 {
941 char c;
b5d20cf6 942
63589bf4
JL
943 c = get_symbol_end();
944 line_label = label = colon( name); /* user-defined label */
945 *input_line_pointer = c;
946
947 demand_empty_rest_of_line();
948 } /* if a valid identifyer name */
949 break;
b5d20cf6 950
63589bf4
JL
951 case 0: /* .EndDmaData */
952 if( state != 1)
953 {
954 as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
955 ignore_rest_of_line();
956 state = 0;
957 break;
958 }
959 state = 0;
960 demand_empty_rest_of_line();
961
962 /*
963 *"label" points to beginning of block
964 * Create a name for the final label like _$<name>
965 */
5fcbec8f
JL
966 prevName = label->bsym->name;
967 temp = strlen( prevName) + 1;
968 name = malloc( temp + 2);
969 name[ 0] = '_';
970 name[ 1] = '$';
971 memcpy( name+2, prevName, temp); /* copy original name & \0 */
972 colon( name);
973 free( name);
63589bf4
JL
974 break;
975
976 default:
977 as_assert( __FILE__, __LINE__, 0);
978 }
b5d20cf6
DE
979}
980
981static void
63589bf4 982s_dmapackpke( ignore)
f7306261 983 int ignore;
b5d20cf6 984{
63589bf4
JL
985 /* Syntax: .dmapackpke 0|1 */
986 struct symbol *label; /* Points to symbol */
987 char *name; /* points to name of symbol */
988
989 SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
990 switch( *input_line_pointer++)
991 {
992 case 0:
993 dma_pack_pke_p = 0;
994 break;
995 case 1:
996 dma_pack_pke_p = 1;
997 break;
998 default:
999 as_bad( "illegal argument to `.DmaPackPke'");
1000 }
1001 demand_empty_rest_of_line();
b5d20cf6
DE
1002}
1003
1004static void
63589bf4 1005s_enddirect (ignore)
f7306261 1006 int ignore;
b5d20cf6
DE
1007{
1008}
1009
1010static void
f7306261
DE
1011s_endgpuif (ignore)
1012 int ignore;
b5d20cf6
DE
1013{
1014}
1015
1016static void
f7306261
DE
1017s_endmpg (ignore)
1018 int ignore;
b5d20cf6
DE
1019{
1020 vu_mode_p = 0;
1021}
1022
1023static void
f7306261
DE
1024s_endunpack (ignore)
1025 int ignore;
b5d20cf6
DE
1026{
1027 vu_mode_p = 0;
1028}
1029
1030static void
f7306261
DE
1031s_vu (enable_p)
1032 int enable_p;
b5d20cf6
DE
1033{
1034 vu_mode_p = enable_p;
1035}
This page took 0.067723 seconds and 4 git commands to generate.