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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-or32.c] - Blame information for rev 816

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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