OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-or32.c] - Blame information for rev 205

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* Assembly backend for the OpenRISC 1000.
2
   Copyright (C) 2002, 2003, 2005, 2007, 2009
3
   Free Software Foundation, Inc.
4
   Contributed by Damjan Lampret <lampret@opencores.org>.
5
   Modified bu Johan Rydberg, <johan.rydberg@netinsight.se>.
6
               Gyorgy Jeney <nog@sdf.lonestar.org>
7
   Based upon a29k port.
8
 
9
   This file is part of GAS, the GNU Assembler.
10
 
11
   GAS is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3, or (at your option)
14
   any later version.
15
 
16
   GAS is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
 
21
   You should have received a copy of the GNU General Public License
22
   along with GAS; see the file COPYING.  If not, write to
23
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
24
   Boston, MA 02110-1301, USA.  */
25
 
26
/* tc-a29k.c used as a template.  */
27
 
28
#include "safe-ctype.h"
29
#include "as.h"
30
#include "opcode/or32.h"
31
#include "struc-symbol.h"
32
#include "elf/or32.h"
33
 
34
#define DEBUG 0
35
 
36
#ifndef REGISTER_PREFIX
37
#define REGISTER_PREFIX   '%'
38
#endif
39
 
40
/* Make it easier to clone this machine desc into another one.  */
41
#define machine_opcode  or32_opcode
42
#define machine_opcodes or32_opcodes
43
#define machine_ip      or32_ip
44
#define machine_it      or32_it
45
 
46
/* Handle of the OPCODE hash table.  */
47
static struct hash_control *op_hash = NULL;
48
 
49
struct machine_it
50
{
51
  char *          error;
52
  unsigned long   opcode;
53
  struct nlist *  nlistp;
54
  expressionS     exp;
55
  int             pcrel;
56
  int             reloc;
57
}
58
the_insn;
59
 
60
const pseudo_typeS md_pseudo_table[] =
61
{
62
  {"align",   s_align_bytes,  4 },
63
  {"space",   s_space,        0 },
64
  {"cputype", s_ignore,       0 },
65
  {"reg",     s_lsym,         0 },  /* Register equate, same as equ.  */
66
  {"sect",    s_ignore,       0 },  /* Creation of coff sections.  */
67
  {"proc",    s_ignore,       0 },  /* Start of a function.  */
68
  {"endproc", s_ignore,       0 },  /* Function end.  */
69
  {"half",    cons,           2 },
70
  {"word",    cons,           4 },
71
  {NULL,      0,              0 },
72
};
73
 
74
int md_short_jump_size  = 4;
75
int md_long_jump_size   = 4;
76
 
77
/* This array holds the chars that always start a comment.
78
   If the pre-processor is disabled, these aren't very useful.  */
79
const char comment_chars[] = "#";
80
 
81
/* This array holds the chars that only start a comment at the beginning of
82
   a line.  If the line seems to have the form '# 123 filename'
83
   .line and .file directives will appear in the pre-processed output.  */
84
/* Note that input_file.c hand checks for '#' at the beginning of the
85
   first line of the input file.  This is because the compiler outputs
86
   #NO_APP at the beginning of its output.  */
87
/* Also note that comments like this one will always work.  */
88
const char line_comment_chars[] = "#";
89
 
90
/* We needed an unused char for line separation to work around the
91
   lack of macros, using sed and such.  */
92
const char line_separator_chars[] = ";";
93
 
94
/* Chars that can be used to separate mant from exp in floating point nums.  */
95
const char EXP_CHARS[] = "eE";
96
 
97
/* Chars that mean this number is a floating point constant.
98
   As in 0f12.456
99
   or    0d1.2345e12.  */
100
const char FLT_CHARS[] = "rRsSfFdDxXpP";
101
 
102
/* "l.jalr r9" precalculated opcode.  */
103
static unsigned long jalr_r9_opcode;
104
 
105
static void machine_ip (char *);
106
 
107
 
108
/* Set bits in machine opcode according to insn->encoding
109
   description and passed operand.  */
110
 
111
static void
112
encode (const struct machine_opcode *insn,
113
        unsigned long *opcode,
114
        signed long param_val,
115
        char param_ch)
116
{
117
  int opc_pos = 0;
118
  int param_pos = 0;
119
  char *enc;
120
 
121
#if DEBUG
122
  printf ("    encode:  opcode=%.8x  param_val=%.8x abs=%.8x param_ch=%c\n",
123
          (unsigned int) *opcode,(unsigned int) param_val, abs (param_val), param_ch);
124
#endif
125
  for (enc = insn->encoding; *enc != '\0'; enc++)
126
    if (*enc == param_ch)
127
      {
128
        if (enc - 2 >= insn->encoding && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
129
          continue;
130
        else
131
          param_pos ++;
132
      }
133
 
134
  opc_pos = 32;
135
 
136
  for (enc = insn->encoding; *enc != '\0';)
137
    {
138
      if ((*enc == '0') && (*(enc + 1) == 'x'))
139
        {
140
          int tmp = strtol (enc, NULL, 16);
141
 
142
          opc_pos -= 4;
143
          *opcode |= tmp << opc_pos;
144
          enc += 3;
145
        }
146
      else if ((*enc == '0') || (*enc == '-'))
147
        {
148
          opc_pos--;
149
          enc++;
150
        }
151
      else if (*enc == '1')
152
        {
153
          opc_pos--;
154
          *opcode |= 1 << opc_pos;
155
          enc++;
156
        }
157
      else if (*enc == param_ch)
158
        {
159
          opc_pos--;
160
          param_pos--;
161
          *opcode |= ((param_val >> param_pos) & 0x1) << opc_pos;
162
          enc++;
163
        }
164
      else if (ISALPHA (*enc))
165
        {
166
          opc_pos--;
167
          enc++;
168
        }
169
      else
170
        enc++;
171
    }
172
 
173
#if DEBUG
174
  printf ("    opcode=%.8lx\n", *opcode);
175
#endif
176
}
177
 
178
/* This function is called once, at assembler startup time.  It should
179
   set up all the tables, etc., that the MD part of the assembler will
180
   need.  */
181
 
182
void
183
md_begin (void)
184
{
185
  const char *retval = NULL;
186
  int lose = 0;
187
  int skipnext = 0;
188
  unsigned int i;
189
 
190
  /* Hash up all the opcodes for fast use later.  */
191
  op_hash = hash_new ();
192
 
193
  for (i = 0; i < or32_num_opcodes; i++)
194
    {
195
      const char *name = machine_opcodes[i].name;
196
 
197
      if (skipnext)
198
        {
199
          skipnext = 0;
200
          continue;
201
        }
202
 
203
      retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]);
204
      if (retval != NULL)
205
        {
206
          fprintf (stderr, "internal error: can't hash `%s': %s\n",
207
                   machine_opcodes[i].name, retval);
208
          lose = 1;
209
        }
210
    }
211
 
212
  if (lose)
213
    as_fatal (_("Broken assembler.  No assembly attempted."));
214
 
215
  encode (&machine_opcodes[insn_index ("l.jalr")], &jalr_r9_opcode, 9, 'B');
216
}
217
 
218
/* Returns non zero if instruction is to be used.  */
219
 
220
static int
221
check_invalid_opcode (unsigned long opcode)
222
{
223
  return opcode == jalr_r9_opcode;
224
}
225
 
226
/* Assemble a single instruction.  Its label has already been handled
227
   by the generic front end.  We just parse opcode and operands, and
228
   produce the bytes of data and relocation.  */
229
 
230
void
231
md_assemble (char *str)
232
{
233
  char *toP;
234
 
235
#if DEBUG
236
  printf ("NEW INSTRUCTION\n");
237
#endif
238
 
239
  know (str);
240
  machine_ip (str);
241
  toP = frag_more (4);
242
 
243
  /* Put out the opcode.  */
244
  md_number_to_chars (toP, the_insn.opcode, 4);
245
 
246
  /* Put out the symbol-dependent stuff.  */
247
  if (the_insn.reloc != BFD_RELOC_NONE)
248
    {
249
      fix_new_exp (frag_now,
250
                   (toP - frag_now->fr_literal),
251
                   4,   /* size */
252
                   &the_insn.exp,
253
                   the_insn.pcrel,
254
                   the_insn.reloc);
255
    }
256
}
257
 
258
static int mask_or_shift = 0;
259
 
260
static char *
261
parse_operand (char *s, expressionS *operandp, int opt)
262
{
263
  char *save = input_line_pointer;
264
  char *new_pointer;
265
 
266
#if DEBUG
267
  printf ("  PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt);
268
#endif
269
 
270
  input_line_pointer = s;
271
 
272
  if (strncasecmp (s, "HI(", 3) == 0)
273
    {
274
      mask_or_shift = BFD_RELOC_HI16;
275
 
276
      input_line_pointer += 3;
277
    }
278
  else if (strncasecmp (s, "LO(", 3) == 0)
279
    {
280
      mask_or_shift = BFD_RELOC_LO16;
281
 
282
      input_line_pointer += 3;
283
    }
284
  else
285
    mask_or_shift = 0;
286
 
287
  if ((*s == '(') && (*(s+1) == 'r'))
288
    s++;
289
 
290
  if ((*s == 'r') && ISDIGIT (*(s + 1)))
291
    {
292
      operandp->X_add_number = strtol (s + 1, NULL, 10);
293
      operandp->X_op = O_register;
294
      operandp->X_op_symbol = NULL; // Added to stop a know() in machine_ip()
295
                                    // erroring out - it appears this wasn't 
296
                                    // getting cleared sometimes. - JB 100718
297
      for (; (*s != ',') && (*s != '\0');)
298
        s++;
299
      input_line_pointer = save;
300
      return s;
301
    }
302
 
303
  expression (operandp);
304
 
305
  if (operandp->X_op == O_absent)
306
    {
307
      if (! opt)
308
        as_bad (_("missing operand"));
309
      else
310
        {
311
          operandp->X_add_number = 0;
312
          operandp->X_op = O_constant;
313
        }
314
    }
315
 
316
  new_pointer = input_line_pointer;
317
  input_line_pointer = save;
318
 
319
#if DEBUG
320
  printf ("  %s=parse_operand(%s): operandp->X_op = %u\n", new_pointer, s,
321
          operandp->X_op);
322
#endif
323
 
324
  return new_pointer;
325
}
326
 
327
/* Instruction parsing.  Takes a string containing the opcode.
328
   Operands are at input_line_pointer.  Output is in the_insn.
329
   Warnings or errors are generated.  */
330
 
331
static void
332
machine_ip (char *str)
333
{
334
  char *s;
335
  const char *args;
336
  const struct machine_opcode *insn;
337
  unsigned long opcode;
338
  expressionS operand;
339
  int reloc = BFD_RELOC_NONE;
340
 
341
#if DEBUG
342
  printf ("machine_ip(%s)\n", str);
343
#endif
344
 
345
  s = str;
346
  for (; ISALNUM (*s) || *s == '.' || *s == '_'; ++s)
347
    if (ISUPPER (*s))
348
      *s = TOLOWER (*s);
349
 
350
  switch (*s)
351
    {
352
    case '\0':
353
      break;
354
 
355
    case ' ':     /* FIXME-SOMEDAY more whitespace.  */
356
      *s++ = '\0';
357
      break;
358
 
359
    default:
360
      as_bad (_("unknown opcode1: `%s'"), str);
361
      return;
362
    }
363
 
364
  if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
365
    {
366
      as_bad (_("unknown opcode2 `%s'."), str);
367
      return;
368
    }
369
 
370
  opcode = 0;
371
  memset (&the_insn, '\0', sizeof (the_insn));
372
  the_insn.reloc = BFD_RELOC_NONE;
373
 
374
  reloc = BFD_RELOC_NONE;
375
 
376
  /* Build the opcode, checking as we go to make sure that the
377
     operands match.
378
 
379
     If an operand matches, we modify the_insn or opcode appropriately,
380
     and do a "continue".  If an operand fails to match, we "break".  */
381
  if (insn->args[0] != '\0')
382
    /* Prime the pump.  */
383
    s = parse_operand (s,
384
                       &operand,
385
                       (insn->args[0] == 'I') ||
386
                       (strcmp(insn->name, "l.nop") == 0) );
387
 
388
  for (args = insn->args;; ++args)
389
    {
390
#if DEBUG
391
      printf ("  args = %s\n", args);
392
#endif
393
      switch (*args)
394
        {
395
        case '\0':    /* End of args.  */
396
          /* We have have 0 args, do the bazoooka!  */
397
          if (args == insn->args)
398
            encode (insn, &opcode, 0, 0);
399
 
400
          if (*s == '\0')
401
            {
402
              /* We are truly done.  */
403
              the_insn.opcode = opcode;
404
              if (check_invalid_opcode (opcode))
405
                as_bad (_("instruction not allowed: %s"), str);
406
              return;
407
            }
408
          as_bad (_("too many operands: %s"), s);
409
          break;
410
 
411
        case ',':   /* Must match a comma.  */
412
          if (*s++ == ',')
413
            {
414
              reloc = BFD_RELOC_NONE;
415
 
416
              /* Parse next operand.  */
417
              s = parse_operand (s, &operand, args[1] == 'I');
418
#if DEBUG
419
              printf ("    ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n",
420
                      (int) operand.X_add_number, args, s);
421
#endif
422
              continue;
423
            }
424
          break;
425
 
426
        case '(':   /* Must match a (.  */
427
          s = parse_operand (s, &operand, args[1] == 'I');
428
          continue;
429
 
430
        case ')':   /* Must match a ).  */
431
          continue;
432
 
433
        case 'r':   /* A general register.  */
434
          args++;
435
 
436
          if (operand.X_op != O_register)
437
            break;    /* Only registers.  */
438
#if DEBUG
439
          printf("   (operand.X_add_symbol == 0)=%d",
440
                 (operand.X_add_symbol == NULL));
441
          printf("   (operand.X_op_symbol(%x) == 0)=%d",
442
                 (unsigned int)operand.X_op_symbol,
443
                 (operand.X_op_symbol == NULL));
444
#endif    
445
          know (operand.X_add_symbol == NULL);
446
          know (operand.X_op_symbol == NULL);
447
          encode (insn, &opcode, operand.X_add_number, *args);
448
#if DEBUG
449
          printf ("    r: operand->X_op = %d\n", operand.X_op);
450
#endif
451
          continue;
452
 
453
        default:
454
          if (mask_or_shift)
455
            {
456
#if DEBUG
457
              printf ("mask_or_shift = %d\n", mask_or_shift);
458
#endif
459
              reloc = mask_or_shift;
460
            }
461
          mask_or_shift = 0;
462
          if (*s == '(')
463
            operand.X_op = O_constant;
464
          else if (*s == ')')
465
            s += 1;
466
#if DEBUG
467
          printf ("    default case: operand->X_add_number = %d, *args = %s, *s = %s\n",(int) operand.X_add_number, args, s);
468
#endif
469
          if (operand.X_op == O_constant)
470
            {
471
            unsigned long add = operand.X_add_number;
472
              if (reloc == BFD_RELOC_NONE)
473
                {
474
                  bfd_vma v, mask;
475
 
476
                  mask = 0x3ffffff;
477
                  v = abs (operand.X_add_number) & ~ mask;
478
                  if (v)
479
                    as_bad (_("call/jmp target out of range (1)"));
480
                }
481
 
482
              if (reloc == BFD_RELOC_HI16)
483
                add = ((operand.X_add_number >> 16) & 0xffff);
484
 
485
              the_insn.pcrel = 0;
486
              encode (insn, &opcode, add, *args);
487
              continue;
488
            }
489
 
490
          if (reloc == BFD_RELOC_NONE)
491
            the_insn.reloc = BFD_RELOC_28_PCREL_S2;
492
          else
493
            the_insn.reloc = reloc;
494
 
495
          /* the_insn.reloc = insn->reloc;  */
496
#if DEBUG
497
          printf ("    reloc sym=%d\n", the_insn.reloc);
498
          printf ("    BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE);
499
#endif
500
          the_insn.exp = operand;
501
 
502
          /*  the_insn.reloc_offset = 1;  */
503
          the_insn.pcrel = 1; /* Assume PC-relative jump.  */
504
 
505
          /* FIXME-SOON, Do we figure out whether abs later, after
506
             know sym val?  */
507
          if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16)
508
            the_insn.pcrel = 0;
509
 
510
          if (reloc == BFD_RELOC_NONE)
511
            encode (insn, &opcode, operand.X_add_number, *args);
512
          else
513
            encode (insn, &opcode, 0, *args);
514
          continue;
515
        }
516
 
517
      /* Types or values of args don't match.  */
518
      as_bad (_("invalid operands"));
519
      return;
520
    }
521
}
522
 
523
char *
524
md_atof (int type, char * litP, int *  sizeP)
525
{
526
  return ieee_md_atof (type, litP, sizeP, TRUE);
527
}
528
 
529
/* Write out big-endian.  */
530
 
531
void
532
md_number_to_chars (char *buf, valueT val, int n)
533
{
534
  number_to_chars_bigendian (buf, val, n);
535
}
536
 
537
void
538
md_apply_fix (fixS * fixP, valueT * val, segT seg ATTRIBUTE_UNUSED)
539
{
540
  bfd_byte *buf;
541
  long insn;
542
 
543
  buf = (bfd_byte *) (fixP->fx_where + fixP->fx_frag->fr_literal);
544
 
545
#if DEBUG
546
  printf ("md_apply_fix *val=%x fixP->fx_r_type=%i sym=%s\n",(unsigned int)*val,
547
           fixP->fx_r_type, fixP->fx_addsy ? fixP->fx_addsy->bsym->name : "(none)");
548
#endif
549
 
550
  if ((fixP->fx_addsy == (symbolS *) NULL) && !fixP->fx_pcrel)
551
    fixP->fx_done = 1;
552
 
553
  switch (fixP->fx_r_type)
554
    {
555
    case BFD_RELOC_32:      /* XXXXXXXX pattern in a word.  */
556
#if DEBUG
557
      printf ("reloc_const: val=%x\n", (unsigned int) *val);
558
#endif
559
      /* If we are deleting this reloc entry, we must fill in the
560
               value now.  This can happen if we have a .word which is not
561
               resolved when it appears but is later defined.  We also need
562
               to fill in the value if this is an embedded PIC switch table
563
               entry.  */
564
      if (fixP->fx_done)
565
        md_number_to_chars ((char *) buf, *val, 4);
566
      break;
567
 
568
    case BFD_RELOC_16:      /* XXXX0000 pattern in a word.  */
569
#if DEBUG
570
      printf ("reloc_const: val=%x\n", (unsigned int)*val);
571
#endif
572
      /* If we are deleting this reloc entry, we must fill in the
573
         value now.  */
574
      gas_assert (fixP->fx_size == 2);
575
      if (fixP->fx_done)
576
              md_number_to_chars ((char *) buf, *val, 2);
577
      break;
578
 
579
    case BFD_RELOC_8:      /* XX000000 pattern in a word.  */
580
    case BFD_RELOC_LO16:      /* 0000XXXX pattern in a word.  */
581
#if DEBUG
582
      printf ("reloc_const: val=%x\n", (unsigned int)*val);
583
#endif
584
      break;
585
 
586
    case BFD_RELOC_HI16:    /* 0000XXXX pattern in a word.  */
587
#if DEBUG
588
      printf ("reloc_consth: val=%x\n", (unsigned int)*val);
589
#endif
590
      break;
591
 
592
    case BFD_RELOC_28_PCREL_S2:  /* 0000XXXX pattern in a word.  */
593
#if DEBUG
594
      printf("reloc_pcrel: *val=%x done=%d fixP->fx_pcrel=%i line=%i\n",
595
             (unsigned int) *val, fixP->fx_done, fixP->fx_pcrel, fixP->fx_line);
596
#endif
597
      if ((*val & 0x3) != 0)
598
        as_bad_where (fixP->fx_file, fixP->fx_line,
599
                      _("Branch to odd address (%lx)"), (long) *val);
600
 
601
      /*
602
       * We need to save the bits in the instruction since fixup_segment()
603
       * might be deleting the relocation entry (i.e., a branch within
604
       * the current segment).
605
       */
606
      if (! fixP->fx_done)
607
        break;
608
 
609
      /* update old instruction data */
610
      if (target_big_endian)
611
        insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
612
      else
613
        insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
614
      insn |= (*val >> 2) & 0x03ffffff;
615
      md_number_to_chars ((char *) buf, insn, 4);
616
#if DEBUG
617
      printf("Resulting instruction: %08x\n", (unsigned int)insn);
618
#endif
619
      break;
620
 
621
    case BFD_RELOC_VTABLE_INHERIT:
622
    case BFD_RELOC_VTABLE_ENTRY:
623
      fixP->fx_done = 0;
624
      break;
625
 
626
    case BFD_RELOC_NONE:
627
    default:
628
      as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
629
      break;
630
    }
631
 
632
  fixP->fx_addnumber = *val; /* Remember value for emit_reloc.  */
633
}
634
 
635
/* Should never be called for or32.  */
636
 
637
void
638
md_create_short_jump (char *    ptr       ATTRIBUTE_UNUSED,
639
                      addressT  from_addr ATTRIBUTE_UNUSED,
640
                      addressT  to_addr   ATTRIBUTE_UNUSED,
641
                      fragS *   frag      ATTRIBUTE_UNUSED,
642
                      symbolS * to_symbol ATTRIBUTE_UNUSED)
643
{
644
  as_fatal ("or32_create_short_jmp\n");
645
}
646
 
647
/* Should never be called for or32.  */
648
 
649
void
650
md_convert_frag (bfd *   headers ATTRIBUTE_UNUSED,
651
                 segT    seg     ATTRIBUTE_UNUSED,
652
                 fragS * fragP   ATTRIBUTE_UNUSED)
653
{
654
  as_fatal ("or32_convert_frag\n");
655
}
656
 
657
/* Should never be called for or32.  */
658
 
659
void
660
md_create_long_jump (char *    ptr       ATTRIBUTE_UNUSED,
661
                     addressT  from_addr ATTRIBUTE_UNUSED,
662
                     addressT  to_addr   ATTRIBUTE_UNUSED,
663
                     fragS *   frag      ATTRIBUTE_UNUSED,
664
                     symbolS * to_symbol ATTRIBUTE_UNUSED)
665
{
666
  as_fatal ("or32_create_long_jump\n");
667
}
668
 
669
/* Should never be called for or32.  */
670
 
671
int
672
md_estimate_size_before_relax (fragS * fragP   ATTRIBUTE_UNUSED,
673
                               segT    segtype ATTRIBUTE_UNUSED)
674
{
675
  as_fatal ("or32_estimate_size_before_relax\n");
676
  return 0;
677
}
678
 
679
/* Translate internal representation of relocation info to target format.
680
 
681
   On sparc/29k: first 4 bytes are normal unsigned long address, next three
682
   bytes are index, most sig. byte first.  Byte 7 is broken up with
683
   bit 7 as external, bits 6 & 5 unused, and the lower
684
   five bits as relocation type.  Next 4 bytes are long addend.  */
685
/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com.  */
686
 
687
#ifdef OBJ_AOUT
688
void
689
tc_aout_fix_to_chars (char *where,
690
                      fixS *fixP,
691
                      relax_addressT segment_address_in_file)
692
{
693
  long r_symbolnum;
694
 
695
#if DEBUG
696
  printf ("tc_aout_fix_to_chars\n");
697
#endif
698
 
699
  know (fixP->fx_r_type < BFD_RELOC_NONE);
700
  know (fixP->fx_addsy != NULL);
701
 
702
  md_number_to_chars
703
    (where,
704
     fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
705
     4);
706
 
707
  r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
708
     ? S_GET_TYPE (fixP->fx_addsy)
709
     : fixP->fx_addsy->sy_number);
710
 
711
  where[4] = (r_symbolnum >> 16) & 0x0ff;
712
  where[5] = (r_symbolnum >> 8) & 0x0ff;
713
  where[6] = r_symbolnum & 0x0ff;
714
  where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
715
 
716
  /* Also easy.  */
717
  md_number_to_chars (&where[8], fixP->fx_addnumber, 4);
718
}
719
 
720
#endif /* OBJ_AOUT */
721
 
722
const char *md_shortopts = "";
723
 
724
struct option md_longopts[] =
725
{
726
  { NULL, no_argument, NULL, 0 }
727
};
728
size_t md_longopts_size = sizeof (md_longopts);
729
 
730
int
731
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
732
{
733
  return 0;
734
}
735
 
736
void
737
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
738
{
739
}
740
 
741
/* This is called when a line is unrecognized.  This is used to handle
742
   definitions of or32 style local labels.  */
743
 
744
int
745
or32_unrecognized_line (int c)
746
{
747
  int lab;
748
  char *s;
749
 
750
  if (c != '$'
751
      || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
752
    return 0;
753
 
754
  s = input_line_pointer;
755
 
756
  lab = 0;
757
  while (ISDIGIT ((unsigned char) *s))
758
    {
759
      lab = lab * 10 + *s - '0';
760
      ++s;
761
    }
762
 
763
  if (*s != ':')
764
    /* Not a label definition.  */
765
    return 0;
766
 
767
  if (dollar_label_defined (lab))
768
    {
769
      as_bad (_("label \"$%d\" redefined"), lab);
770
      return 0;
771
    }
772
 
773
  define_dollar_label (lab);
774
  colon (dollar_label_name (lab, 0));
775
  input_line_pointer = s + 1;
776
 
777
  return 1;
778
}
779
 
780
/* Default the values of symbols known that should be "predefined".  We
781
   don't bother to predefine them unless you actually use one, since there
782
   are a lot of them.  */
783
 
784
symbolS *
785
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
786
{
787
  return NULL;
788
}
789
 
790
/* Parse an operand that is machine-specific.  */
791
 
792
void
793
md_operand (expressionS *expressionP)
794
{
795
#if DEBUG
796
  printf ("  md_operand(input_line_pointer = %s)\n", input_line_pointer);
797
#endif
798
 
799
  if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r')
800
    {
801
      /* We have a numeric register expression.  No biggy.  */
802
      input_line_pointer += 2;  /* Skip %r */
803
      (void) expression (expressionP);
804
 
805
      if (expressionP->X_op != O_constant
806
          || expressionP->X_add_number > 255)
807
        as_bad (_("Invalid expression after %%%%\n"));
808
      expressionP->X_op = O_register;
809
    }
810
  else if (input_line_pointer[0] == '&')
811
    {
812
      /* We are taking the 'address' of a register...this one is not
813
         in the manual, but it *is* in traps/fpsymbol.h!  What they
814
         seem to want is the register number, as an absolute number.  */
815
      input_line_pointer++; /* Skip & */
816
      (void) expression (expressionP);
817
 
818
      if (expressionP->X_op != O_register)
819
        as_bad (_("invalid register in & expression"));
820
      else
821
        expressionP->X_op = O_constant;
822
    }
823
  else if (input_line_pointer[0] == '$'
824
           && ISDIGIT ((unsigned char) input_line_pointer[1]))
825
    {
826
      long lab;
827
      char *name;
828
      symbolS *sym;
829
 
830
      /* This is a local label.  */
831
      ++input_line_pointer;
832
      lab = (long) get_absolute_expression ();
833
 
834
      if (dollar_label_defined (lab))
835
        {
836
          name = dollar_label_name (lab, 0);
837
          sym = symbol_find (name);
838
        }
839
      else
840
        {
841
          name = dollar_label_name (lab, 1);
842
          sym = symbol_find_or_make (name);
843
        }
844
 
845
      expressionP->X_op = O_symbol;
846
      expressionP->X_add_symbol = sym;
847
      expressionP->X_add_number = 0;
848
    }
849
  else if (input_line_pointer[0] == '$')
850
    {
851
      char *s;
852
      char type;
853
      int fieldnum, fieldlimit;
854
      LITTLENUM_TYPE floatbuf[8];
855
 
856
      /* $float(), $doubleN(), or $extendN() convert floating values
857
         to integers.  */
858
      s = input_line_pointer;
859
 
860
      ++s;
861
 
862
      fieldnum = 0;
863
      if (strncmp (s, "double", sizeof "double" - 1) == 0)
864
        {
865
          s += sizeof "double" - 1;
866
          type = 'd';
867
          fieldlimit = 2;
868
        }
869
      else if (strncmp (s, "float", sizeof "float" - 1) == 0)
870
        {
871
          s += sizeof "float" - 1;
872
          type = 'f';
873
          fieldlimit = 1;
874
        }
875
      else if (strncmp (s, "extend", sizeof "extend" - 1) == 0)
876
        {
877
          s += sizeof "extend" - 1;
878
          type = 'x';
879
          fieldlimit = 4;
880
        }
881
      else
882
        return;
883
 
884
      if (ISDIGIT (*s))
885
        {
886
          fieldnum = *s - '0';
887
          ++s;
888
        }
889
      if (fieldnum >= fieldlimit)
890
        return;
891
 
892
      SKIP_WHITESPACE ();
893
      if (*s != '(')
894
        return;
895
      ++s;
896
      SKIP_WHITESPACE ();
897
 
898
      s = atof_ieee (s, type, floatbuf);
899
      if (s == NULL)
900
        return;
901
      s = s;
902
 
903
      SKIP_WHITESPACE ();
904
      if (*s != ')')
905
        return;
906
      ++s;
907
      SKIP_WHITESPACE ();
908
 
909
      input_line_pointer = s;
910
      expressionP->X_op = O_constant;
911
      expressionP->X_unsigned = 1;
912
      expressionP->X_add_number = ((floatbuf[fieldnum * 2]
913
                                    << LITTLENUM_NUMBER_OF_BITS)
914
                                   + floatbuf[fieldnum * 2 + 1]);
915
    }
916
}
917
 
918
/* Round up a section size to the appropriate boundary.  */
919
 
920
valueT
921
md_section_align (asection * seg, valueT addr ATTRIBUTE_UNUSED)
922
{
923
  int align = bfd_get_section_alignment (stdoutput, seg);
924
  return ((addr + (1 << align) - 1) & (-1 << align));
925
}
926
 
927
/* Exactly what point is a PC-relative offset relative TO?
928
   On the 29000, they're relative to the address of the instruction,
929
   which we have set up as the address of the fixup too.  */
930
 
931
long
932
md_pcrel_from (fixS *fixP)
933
{
934
  return fixP->fx_where + fixP->fx_frag->fr_address;
935
}
936
 
937
/* Generate a reloc for a fixup.  */
938
 
939
arelent *
940
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
941
{
942
  arelent *reloc;
943
 
944
  reloc = xmalloc (sizeof (arelent));
945
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
946
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
947
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
948
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
949
 
950
  if (reloc->howto == (reloc_howto_type *) NULL)
951
    {
952
      as_bad_where (fixp->fx_file, fixp->fx_line,
953
                    _("reloc %d not supported by object file format"),
954
                    (int) fixp->fx_r_type);
955
      return NULL;
956
    }
957
 
958
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
959
    reloc->address = fixp->fx_offset;
960
  else if (fixp->fx_pcrel)
961
  {
962
    bfd_vma pcrel_address;
963
    pcrel_address = reloc->address;
964
    if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
965
    {
966
      /* At this point, fx_addnumber is "symbol offset - pcrel_address".
967
               Relocations want only the symbol offset.  */
968
      reloc->addend = fixp->fx_addnumber;
969
    }
970
    else
971
    {
972
      if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
973
        /* A gruesome hack which is a result of the gruesome gas reloc
974
           handling.  */
975
        reloc->addend = pcrel_address;
976
      else
977
        reloc->addend = -pcrel_address;
978
    }
979
  }
980
  else
981
    reloc->addend = fixp->fx_addnumber;
982
  return reloc;
983
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.