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

Subversion Repositories openrisc_2011-10-31

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

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

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

powered by: WebSVN 2.1.0

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