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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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