OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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 206 julius
      operandp->X_add_symbol = NULL;// Added to stop a know() in machine_ip()
295 205 julius
      operandp->X_op_symbol = NULL; // Added to stop a know() in machine_ip()
296
                                    // erroring out - it appears this wasn't 
297
                                    // getting cleared sometimes. - JB 100718
298
      for (; (*s != ',') && (*s != '\0');)
299
        s++;
300
      input_line_pointer = save;
301
      return s;
302
    }
303
 
304
  expression (operandp);
305
 
306
  if (operandp->X_op == O_absent)
307
    {
308
      if (! opt)
309
        as_bad (_("missing operand"));
310
      else
311
        {
312
          operandp->X_add_number = 0;
313
          operandp->X_op = O_constant;
314
        }
315
    }
316
 
317
  new_pointer = input_line_pointer;
318
  input_line_pointer = save;
319
 
320
#if DEBUG
321
  printf ("  %s=parse_operand(%s): operandp->X_op = %u\n", new_pointer, s,
322
          operandp->X_op);
323
#endif
324
 
325
  return new_pointer;
326
}
327
 
328
/* Instruction parsing.  Takes a string containing the opcode.
329
   Operands are at input_line_pointer.  Output is in the_insn.
330
   Warnings or errors are generated.  */
331
 
332
static void
333
machine_ip (char *str)
334
{
335
  char *s;
336
  const char *args;
337
  const struct machine_opcode *insn;
338
  unsigned long opcode;
339
  expressionS operand;
340
  int reloc = BFD_RELOC_NONE;
341
 
342
#if DEBUG
343
  printf ("machine_ip(%s)\n", str);
344
#endif
345
 
346
  s = str;
347
  for (; ISALNUM (*s) || *s == '.' || *s == '_'; ++s)
348
    if (ISUPPER (*s))
349
      *s = TOLOWER (*s);
350
 
351
  switch (*s)
352
    {
353
    case '\0':
354
      break;
355
 
356
    case ' ':     /* FIXME-SOMEDAY more whitespace.  */
357
      *s++ = '\0';
358
      break;
359
 
360
    default:
361
      as_bad (_("unknown opcode1: `%s'"), str);
362
      return;
363
    }
364
 
365
  if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
366
    {
367
      as_bad (_("unknown opcode2 `%s'."), str);
368
      return;
369
    }
370
 
371
  opcode = 0;
372
  memset (&the_insn, '\0', sizeof (the_insn));
373
  the_insn.reloc = BFD_RELOC_NONE;
374
 
375
  reloc = BFD_RELOC_NONE;
376
 
377
  /* Build the opcode, checking as we go to make sure that the
378
     operands match.
379
 
380
     If an operand matches, we modify the_insn or opcode appropriately,
381
     and do a "continue".  If an operand fails to match, we "break".  */
382
  if (insn->args[0] != '\0')
383
    /* Prime the pump.  */
384
    s = parse_operand (s,
385
                       &operand,
386
                       (insn->args[0] == 'I') ||
387
                       (strcmp(insn->name, "l.nop") == 0) );
388
 
389
  for (args = insn->args;; ++args)
390
    {
391
#if DEBUG
392
      printf ("  args = %s\n", args);
393
#endif
394
      switch (*args)
395
        {
396
        case '\0':    /* End of args.  */
397
          /* We have have 0 args, do the bazoooka!  */
398
          if (args == insn->args)
399
            encode (insn, &opcode, 0, 0);
400
 
401
          if (*s == '\0')
402
            {
403
              /* We are truly done.  */
404
              the_insn.opcode = opcode;
405
              if (check_invalid_opcode (opcode))
406
                as_bad (_("instruction not allowed: %s"), str);
407
              return;
408
            }
409
          as_bad (_("too many operands: %s"), s);
410
          break;
411
 
412
        case ',':   /* Must match a comma.  */
413
          if (*s++ == ',')
414
            {
415
              reloc = BFD_RELOC_NONE;
416
 
417
              /* Parse next operand.  */
418
              s = parse_operand (s, &operand, args[1] == 'I');
419
#if DEBUG
420
              printf ("    ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n",
421
                      (int) operand.X_add_number, args, s);
422
#endif
423
              continue;
424
            }
425
          break;
426
 
427
        case '(':   /* Must match a (.  */
428
          s = parse_operand (s, &operand, args[1] == 'I');
429
          continue;
430
 
431
        case ')':   /* Must match a ).  */
432
          continue;
433
 
434
        case 'r':   /* A general register.  */
435
          args++;
436
 
437
          if (operand.X_op != O_register)
438
            break;    /* Only registers.  */
439
#if DEBUG
440
          printf("   (operand.X_add_symbol == 0)=%d",
441
                 (operand.X_add_symbol == NULL));
442
          printf("   (operand.X_op_symbol(%x) == 0)=%d",
443
                 (unsigned int)operand.X_op_symbol,
444
                 (operand.X_op_symbol == NULL));
445
#endif    
446
          know (operand.X_add_symbol == NULL);
447
          know (operand.X_op_symbol == NULL);
448
          encode (insn, &opcode, operand.X_add_number, *args);
449
#if DEBUG
450
          printf ("    r: operand->X_op = %d\n", operand.X_op);
451
#endif
452
          continue;
453
 
454
        default:
455
          if (mask_or_shift)
456
            {
457
#if DEBUG
458
              printf ("mask_or_shift = %d\n", mask_or_shift);
459
#endif
460
              reloc = mask_or_shift;
461
            }
462
          mask_or_shift = 0;
463
          if (*s == '(')
464
            operand.X_op = O_constant;
465
          else if (*s == ')')
466
            s += 1;
467
#if DEBUG
468
          printf ("    default case: operand->X_add_number = %d, *args = %s, *s = %s\n",(int) operand.X_add_number, args, s);
469
#endif
470
          if (operand.X_op == O_constant)
471
            {
472
            unsigned long add = operand.X_add_number;
473
              if (reloc == BFD_RELOC_NONE)
474
                {
475
                  bfd_vma v, mask;
476
 
477
                  mask = 0x3ffffff;
478
                  v = abs (operand.X_add_number) & ~ mask;
479
                  if (v)
480
                    as_bad (_("call/jmp target out of range (1)"));
481
                }
482
 
483
              if (reloc == BFD_RELOC_HI16)
484
                add = ((operand.X_add_number >> 16) & 0xffff);
485
 
486
              the_insn.pcrel = 0;
487
              encode (insn, &opcode, add, *args);
488
              continue;
489
            }
490
 
491
          if (reloc == BFD_RELOC_NONE)
492
            the_insn.reloc = BFD_RELOC_28_PCREL_S2;
493
          else
494
            the_insn.reloc = reloc;
495
 
496
          /* the_insn.reloc = insn->reloc;  */
497
#if DEBUG
498
          printf ("    reloc sym=%d\n", the_insn.reloc);
499
          printf ("    BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE);
500
#endif
501
          the_insn.exp = operand;
502
 
503
          /*  the_insn.reloc_offset = 1;  */
504
          the_insn.pcrel = 1; /* Assume PC-relative jump.  */
505
 
506
          /* FIXME-SOON, Do we figure out whether abs later, after
507
             know sym val?  */
508
          if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16)
509
            the_insn.pcrel = 0;
510
 
511
          if (reloc == BFD_RELOC_NONE)
512
            encode (insn, &opcode, operand.X_add_number, *args);
513
          else
514
            encode (insn, &opcode, 0, *args);
515
          continue;
516
        }
517
 
518
      /* Types or values of args don't match.  */
519
      as_bad (_("invalid operands"));
520
      return;
521
    }
522
}
523
 
524
char *
525
md_atof (int type, char * litP, int *  sizeP)
526
{
527
  return ieee_md_atof (type, litP, sizeP, TRUE);
528
}
529
 
530
/* Write out big-endian.  */
531
 
532
void
533
md_number_to_chars (char *buf, valueT val, int n)
534
{
535
  number_to_chars_bigendian (buf, val, n);
536
}
537
 
538
void
539
md_apply_fix (fixS * fixP, valueT * val, segT seg ATTRIBUTE_UNUSED)
540
{
541
  bfd_byte *buf;
542
  long insn;
543
 
544
  buf = (bfd_byte *) (fixP->fx_where + fixP->fx_frag->fr_literal);
545
 
546
#if DEBUG
547
  printf ("md_apply_fix *val=%x fixP->fx_r_type=%i sym=%s\n",(unsigned int)*val,
548
           fixP->fx_r_type, fixP->fx_addsy ? fixP->fx_addsy->bsym->name : "(none)");
549
#endif
550
 
551
  if ((fixP->fx_addsy == (symbolS *) NULL) && !fixP->fx_pcrel)
552
    fixP->fx_done = 1;
553
 
554
  switch (fixP->fx_r_type)
555
    {
556
    case BFD_RELOC_32:      /* XXXXXXXX pattern in a word.  */
557
#if DEBUG
558
      printf ("reloc_const: val=%x\n", (unsigned int) *val);
559
#endif
560
      /* If we are deleting this reloc entry, we must fill in the
561
               value now.  This can happen if we have a .word which is not
562
               resolved when it appears but is later defined.  We also need
563
               to fill in the value if this is an embedded PIC switch table
564
               entry.  */
565
      if (fixP->fx_done)
566
        md_number_to_chars ((char *) buf, *val, 4);
567
      break;
568
 
569
    case BFD_RELOC_16:      /* XXXX0000 pattern in a word.  */
570
#if DEBUG
571
      printf ("reloc_const: val=%x\n", (unsigned int)*val);
572
#endif
573
      /* If we are deleting this reloc entry, we must fill in the
574
         value now.  */
575
      gas_assert (fixP->fx_size == 2);
576
      if (fixP->fx_done)
577
              md_number_to_chars ((char *) buf, *val, 2);
578
      break;
579
 
580
    case BFD_RELOC_8:      /* XX000000 pattern in a word.  */
581
    case BFD_RELOC_LO16:      /* 0000XXXX pattern in a word.  */
582
#if DEBUG
583
      printf ("reloc_const: val=%x\n", (unsigned int)*val);
584
#endif
585
      break;
586
 
587
    case BFD_RELOC_HI16:    /* 0000XXXX pattern in a word.  */
588
#if DEBUG
589
      printf ("reloc_consth: val=%x\n", (unsigned int)*val);
590
#endif
591
      break;
592
 
593
    case BFD_RELOC_28_PCREL_S2:  /* 0000XXXX pattern in a word.  */
594
#if DEBUG
595
      printf("reloc_pcrel: *val=%x done=%d fixP->fx_pcrel=%i line=%i\n",
596
             (unsigned int) *val, fixP->fx_done, fixP->fx_pcrel, fixP->fx_line);
597
#endif
598
      if ((*val & 0x3) != 0)
599
        as_bad_where (fixP->fx_file, fixP->fx_line,
600
                      _("Branch to odd address (%lx)"), (long) *val);
601
 
602
      /*
603
       * We need to save the bits in the instruction since fixup_segment()
604
       * might be deleting the relocation entry (i.e., a branch within
605
       * the current segment).
606
       */
607
      if (! fixP->fx_done)
608
        break;
609
 
610
      /* update old instruction data */
611
      if (target_big_endian)
612
        insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
613
      else
614
        insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
615
      insn |= (*val >> 2) & 0x03ffffff;
616
      md_number_to_chars ((char *) buf, insn, 4);
617
#if DEBUG
618
      printf("Resulting instruction: %08x\n", (unsigned int)insn);
619
#endif
620
      break;
621
 
622
    case BFD_RELOC_VTABLE_INHERIT:
623
    case BFD_RELOC_VTABLE_ENTRY:
624
      fixP->fx_done = 0;
625
      break;
626
 
627
    case BFD_RELOC_NONE:
628
    default:
629
      as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
630
      break;
631
    }
632
 
633
  fixP->fx_addnumber = *val; /* Remember value for emit_reloc.  */
634
}
635
 
636
/* Should never be called for or32.  */
637
 
638
void
639
md_create_short_jump (char *    ptr       ATTRIBUTE_UNUSED,
640
                      addressT  from_addr ATTRIBUTE_UNUSED,
641
                      addressT  to_addr   ATTRIBUTE_UNUSED,
642
                      fragS *   frag      ATTRIBUTE_UNUSED,
643
                      symbolS * to_symbol ATTRIBUTE_UNUSED)
644
{
645
  as_fatal ("or32_create_short_jmp\n");
646
}
647
 
648
/* Should never be called for or32.  */
649
 
650
void
651
md_convert_frag (bfd *   headers ATTRIBUTE_UNUSED,
652
                 segT    seg     ATTRIBUTE_UNUSED,
653
                 fragS * fragP   ATTRIBUTE_UNUSED)
654
{
655
  as_fatal ("or32_convert_frag\n");
656
}
657
 
658
/* Should never be called for or32.  */
659
 
660
void
661
md_create_long_jump (char *    ptr       ATTRIBUTE_UNUSED,
662
                     addressT  from_addr ATTRIBUTE_UNUSED,
663
                     addressT  to_addr   ATTRIBUTE_UNUSED,
664
                     fragS *   frag      ATTRIBUTE_UNUSED,
665
                     symbolS * to_symbol ATTRIBUTE_UNUSED)
666
{
667
  as_fatal ("or32_create_long_jump\n");
668
}
669
 
670
/* Should never be called for or32.  */
671
 
672
int
673
md_estimate_size_before_relax (fragS * fragP   ATTRIBUTE_UNUSED,
674
                               segT    segtype ATTRIBUTE_UNUSED)
675
{
676
  as_fatal ("or32_estimate_size_before_relax\n");
677
  return 0;
678
}
679
 
680
/* Translate internal representation of relocation info to target format.
681
 
682
   On sparc/29k: first 4 bytes are normal unsigned long address, next three
683
   bytes are index, most sig. byte first.  Byte 7 is broken up with
684
   bit 7 as external, bits 6 & 5 unused, and the lower
685
   five bits as relocation type.  Next 4 bytes are long addend.  */
686
/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com.  */
687
 
688
#ifdef OBJ_AOUT
689
void
690
tc_aout_fix_to_chars (char *where,
691
                      fixS *fixP,
692
                      relax_addressT segment_address_in_file)
693
{
694
  long r_symbolnum;
695
 
696
#if DEBUG
697
  printf ("tc_aout_fix_to_chars\n");
698
#endif
699
 
700
  know (fixP->fx_r_type < BFD_RELOC_NONE);
701
  know (fixP->fx_addsy != NULL);
702
 
703
  md_number_to_chars
704
    (where,
705
     fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
706
     4);
707
 
708
  r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
709
     ? S_GET_TYPE (fixP->fx_addsy)
710
     : fixP->fx_addsy->sy_number);
711
 
712
  where[4] = (r_symbolnum >> 16) & 0x0ff;
713
  where[5] = (r_symbolnum >> 8) & 0x0ff;
714
  where[6] = r_symbolnum & 0x0ff;
715
  where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
716
 
717
  /* Also easy.  */
718
  md_number_to_chars (&where[8], fixP->fx_addnumber, 4);
719
}
720
 
721
#endif /* OBJ_AOUT */
722
 
723
const char *md_shortopts = "";
724
 
725
struct option md_longopts[] =
726
{
727
  { NULL, no_argument, NULL, 0 }
728
};
729
size_t md_longopts_size = sizeof (md_longopts);
730
 
731
int
732
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
733
{
734
  return 0;
735
}
736
 
737
void
738
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
739
{
740
}
741
 
742
/* This is called when a line is unrecognized.  This is used to handle
743
   definitions of or32 style local labels.  */
744
 
745
int
746
or32_unrecognized_line (int c)
747
{
748
  int lab;
749
  char *s;
750
 
751
  if (c != '$'
752
      || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
753
    return 0;
754
 
755
  s = input_line_pointer;
756
 
757
  lab = 0;
758
  while (ISDIGIT ((unsigned char) *s))
759
    {
760
      lab = lab * 10 + *s - '0';
761
      ++s;
762
    }
763
 
764
  if (*s != ':')
765
    /* Not a label definition.  */
766
    return 0;
767
 
768
  if (dollar_label_defined (lab))
769
    {
770
      as_bad (_("label \"$%d\" redefined"), lab);
771
      return 0;
772
    }
773
 
774
  define_dollar_label (lab);
775
  colon (dollar_label_name (lab, 0));
776
  input_line_pointer = s + 1;
777
 
778
  return 1;
779
}
780
 
781
/* Default the values of symbols known that should be "predefined".  We
782
   don't bother to predefine them unless you actually use one, since there
783
   are a lot of them.  */
784
 
785
symbolS *
786
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
787
{
788
  return NULL;
789
}
790
 
791
/* Parse an operand that is machine-specific.  */
792
 
793
void
794
md_operand (expressionS *expressionP)
795
{
796
#if DEBUG
797
  printf ("  md_operand(input_line_pointer = %s)\n", input_line_pointer);
798
#endif
799
 
800
  if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r')
801
    {
802
      /* We have a numeric register expression.  No biggy.  */
803
      input_line_pointer += 2;  /* Skip %r */
804
      (void) expression (expressionP);
805
 
806
      if (expressionP->X_op != O_constant
807
          || expressionP->X_add_number > 255)
808
        as_bad (_("Invalid expression after %%%%\n"));
809
      expressionP->X_op = O_register;
810
    }
811
  else if (input_line_pointer[0] == '&')
812
    {
813
      /* We are taking the 'address' of a register...this one is not
814
         in the manual, but it *is* in traps/fpsymbol.h!  What they
815
         seem to want is the register number, as an absolute number.  */
816
      input_line_pointer++; /* Skip & */
817
      (void) expression (expressionP);
818
 
819
      if (expressionP->X_op != O_register)
820
        as_bad (_("invalid register in & expression"));
821
      else
822
        expressionP->X_op = O_constant;
823
    }
824
  else if (input_line_pointer[0] == '$'
825
           && ISDIGIT ((unsigned char) input_line_pointer[1]))
826
    {
827
      long lab;
828
      char *name;
829
      symbolS *sym;
830
 
831
      /* This is a local label.  */
832
      ++input_line_pointer;
833
      lab = (long) get_absolute_expression ();
834
 
835
      if (dollar_label_defined (lab))
836
        {
837
          name = dollar_label_name (lab, 0);
838
          sym = symbol_find (name);
839
        }
840
      else
841
        {
842
          name = dollar_label_name (lab, 1);
843
          sym = symbol_find_or_make (name);
844
        }
845
 
846
      expressionP->X_op = O_symbol;
847
      expressionP->X_add_symbol = sym;
848
      expressionP->X_add_number = 0;
849
    }
850
  else if (input_line_pointer[0] == '$')
851
    {
852
      char *s;
853
      char type;
854
      int fieldnum, fieldlimit;
855
      LITTLENUM_TYPE floatbuf[8];
856
 
857
      /* $float(), $doubleN(), or $extendN() convert floating values
858
         to integers.  */
859
      s = input_line_pointer;
860
 
861
      ++s;
862
 
863
      fieldnum = 0;
864
      if (strncmp (s, "double", sizeof "double" - 1) == 0)
865
        {
866
          s += sizeof "double" - 1;
867
          type = 'd';
868
          fieldlimit = 2;
869
        }
870
      else if (strncmp (s, "float", sizeof "float" - 1) == 0)
871
        {
872
          s += sizeof "float" - 1;
873
          type = 'f';
874
          fieldlimit = 1;
875
        }
876
      else if (strncmp (s, "extend", sizeof "extend" - 1) == 0)
877
        {
878
          s += sizeof "extend" - 1;
879
          type = 'x';
880
          fieldlimit = 4;
881
        }
882
      else
883
        return;
884
 
885
      if (ISDIGIT (*s))
886
        {
887
          fieldnum = *s - '0';
888
          ++s;
889
        }
890
      if (fieldnum >= fieldlimit)
891
        return;
892
 
893
      SKIP_WHITESPACE ();
894
      if (*s != '(')
895
        return;
896
      ++s;
897
      SKIP_WHITESPACE ();
898
 
899
      s = atof_ieee (s, type, floatbuf);
900
      if (s == NULL)
901
        return;
902
      s = s;
903
 
904
      SKIP_WHITESPACE ();
905
      if (*s != ')')
906
        return;
907
      ++s;
908
      SKIP_WHITESPACE ();
909
 
910
      input_line_pointer = s;
911
      expressionP->X_op = O_constant;
912
      expressionP->X_unsigned = 1;
913
      expressionP->X_add_number = ((floatbuf[fieldnum * 2]
914
                                    << LITTLENUM_NUMBER_OF_BITS)
915
                                   + floatbuf[fieldnum * 2 + 1]);
916
    }
917
}
918
 
919
/* Round up a section size to the appropriate boundary.  */
920
 
921
valueT
922
md_section_align (asection * seg, valueT addr ATTRIBUTE_UNUSED)
923
{
924
  int align = bfd_get_section_alignment (stdoutput, seg);
925
  return ((addr + (1 << align) - 1) & (-1 << align));
926
}
927
 
928
/* Exactly what point is a PC-relative offset relative TO?
929
   On the 29000, they're relative to the address of the instruction,
930
   which we have set up as the address of the fixup too.  */
931
 
932
long
933
md_pcrel_from (fixS *fixP)
934
{
935
  return fixP->fx_where + fixP->fx_frag->fr_address;
936
}
937
 
938
/* Generate a reloc for a fixup.  */
939
 
940
arelent *
941
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
942
{
943
  arelent *reloc;
944
 
945
  reloc = xmalloc (sizeof (arelent));
946
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
947
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
948
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
949
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
950
 
951
  if (reloc->howto == (reloc_howto_type *) NULL)
952
    {
953
      as_bad_where (fixp->fx_file, fixp->fx_line,
954
                    _("reloc %d not supported by object file format"),
955
                    (int) fixp->fx_r_type);
956
      return NULL;
957
    }
958
 
959
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
960
    reloc->address = fixp->fx_offset;
961
  else if (fixp->fx_pcrel)
962
  {
963
    bfd_vma pcrel_address;
964
    pcrel_address = reloc->address;
965
    if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
966
    {
967
      /* At this point, fx_addnumber is "symbol offset - pcrel_address".
968
               Relocations want only the symbol offset.  */
969
      reloc->addend = fixp->fx_addnumber;
970
    }
971
    else
972
    {
973
      if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
974
        /* A gruesome hack which is a result of the gruesome gas reloc
975
           handling.  */
976
        reloc->addend = pcrel_address;
977
      else
978
        reloc->addend = -pcrel_address;
979
    }
980
  }
981
  else
982
    reloc->addend = fixp->fx_addnumber;
983
  return reloc;
984
}

powered by: WebSVN 2.1.0

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