* tc-txvu.c: First pass at dma/pke/gpuif support.
[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));
80static void s_enddmadata PARAMS ((int));
81static void s_endgpuif PARAMS ((int));
82static void s_endmpg PARAMS ((int));
83static void s_endunpack PARAMS ((int));
84static void s_vu PARAMS ((int));
85
209fb346
DE
86/* The target specific pseudo-ops which we support. */
87const pseudo_typeS md_pseudo_table[] =
88{
89 { "word", cons, 4 },
b5d20cf6
DE
90 { "dmadata", s_dmadata, 0 },
91 { "dmapackpke", s_dmapackpke, 0 },
92 { "enddirect", s_enddirect, 0 },
93 { "enddmadata", s_enddmadata, 0 },
94 { "endgpuif", s_endgpuif, 0 },
95 { "endmpg", s_endmpg, 0 },
96 { "endunpack", s_endunpack, 0 },
97 /* .vu,.endvu added to simplify debugging */
98 { "vu", s_vu, 1 },
99 { "endvu", s_vu, 0 },
209fb346
DE
100 { NULL, NULL, 0 }
101};
102\f
103void
104md_begin ()
105{
106 flagword applicable;
107 segT seg;
108 subsegT subseg;
109
110 /* Save the current subseg so we can restore it [it's the default one and
111 we don't want the initial section to be .sbss. */
112 seg = now_seg;
113 subseg = now_subseg;
114
115 subseg_set (seg, subseg);
f6428b86
DE
116
117 /* Initialize the opcode tables.
118 This involves computing the hash chains. */
119 txvu_opcode_init_tables (0);
b5d20cf6
DE
120
121 vu_mode_p = 0;
122 dma_pack_pke_p = 0;
209fb346 123}
f7306261
DE
124\f
125enum cputype { CPU_VUUP, CPU_VULO, CPU_DMA, CPU_PKE, CPU_GPUIF };
209fb346 126
f6428b86
DE
127/* We need to keep a list of fixups. We can't simply generate them as
128 we go, because that would require us to first create the frag, and
129 that would screw up references to ``.''. */
130
131struct txvu_fixup
132{
133 /* index into `txvu_operands' */
134 int opindex;
135 expressionS exp;
136};
137
138#define MAX_FIXUPS 5
139
f7306261
DE
140static int fixup_count;
141static struct txvu_fixup fixups[MAX_FIXUPS];
142
b5d20cf6
DE
143static void assemble_dma PARAMS ((char *));
144static void assemble_gpuif PARAMS ((char *));
145static void assemble_pke PARAMS ((char *));
146static void assemble_vu PARAMS ((char *));
f7306261
DE
147static char * assemble_vu_insn PARAMS ((enum cputype,
148 const struct txvu_opcode *,
149 const struct txvu_operand *,
150 char *, char *));
151static char * assemble_one_insn PARAMS ((enum cputype,
152 const struct txvu_opcode *,
153 const struct txvu_operand *,
154 char *, TXVU_INSN *));
f6428b86 155
209fb346
DE
156void
157md_assemble (str)
158 char *str;
b5d20cf6 159{
f7306261
DE
160 /* Skip leading white space. */
161 while (isspace (*str))
162 str++;
163
b5d20cf6
DE
164 if (! vu_mode_p)
165 {
166 if (strncasecmp (str, "dma", 3) == 0)
167 assemble_dma (str);
168 else if (strncasecmp (str, "gpuif", 5) == 0)
169 assemble_gpuif (str);
170 else
171 assemble_pke (str);
172 }
173 else
174 assemble_vu (str);
175}
176
f7306261 177/* Subroutine of md_assemble to assemble DMA instructions. */
b5d20cf6
DE
178
179static void
180assemble_dma (str)
181 char *str;
182{
f7306261
DE
183 TXVU_INSN buf[4];
184
185 assemble_one_insn (CPU_DMA,
186 dma_opcode_lookup_asm (str), dma_operands,
187 str, buf);
b5d20cf6
DE
188}
189
f7306261 190/* Subroutine of md_assemble to assemble PKE instructions. */
b5d20cf6
DE
191
192static void
f7306261 193assemble_pke (str)
b5d20cf6
DE
194 char *str;
195{
f7306261
DE
196 TXVU_INSN buf[4];
197
198 assemble_one_insn (CPU_PKE,
199 pke_opcode_lookup_asm (str), pke_operands,
200 str, buf);
b5d20cf6
DE
201}
202
f7306261 203/* Subroutine of md_assemble to assemble GPUIF instructions. */
b5d20cf6
DE
204
205static void
f7306261 206assemble_gpuif (str)
b5d20cf6
DE
207 char *str;
208{
f7306261
DE
209 TXVU_INSN buf[4];
210
211 assemble_one_insn (CPU_GPUIF,
212 gpuif_opcode_lookup_asm (str), gpuif_operands,
213 str, buf);
b5d20cf6
DE
214}
215
216/* Subroutine of md_assemble to assemble VU instructions. */
217
218static void
219assemble_vu (str)
220 char *str;
209fb346 221{
020ba60b
DE
222 /* The lower instruction has the lower address.
223 Handle this by grabbing 8 bytes now, and then filling each word
224 as appropriate. */
225 char *f = frag_more (8);
226
61e09fac 227#ifdef VERTICAL_BAR_SEPARATOR
f6428b86
DE
228 char *p = strchr (str, '|');
229
230 if (p == NULL)
231 {
232 as_bad ("lower slot missing in `%s'", str);
233 return;
234 }
235
236 *p = 0;
f7306261
DE
237 assemble_vu_insn (CPU_VUUP,
238 txvu_upper_opcode_lookup_asm (str), txvu_operands,
239 str, f + 4);
f6428b86 240 *p = '|';
f7306261
DE
241 assemble_vu_insn (CPU_VULO,
242 txvu_lower_opcode_lookup_asm (str), txvu_operands,
243 p + 1, f);
61e09fac 244#else
f7306261
DE
245 str = assemble_vu_insn (CPU_VUUP,
246 txvu_upper_opcode_lookup_asm (str), txvu_operands,
247 str, f + 4);
61e09fac
DE
248 /* Don't assemble next one if we couldn't assemble the first. */
249 if (str)
f7306261
DE
250 assemble_vu_insn (CPU_VULO,
251 txvu_lower_opcode_lookup_asm (str), txvu_operands,
252 str, f);
61e09fac 253#endif
f6428b86
DE
254}
255
61e09fac 256static char *
f7306261
DE
257assemble_vu_insn (cpu, opcode, operand_table, str, buf)
258 enum cputype cpu;
259 const struct txvu_opcode *opcode;
260 const struct txvu_operand *operand_table;
f6428b86 261 char *str;
020ba60b 262 char *buf;
f6428b86 263{
f7306261 264 int i;
f6428b86
DE
265 TXVU_INSN insn;
266
f7306261
DE
267 str = assemble_one_insn (cpu, opcode, operand_table, str, &insn);
268 if (str == NULL)
269 return NULL;
f6428b86 270
f7306261
DE
271 /* Write out the instruction.
272 Reminder: it is important to fetch enough space in one call to
273 `frag_more'. We use (f - frag_now->fr_literal) to compute where
274 we are and we don't want frag_now to change between calls. */
275 md_number_to_chars (buf, insn, 4);
f6428b86 276
f7306261
DE
277 /* Create any fixups. */
278 for (i = 0; i < fixup_count; ++i)
279 {
280 int op_type, reloc_type;
281 const struct txvu_operand *operand;
282
283 /* Create a fixup for this operand.
284 At this point we do not use a bfd_reloc_code_real_type for
285 operands residing in the insn, but instead just use the
286 operand index. This lets us easily handle fixups for any
287 operand type, although that is admittedly not a very exciting
288 feature. We pick a BFD reloc type in md_apply_fix. */
289
290 op_type = fixups[i].opindex;
291 reloc_type = op_type + (int) BFD_RELOC_UNUSED;
292 operand = &txvu_operands[op_type];
293 fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
294 &fixups[i].exp,
295 (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
296 (bfd_reloc_code_real_type) reloc_type);
297 }
298
299 /* All done. */
300 return str;
301}
302
303/* Assemble one instruction.
304 CPU indicates what component we're assembling for.
305 The assembled instruction is stored in INSN_BUF.
306
307 The result is a pointer to beyond the end of the scanned insn
308 or NULL if an error occured. This is to handle the VU where two
309 instructions appear on one line. If this is the upper insn, the caller
310 can pass back to result to us parse the lower insn. */
311
312static char *
313assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
314 enum cputype cpu;
315 const struct txvu_opcode *opcode;
316 const struct txvu_operand *operand_table;
317 char *str;
318 TXVU_INSN *insn_buf;
319{
320 char *start;
f6428b86
DE
321
322 /* Keep looking until we find a match. */
323
324 start = str;
325 for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_ASM (opcode))
326 {
f7306261 327 int past_opcode_p, num_suffixes, num_operands;
f6428b86 328 const unsigned char *syn;
f6428b86
DE
329
330 /* Ensure the mnemonic part matches. */
331 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
332 if (tolower (*str) != tolower (*syn))
333 break;
334 if (*syn != '\0')
335 continue;
f6428b86
DE
336
337 /* Scan the syntax string. If it doesn't match, try the next one. */
338
339 txvu_opcode_init_parse ();
f7306261
DE
340 *insn_buf = opcode->value;
341 fixup_count = 0;
f6428b86
DE
342 past_opcode_p = 0;
343 num_suffixes = 0;
344 num_operands = 0;
345
346 /* We don't check for (*str != '\0') here because we want to parse
347 any trailing fake arguments in the syntax string. */
348 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
349 {
350 int mods,index;
351 const struct txvu_operand *operand;
352 const char *errmsg;
353
fbe2ad46
DE
354 /* Non operand chars must match exactly.
355 Operand chars that are letters are not part of symbols
356 and are case insensitive. */
f6428b86
DE
357 if (*syn < 128)
358 {
fbe2ad46 359 if (tolower (*str) == tolower (*syn))
f6428b86
DE
360 {
361 if (*syn == ' ')
362 past_opcode_p = 1;
363 ++syn;
364 ++str;
365 }
366 else
367 break;
368 continue;
369 }
370
371 /* We have a suffix or an operand. Pick out any modifiers. */
372 mods = 0;
373 index = TXVU_OPERAND_INDEX (*syn);
f7306261 374 while (TXVU_MOD_P (operand_table[index].flags))
f6428b86 375 {
f7306261 376 mods |= operand_table[index].flags & TXVU_MOD_BITS;
f6428b86
DE
377 ++syn;
378 index = TXVU_OPERAND_INDEX (*syn);
379 }
f7306261 380 operand = operand_table + index;
f6428b86
DE
381
382 if (operand->flags & TXVU_OPERAND_FAKE)
383 {
384 if (operand->insert)
385 {
f62a42d0 386 errmsg = NULL;
f7306261 387 (*operand->insert) (insn_buf, operand, mods, 0, &errmsg);
f6428b86
DE
388 /* If we get an error, go on to try the next insn. */
389 if (errmsg)
390 break;
391 }
392 ++syn;
393 }
394 /* Are we finished with suffixes? */
395 else if (!past_opcode_p)
396 {
397 int found;
398 char c;
399 char *s,*t;
400 long suf_value;
401
402 if (!(operand->flags & TXVU_OPERAND_SUFFIX))
403 as_fatal ("bad opcode table, missing suffix flag");
404
405 /* If we're at a space in the input string, we want to skip the
406 remaining suffixes. There may be some fake ones though, so
407 just go on to try the next one. */
408 if (*str == ' ')
409 {
410 ++syn;
411 continue;
412 }
413
414 s = str;
415
416 /* Pick the suffix out and parse it. */
fbe2ad46
DE
417 /* ??? Hmmm ... there may not be any need to nul-terminate the
418 string, and it may in fact complicate things. */
f6428b86
DE
419 for (t = *s == '.' ? s + 1 : s; *t && isalpha (*t); ++t)
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
f7306261
DE
909s_dmadata (ignore)
910 int ignore;
b5d20cf6
DE
911{
912}
913
914static void
f7306261
DE
915s_dmapackpke (ignore)
916 int ignore;
b5d20cf6
DE
917{
918 /* Syntax: .dmapackpke 0|1 */
919 if (*input_line_pointer == '0')
920 dma_pack_pke_p = 0;
921 else if (*input_line_pointer == '1')
922 dma_pack_pke_p = 1;
923 else
924 as_bad ("illegal argument to `.dmapackpke'");
925
926 input_line_pointer++;
927 demand_empty_rest_of_line ();
928}
929
930static void
f7306261
DE
931s_enddirect (ignore)
932 int ignore;
b5d20cf6
DE
933{
934}
935
936static void
f7306261
DE
937s_enddmadata (ignore)
938 int ignore;
b5d20cf6
DE
939{
940}
941
942static void
f7306261
DE
943s_endgpuif (ignore)
944 int ignore;
b5d20cf6
DE
945{
946}
947
948static void
f7306261
DE
949s_endmpg (ignore)
950 int ignore;
b5d20cf6
DE
951{
952 vu_mode_p = 0;
953}
954
955static void
f7306261
DE
956s_endunpack (ignore)
957 int ignore;
b5d20cf6
DE
958{
959 vu_mode_p = 0;
960}
961
962static void
f7306261
DE
963s_vu (enable_p)
964 int enable_p;
b5d20cf6
DE
965{
966 vu_mode_p = enable_p;
967}
This page took 0.062633 seconds and 4 git commands to generate.