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 38

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

powered by: WebSVN 2.1.0

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