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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 38 julius
/* tc-ldx.c -- Assemble for the DLX
2
   Copyright 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
3
 
4
   This file is part of GAS, the GNU Assembler.
5
 
6
   GAS is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
 
11
   GAS is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with GAS; see the file COPYING.  If not, write to the Free
18
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19
   02110-1301, USA.  */
20
 
21
/* Initially created by Kuang Hwa Lin, 3/20/2002.  */
22
 
23
#include "safe-ctype.h"
24
#include "as.h"
25
#include "tc-dlx.h"
26
#include "opcode/dlx.h"
27
 
28
/* Make it easier to clone this machine desc into another one.  */
29
#define machine_opcode      dlx_opcode
30
#define machine_opcodes     dlx_opcodes
31
#define machine_ip          dlx_ip
32
#define machine_it          dlx_it
33
 
34
#define NO_RELOC            BFD_RELOC_NONE
35
#define RELOC_DLX_REL26     BFD_RELOC_DLX_JMP26
36
#define RELOC_DLX_16        BFD_RELOC_16
37
#define RELOC_DLX_REL16     BFD_RELOC_16_PCREL_S2
38
#define RELOC_DLX_HI16      BFD_RELOC_HI16_S
39
#define RELOC_DLX_LO16      BFD_RELOC_LO16
40
#define RELOC_DLX_VTINHERIT BFD_RELOC_VTABLE_INHERIT
41
#define RELOC_DLX_VTENTRY   BFD_RELOC_VTABLE_ENTRY
42
 
43
/* handle of the OPCODE hash table */
44
static struct hash_control *op_hash = NULL;
45
 
46
struct machine_it
47
{
48
  char *error;
49
  unsigned long opcode;
50
  struct nlist *nlistp;
51
  expressionS exp;
52
  int pcrel;
53
  int size;
54
  int reloc_offset;             /* Offset of reloc within insn.  */
55
  int reloc;
56
  int HI;
57
  int LO;
58
}
59
the_insn;
60
 
61
/* This array holds the chars that always start a comment.  If the
62
   pre-processor is disabled, these aren't very useful.  */
63
const char comment_chars[] = ";";
64
 
65
/* This array holds the chars that only start a comment at the beginning of
66
   a line.  If the line seems to have the form '# 123 filename'
67
   .line and .file directives will appear in the pre-processed output.  */
68
/* Note that input_file.c hand checks for '#' at the beginning of the
69
   first line of the input file.  This is because the compiler outputs
70
   #NO_APP at the beginning of its output.  */
71
/* Also note that comments like this one will always work.  */
72
const char line_comment_chars[] = "#";
73
 
74
/* We needed an unused char for line separation to work around the
75
   lack of macros, using sed and such.  */
76
const char line_separator_chars[] = "@";
77
 
78
/* Chars that can be used to separate mant from exp in floating point nums.  */
79
const char EXP_CHARS[] = "eE";
80
 
81
/* Chars that mean this number is a floating point constant.
82
   As in 0f12.456
83
   or    0d1.2345e12.  */
84
const char FLT_CHARS[] = "rRsSfFdDxXpP";
85
 
86
static void
87
insert_sreg (char *regname, int regnum)
88
{
89
  /* Must be large enough to hold the names of the special registers.  */
90
  char buf[80];
91
  int i;
92
 
93
  symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum,
94
                                   &zero_address_frag));
95
  for (i = 0; regname[i]; i++)
96
    buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
97
  buf[i] = '\0';
98
 
99
  symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum,
100
                                   &zero_address_frag));
101
}
102
 
103
/* Install symbol definitions for assorted special registers.
104
   See MIPS Assembly Language Programmer's Guide page 1-4   */
105
 
106
static void
107
define_some_regs (void)
108
{
109
  /* Software representation.  */
110
  insert_sreg ("zero",  0);
111
  insert_sreg ("at",    1);
112
  insert_sreg ("v0",    2);
113
  insert_sreg ("v1",    3);
114
  insert_sreg ("a0",    4);
115
  insert_sreg ("a1",    5);
116
  insert_sreg ("a2",    6);
117
  insert_sreg ("a3",    7);
118
  insert_sreg ("t0",    8);
119
  insert_sreg ("t1",    9);
120
  insert_sreg ("t2",    10);
121
  insert_sreg ("t3",    11);
122
  insert_sreg ("t4",    12);
123
  insert_sreg ("t5",    13);
124
  insert_sreg ("t6",    14);
125
  insert_sreg ("t7",    15);
126
  insert_sreg ("s0",    16);
127
  insert_sreg ("s1",    17);
128
  insert_sreg ("s2",    18);
129
  insert_sreg ("s3",    19);
130
  insert_sreg ("s4",    20);
131
  insert_sreg ("s5",    21);
132
  insert_sreg ("s6",    22);
133
  insert_sreg ("s7",    23);
134
  insert_sreg ("t8",    24);
135
  insert_sreg ("t9",    25);
136
  insert_sreg ("k0",    26);
137
  insert_sreg ("k1",    27);
138
  insert_sreg ("gp",    28);
139
  insert_sreg ("sp",    29);
140
  insert_sreg ("fp",    30);
141
  insert_sreg ("ra",    31);
142
  /* Special registers.  */
143
  insert_sreg ("pc",    0);
144
  insert_sreg ("npc",   1);
145
  insert_sreg ("iad",   2);
146
}
147
 
148
/* Subroutine check the string to match an register.  */
149
 
150
static int
151
match_sft_register (char *name)
152
{
153
#define MAX_REG_NO  35
154
/* Currently we have 35 software registers defined -
155
   we borrowed from MIPS.   */
156
  static char *soft_reg[] =
157
    {
158
      "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
159
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9",
160
      "s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1",
161
      "gp", "sp", "fp", "ra", "pc", "npc", "iad",
162
      "EndofTab"  /* End of the Table indicator */
163
    };
164
  char low_name[21], *ptr;
165
  int idx;
166
 
167
  for (ptr = name,idx = 0; *ptr != '\0'; ptr++)
168
    low_name[idx++] = TOLOWER (*ptr);
169
 
170
  low_name[idx] = '\0';
171
  idx = 0;
172
 
173
  while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0]))
174
    idx += 1;
175
 
176
  return idx < MAX_REG_NO;
177
}
178
 
179
/* Subroutine check the string to match an register.  */
180
 
181
static int
182
is_ldst_registers (char *name)
183
{
184
  char *ptr = name;
185
 
186
  /* The first character of the register name got to be either %, $, r of R.  */
187
  if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R')
188
      && ISDIGIT ((unsigned char) ptr[1]))
189
    return 1;
190
 
191
  /* Now check the software register representation.  */
192
  return match_sft_register (ptr);
193
}
194
 
195
/* Subroutine of s_proc so targets can choose a different default prefix.
196
   If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
197
 
198
static void
199
s_proc (int end_p)
200
{
201
  /* Record the current function so that we can issue an error message for
202
     misplaced .func,.endfunc, and also so that .endfunc needs no
203
     arguments.  */
204
  static char *current_name;
205
  static char *current_label;
206
 
207
  if (end_p)
208
    {
209
      if (current_name == NULL)
210
        {
211
          as_bad (_("missing .proc"));
212
          ignore_rest_of_line ();
213
          return;
214
        }
215
 
216
      current_name = current_label = NULL;
217
      SKIP_WHITESPACE ();
218
      while (!is_end_of_line[(unsigned char) *input_line_pointer])
219
        input_line_pointer++;
220
    }
221
  else
222
    {
223
      char *name, *label;
224
      char delim1, delim2;
225
 
226
      if (current_name != NULL)
227
        {
228
          as_bad (_(".endfunc missing for previous .proc"));
229
          ignore_rest_of_line ();
230
          return;
231
        }
232
 
233
      name = input_line_pointer;
234
      delim1 = get_symbol_end ();
235
      name = xstrdup (name);
236
      *input_line_pointer = delim1;
237
      SKIP_WHITESPACE ();
238
 
239
      if (*input_line_pointer != ',')
240
        {
241
          char leading_char = 0;
242
 
243
          leading_char = bfd_get_symbol_leading_char (stdoutput);
244
          /* Missing entry point, use function's name with the leading
245
             char prepended.  */
246
          if (leading_char)
247
            asprintf (&label, "%c%s", leading_char, name);
248
          else
249
            label = name;
250
        }
251
      else
252
        {
253
          ++input_line_pointer;
254
          SKIP_WHITESPACE ();
255
          label = input_line_pointer;
256
          delim2 = get_symbol_end ();
257
          label = xstrdup (label);
258
          *input_line_pointer = delim2;
259
        }
260
 
261
      current_name = name;
262
      current_label = label;
263
    }
264
  demand_empty_rest_of_line ();
265
}
266
 
267
/* This function is called once, at assembler startup time.  It should
268
   set up all the tables, etc., that the MD part of the assembler will
269
   need.  */
270
 
271
void
272
md_begin (void)
273
{
274
  const char *retval = NULL;
275
  int lose = 0;
276
  unsigned int i;
277
 
278
  /* Create a new hash table.  */
279
  op_hash = hash_new ();
280
 
281
  /* Hash up all the opcodes for fast use later.  */
282
  for (i = 0; i < num_dlx_opcodes; i++)
283
    {
284
      const char *name = machine_opcodes[i].name;
285
 
286
      retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]);
287
 
288
      if (retval != NULL)
289
        {
290
          fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
291
                   machine_opcodes[i].name, retval);
292
          lose = 1;
293
        }
294
    }
295
 
296
  if (lose)
297
    as_fatal (_("Broken assembler.  No assembly attempted."));
298
 
299
  define_some_regs ();
300
}
301
 
302
/* This function will check the opcode and return 1 if the opcode is one
303
   of the load/store instruction, and it will fix the operand string to
304
   the standard form so we can use the standard parse_operand routine.  */
305
 
306
#define READ_OP     0x100
307
#define WRITE_OP    0x200
308
static char iBuf[81];
309
 
310
static char *
311
dlx_parse_loadop (char * str)
312
{
313
  char *ptr = str;
314
  int   idx = 0;
315
 
316
  /* The last pair of ()/[] is the register, all other are the
317
     reloc displacement, and if there is a register then it ought
318
     to have a pair of ()/[]
319
     This is not necessarily true, what if the load instruction come
320
     without the register and with %hi/%lo modifier?  */
321
  for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++)
322
    ;
323
 
324
  if (idx == 72)
325
    {
326
    badoperand_load:
327
      as_bad (_("Bad operand for a load instruction: <%s>"), str);
328
      return NULL;
329
    }
330
  else
331
    {
332
      int i, pb = 0;
333
      int m2 = 0;
334
      char rs1[7], rd[7], endm, match = '0';
335
      char imm[72];
336
 
337
      idx -= 1;
338
      switch (str[idx])
339
        {
340
        case ')':
341
          match = '(';
342
          endm  = ')';
343
          break;
344
        case ']':
345
          match = '[';
346
          endm  = ']';
347
          break;
348
        default:
349
          /* No register indicated, fill in zero.  */
350
          rs1[0] = 'r';
351
          rs1[1] = '0';
352
          rs1[2] = '\0';
353
          match  = 0;
354
          endm = 0;
355
          m2 = 1;
356
        }
357
 
358
      if (!m2)
359
        {
360
          /* Searching for (/[ which will match the ]/).  */
361
          for (pb = idx - 1; str[pb] != match; pb -= 1)
362
            /* Match can only be either '[' or '(', if it is
363
               '(' then this can be a normal expression, we'll treat
364
               it as an operand.  */
365
            if (str[pb] == endm || pb < (idx - 5))
366
              goto load_no_rs1;
367
          pb += 1;
368
 
369
          for (i = 0; (pb + i) < idx; i++)
370
            rs1[i] = str[pb+i];
371
 
372
          rs1[i] = '\0';
373
 
374
          if (is_ldst_registers (& rs1[0]))
375
            /* Point to the last character of the imm.  */
376
            pb -= 1;
377
          else
378
            {
379
            load_no_rs1:
380
              if (match == '[')
381
                goto badoperand_load;
382
              /* No register indicated, fill in zero and restore the imm.  */
383
              rs1[0] = 'r';
384
              rs1[1] = '0';
385
              rs1[2] = '\0';
386
              m2 = 1;
387
            }
388
        }
389
 
390
      /* Duplicate the first register.  */
391
      for (i = 0; i < 7 && str[i] != ','; i++)
392
        rd[i] = ptr[i];
393
 
394
      if (str[i] != ',')
395
        goto badoperand_load;
396
      else
397
        rd[i] = '\0';
398
 
399
      /* Copy the immd.  */
400
      if (m2)
401
        /* Put the '\0' back in.  */
402
        pb = idx + 1;
403
 
404
      for (i++, m2 = 0; i < pb; m2++,i++)
405
        imm[m2] = ptr[i];
406
 
407
      imm[m2] = '\0';
408
 
409
      /* Assemble the instruction to gas internal format.  */
410
      for (i = 0; rd[i] != '\0'; i++)
411
        iBuf[i] = rd[i];
412
 
413
      iBuf[i++] = ',';
414
 
415
      for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
416
        iBuf[i] = rs1[pb];
417
 
418
      iBuf[i++] = ',';
419
 
420
      for (pb = 0; imm[pb] != '\0'; i++, pb++)
421
        iBuf[i] = imm[pb];
422
 
423
      iBuf[i] = '\0';
424
      return iBuf;
425
    }
426
}
427
 
428
static char *
429
dlx_parse_storeop (char * str)
430
{
431
  char *ptr = str;
432
  int   idx = 0;
433
 
434
  /* Search for the ','.  */
435
  for (idx = 0; idx < 72 && ptr[idx] != ','; idx++)
436
    ;
437
 
438
  if (idx == 72)
439
    {
440
    badoperand_store:
441
      as_bad (_("Bad operand for a store instruction: <%s>"), str);
442
      return NULL;
443
    }
444
  else
445
    {
446
      /* idx now points to the ','.  */
447
      int i, pb = 0;
448
      int comma = idx;
449
      int m2 = 0;
450
      char rs1[7], rd[7], endm, match = '0';
451
      char imm[72];
452
 
453
      /* Now parse the '(' and ')', and make idx point to ')'.  */
454
      idx -= 1;
455
      switch (str[idx])
456
        {
457
        case ')':
458
          match = '(';
459
          endm  = ')';
460
          break;
461
        case ']':
462
          match = '[';
463
          endm  = ']';
464
          break;
465
        default:
466
          /* No register indicated, fill in zero.  */
467
          rs1[0] = 'r';
468
          rs1[1] = '0';
469
          rs1[2] = '\0';
470
          match  = 0;
471
          endm = 0;
472
          m2 = 1;
473
        }
474
 
475
      if (!m2)
476
        {
477
          /* Searching for (/[ which will match the ]/).  */
478
          for (pb = idx - 1; str[pb] != match; pb -= 1)
479
            if (pb < (idx - 5) || str[pb] == endm)
480
              goto store_no_rs1;
481
          pb += 1;
482
 
483
          for (i = 0; (pb + i) < idx; i++)
484
            rs1[i] = str[pb + i];
485
 
486
          rs1[i] = '\0';
487
 
488
          if (is_ldst_registers (& rs1[0]))
489
            /* Point to the last character of the imm.  */
490
            pb -= 1;
491
          else
492
            {
493
            store_no_rs1:
494
              if (match == '[')
495
                goto badoperand_store;
496
 
497
              /* No register indicated, fill in zero and restore the imm.  */
498
              rs1[0] = 'r';
499
              rs1[1] = '0';
500
              rs1[2] = '\0';
501
              pb = comma;
502
            }
503
        }
504
      else
505
        /* No register was specified.  */
506
        pb = comma;
507
 
508
      /* Duplicate the first register.  */
509
      for (i = comma + 1; (str[i] == ' ' || str[i] == '\t'); i++)
510
        ;
511
 
512
      for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++)
513
        {
514
          if (str[i] != ' ' && str[i] != '\t')
515
            rd[m2] = str[i];
516
          else
517
            goto badoperand_store;
518
        }
519
 
520
      if (str[i] != '\0')
521
        goto badoperand_store;
522
      else
523
        rd[m2] = '\0';
524
 
525
      /* Copy the immd.  */
526
      for (i = 0; i < pb; i++)
527
        imm[i] = ptr[i];
528
 
529
      imm[i] = '\0';
530
 
531
      /* Assemble the instruction to gas internal format.  */
532
      for (i = 0; rd[i] != '\0'; i++)
533
        iBuf[i] = rd[i];
534
      iBuf[i++] = ',';
535
      for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
536
        iBuf[i] = rs1[pb];
537
      iBuf[i++] = ',';
538
      for (pb = 0; imm[pb] != '\0'; i++, pb++)
539
        iBuf[i] = imm[pb];
540
      iBuf[i] = '\0';
541
      return iBuf;
542
    }
543
}
544
 
545
static char *
546
fix_ld_st_operand (unsigned long opcode, char* str)
547
{
548
  /* Check the opcode.  */
549
  switch ((int) opcode)
550
    {
551
    case  LBOP:
552
    case  LBUOP:
553
    case  LSBUOP:
554
    case  LHOP:
555
    case  LHUOP:
556
    case  LSHUOP:
557
    case  LWOP:
558
    case  LSWOP:
559
      return dlx_parse_loadop (str);
560
    case  SBOP:
561
    case  SHOP:
562
    case  SWOP:
563
      return dlx_parse_storeop (str);
564
    default:
565
      return str;
566
    }
567
}
568
 
569
static int
570
hilo_modifier_ok (char *s)
571
{
572
  char *ptr = s;
573
  int   idx, count = 1;
574
 
575
  if (*ptr != '(')
576
    return 1;
577
 
578
  for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1)
579
    {
580
      if (count == 0)
581
        return count;
582
 
583
      if (ptr[idx] == '(')
584
        count += 1;
585
 
586
      if (ptr[idx] == ')')
587
        count -= 1;
588
    }
589
 
590
  return (count == 0) ? 1:0;
591
}
592
 
593
static char *
594
parse_operand (char *s, expressionS *operandp)
595
{
596
  char *save = input_line_pointer;
597
  char *new;
598
 
599
  the_insn.HI = the_insn.LO = 0;
600
 
601
  /* Search for %hi and %lo, make a mark and skip it.  */
602
  if (strncmp (s, "%hi", 3) == 0)
603
    {
604
      s += 3;
605
      the_insn.HI = 1;
606
    }
607
  else
608
    {
609
      if (strncmp (s, "%lo", 3) == 0)
610
        {
611
          s += 3;
612
          the_insn.LO = 1;
613
        }
614
      else
615
        the_insn.LO = 0;
616
    }
617
 
618
  if (the_insn.HI || the_insn.LO)
619
    {
620
      if (!hilo_modifier_ok (s))
621
        as_bad (_("Expression Error for operand modifier %%hi/%%lo\n"));
622
    }
623
 
624
  /* Check for the % and $ register representation    */
625
  if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R')
626
      && ISDIGIT ((unsigned char) s[1]))
627
    {
628
      /* We have a numeric register expression.  No biggy.  */
629
      s += 1;
630
      input_line_pointer = s;
631
      (void) expression (operandp);
632
      if (operandp->X_op != O_constant
633
          || operandp->X_add_number > 31)
634
        as_bad (_("Invalid expression after %%%%\n"));
635
      operandp->X_op = O_register;
636
    }
637
  else
638
    {
639
      /* Normal operand parsing.  */
640
      input_line_pointer = s;
641
      (void) expression (operandp);
642
    }
643
 
644
  new = input_line_pointer;
645
  input_line_pointer = save;
646
  return new;
647
}
648
 
649
/* Instruction parsing.  Takes a string containing the opcode.
650
   Operands are at input_line_pointer.  Output is in the_insn.
651
   Warnings or errors are generated.  */
652
 
653
static void
654
machine_ip (char *str)
655
{
656
  char *s;
657
  const char *args;
658
  struct machine_opcode *insn;
659
  char *argsStart;
660
  unsigned long opcode;
661
  expressionS the_operand;
662
  expressionS *operand = &the_operand;
663
  unsigned int reg, reg_shift = 0;
664
 
665
  /* Fixup the opcode string to all lower cases, and also
666
     allow numerical digits.  */
667
  s = str;
668
 
669
  if (ISALPHA (*s))
670
    for (; ISALNUM (*s); ++s)
671
      if (ISUPPER (*s))
672
        *s = TOLOWER (*s);
673
 
674
  switch (*s)
675
    {
676
    case '\0':
677
      break;
678
 
679
      /* FIXME-SOMEDAY more whitespace.  */
680
    case ' ':
681
      *s++ = '\0';
682
      break;
683
 
684
    default:
685
      as_bad (_("Unknown opcode: `%s'"), str);
686
      return;
687
    }
688
 
689
  /* Hash the opcode, insn will have the string from opcode table.
690
     also initialized the_insn struct.  */
691
  if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
692
    {
693
      /* Handle the ret and return macro here.  */
694
      if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0))
695
        {
696
          memset (&the_insn, '\0', sizeof (the_insn));
697
          the_insn.reloc = NO_RELOC;
698
          the_insn.pcrel = 0;
699
          the_insn.opcode =
700
            (unsigned long)(JROP | 0x03e00000);    /* 0x03e00000 = r31 << 21 */
701
        }
702
      else
703
        as_bad (_("Unknown opcode `%s'."), str);
704
 
705
      return;
706
    }
707
 
708
  argsStart = s;
709
  opcode = insn->opcode;
710
  memset (&the_insn, '\0', sizeof (the_insn));
711
  the_insn.reloc = NO_RELOC;
712
  the_insn.pcrel = 0;
713
 
714
  /* Set the sip reloc HI16 flag.  */
715
  if (!set_dlx_skip_hi16_flag (1))
716
    as_bad (_("Can not set dlx_skip_hi16_flag"));
717
 
718
  /* Fix the operand string if it is one of load store instructions.  */
719
  s = fix_ld_st_operand (opcode, s);
720
 
721
  /* Build the opcode, checking as we go to make sure that the
722
     operands match.
723
     If an operand matches, we modify the_insn or opcode appropriately,
724
     and do a "continue".  If an operand fails to match, we "break".  */
725
  if (insn->args[0] != '\0' && insn->args[0] != 'N')
726
    {
727
      /* Prime the pump.  */
728
      if (*s == '\0')
729
        {
730
          as_bad (_("Missing arguments for opcode <%s>."), str);
731
          return;
732
        }
733
      else
734
        s = parse_operand (s, operand);
735
    }
736
  else if (insn->args[0] == 'N')
737
    {
738
      /* Clean up the insn and done!  */
739
      the_insn.opcode = opcode;
740
      return;
741
    }
742
 
743
  /* Parse through the args (this is from opcode table), *s point to
744
     the current character of the instruction stream.  */
745
  for (args = insn->args;; ++args)
746
    {
747
      switch (*args)
748
        {
749
          /* End of Line.  */
750
        case '\0':
751
          /* End of args.  */
752
          if (*s == '\0')
753
            {
754
              /* We are truly done.  */
755
              the_insn.opcode = opcode;
756
              /* Clean up the HI and LO mark.  */
757
              the_insn.HI = 0;
758
              the_insn.LO = 0;
759
              return;
760
            }
761
 
762
          the_insn.HI = 0;
763
          the_insn.LO = 0;
764
          as_bad (_("Too many operands: %s"), s);
765
          break;
766
 
767
          /* ',' Args separator */
768
        case ',':
769
          /* Must match a comma.  */
770
          if (*s++ == ',')
771
            {
772
              /* Parse next operand.  */
773
              s = parse_operand (s, operand);
774
              continue;
775
            }
776
          break;
777
 
778
          /* It can be a 'a' register or 'i' operand.  */
779
        case 'P':
780
          /* Macro move operand/reg.  */
781
          if (operand->X_op == O_register)
782
            {
783
              /* Its a register.  */
784
              reg_shift = 21;
785
              goto general_reg;
786
            }
787
 
788
          /* The immediate 16 bits literal, bit 0-15.  */
789
        case 'i':
790
          /* offset, unsigned.  */
791
        case 'I':
792
          /* offset, signed.  */
793
          if (operand->X_op == O_constant)
794
            {
795
              if (the_insn.HI)
796
                operand->X_add_number >>= 16;
797
 
798
              opcode |= operand->X_add_number & 0xFFFF;
799
 
800
              if (the_insn.HI && the_insn.LO)
801
                as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s);
802
              else
803
                {
804
                  the_insn.HI = 0;
805
                  the_insn.LO = 0;
806
                }
807
              continue;
808
            }
809
 
810
          the_insn.reloc        = (the_insn.HI) ? RELOC_DLX_HI16
811
            : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16);
812
          the_insn.reloc_offset = 2;
813
          the_insn.size         = 2;
814
          the_insn.pcrel        = 0;
815
          the_insn.exp          = * operand;
816
          the_insn.HI           = 0;
817
          the_insn.LO           = 0;
818
          continue;
819
 
820
        case 'd':
821
          /* offset, signed.  */
822
          if (operand->X_op == O_constant)
823
            {
824
              opcode |= operand->X_add_number & 0xFFFF;
825
              continue;
826
            }
827
          the_insn.reloc        = RELOC_DLX_REL16;
828
          the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
829
          the_insn.size         = 4;
830
          the_insn.pcrel        = 1;
831
          the_insn.exp          = *operand;
832
          continue;
833
 
834
          /* The immediate 26 bits literal, bit 0-25.  */
835
        case 'D':
836
          /* offset, signed.  */
837
          if (operand->X_op == O_constant)
838
            {
839
              opcode |= operand->X_add_number & 0x3FFFFFF;
840
              continue;
841
            }
842
          the_insn.reloc = RELOC_DLX_REL26;
843
          the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
844
          the_insn.size  = 4;
845
          the_insn.pcrel = 1;
846
          the_insn.exp = *operand;
847
          continue;
848
 
849
          /* Type 'a' Register.  */
850
        case 'a':
851
          /* A general register at bits 21-25, rs1.  */
852
          reg_shift = 21;
853
          goto general_reg;
854
 
855
          /* Type 'b' Register.  */
856
        case 'b':
857
          /* A general register at bits 16-20, rs2/rd.  */
858
          reg_shift = 16;
859
          goto general_reg;
860
 
861
          /* Type 'c' Register.  */
862
        case 'c':
863
          /* A general register at bits 11-15, rd.  */
864
          reg_shift = 11;
865
 
866
        general_reg:
867
          know (operand->X_add_symbol == 0);
868
          know (operand->X_op_symbol == 0);
869
          reg = operand->X_add_number;
870
          if (reg & 0xffffffe0)
871
            as_fatal (_("failed regnum sanity check."));
872
          else
873
            /* Got the register, now figure out where it goes in the opcode.  */
874
            opcode |= reg << reg_shift;
875
 
876
          switch (*args)
877
            {
878
            case 'a':
879
            case 'b':
880
            case 'c':
881
            case 'P':
882
              continue;
883
            }
884
          as_fatal (_("failed general register sanity check."));
885
          break;
886
 
887
        default:
888
          BAD_CASE (*args);
889
        }
890
 
891
      /* Types or values of args don't match.  */
892
      as_bad (_("Invalid operands"));
893
      return;
894
    }
895
}
896
 
897
/* Assemble a single instruction.  Its label has already been handled
898
   by the generic front end.  We just parse opcode and operands, and
899
   produce the bytes of data and relocation.  */
900
 
901
void
902
md_assemble (char *str)
903
{
904
  char *toP;
905
  fixS *fixP;
906
  bit_fixS *bitP;
907
 
908
  know (str);
909
  machine_ip (str);
910
  toP = frag_more (4);
911
  /* Put out the opcode.  */
912
  md_number_to_chars (toP, the_insn.opcode, 4);
913
 
914
  /* Put out the symbol-dependent stuff.  */
915
  if (the_insn.reloc != NO_RELOC)
916
    {
917
      fixP = fix_new_exp (frag_now,
918
                          (toP - frag_now->fr_literal + the_insn.reloc_offset),
919
                          the_insn.size, & the_insn.exp, the_insn.pcrel,
920
                          the_insn.reloc);
921
 
922
      /* Turn off complaints that the addend is
923
         too large for things like foo+100000@ha.  */
924
      switch (the_insn.reloc)
925
        {
926
        case RELOC_DLX_HI16:
927
        case RELOC_DLX_LO16:
928
          fixP->fx_no_overflow = 1;
929
          break;
930
        default:
931
          break;
932
        }
933
 
934
      switch (fixP->fx_r_type)
935
        {
936
        case RELOC_DLX_REL26:
937
          bitP = malloc (sizeof (bit_fixS));
938
          bitP->fx_bit_size = 26;
939
          bitP->fx_bit_offset = 25;
940
          bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
941
          bitP->fx_bit_base_adj = 0;
942
          bitP->fx_bit_max = 0;
943
          bitP->fx_bit_min = 0;
944
          bitP->fx_bit_add = 0x03FFFFFF;
945
          fixP->fx_bit_fixP = bitP;
946
          break;
947
        case RELOC_DLX_LO16:
948
        case RELOC_DLX_REL16:
949
          bitP = malloc (sizeof (bit_fixS));
950
          bitP->fx_bit_size = 16;
951
          bitP->fx_bit_offset = 15;
952
          bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
953
          bitP->fx_bit_base_adj = 0;
954
          bitP->fx_bit_max = 0;
955
          bitP->fx_bit_min = 0;
956
          bitP->fx_bit_add = 0x0000FFFF;
957
          fixP->fx_bit_fixP = bitP;
958
          break;
959
        case RELOC_DLX_HI16:
960
          bitP = malloc (sizeof (bit_fixS));
961
          bitP->fx_bit_size = 16;
962
          bitP->fx_bit_offset = 15;
963
          bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
964
          bitP->fx_bit_base_adj = 0;
965
          bitP->fx_bit_max = 0;
966
          bitP->fx_bit_min = 0;
967
          bitP->fx_bit_add = 0x0000FFFF;
968
          fixP->fx_bit_fixP = bitP;
969
          break;
970
        default:
971
          fixP->fx_bit_fixP = NULL;
972
          break;
973
        }
974
    }
975
}
976
 
977
/* This is identical to the md_atof in m68k.c.  I think this is right,
978
   but I'm not sure.  Dlx will not use it anyway, so I just leave it
979
   here for now.  */
980
 
981
char *
982
md_atof (int type, char *litP, int *sizeP)
983
{
984
  return ieee_md_atof (type, litP, sizeP, TRUE);
985
}
986
 
987
/* Write out big-endian.  */
988
void
989
md_number_to_chars (char *buf, valueT val, int n)
990
{
991
  number_to_chars_bigendian (buf, val, n);
992
}
993
 
994
bfd_boolean
995
md_dlx_fix_adjustable (fixS *fixP)
996
{
997
  /* We need the symbol name for the VTABLE entries.  */
998
  return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT
999
          && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY);
1000
}
1001
 
1002
void
1003
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1004
{
1005
  long val = *valP;
1006
  char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
1007
 
1008
  switch (fixP->fx_r_type)
1009
    {
1010
    case RELOC_DLX_LO16:
1011
    case RELOC_DLX_REL16:
1012
      if (fixP->fx_bit_fixP != NULL)
1013
        {
1014
          val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base;
1015
          free (fixP->fx_bit_fixP);
1016
          fixP->fx_bit_fixP = NULL;
1017
        }
1018
#ifdef DEBUG
1019
      else
1020
        know ((fixP->fx_bit_fixP != NULL));
1021
#endif
1022
      break;
1023
 
1024
    case RELOC_DLX_HI16:
1025
      if (fixP->fx_bit_fixP != NULL)
1026
        {
1027
          val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base;
1028
          free (fixP->fx_bit_fixP);
1029
          fixP->fx_bit_fixP = NULL;
1030
        }
1031
#ifdef DEBUG
1032
      else
1033
        know ((fixP->fx_bit_fixP != NULL));
1034
#endif
1035
      break;
1036
 
1037
    case RELOC_DLX_REL26:
1038
      if (fixP->fx_bit_fixP != NULL)
1039
        {
1040
          val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base;
1041
          free (fixP->fx_bit_fixP);
1042
          fixP->fx_bit_fixP = NULL;
1043
        }
1044
#ifdef DEBUG
1045
      else
1046
        know ((fixP->fx_bit_fixP != NULL));
1047
#endif
1048
      break;
1049
 
1050
    case BFD_RELOC_VTABLE_INHERIT:
1051
      /* This borrowed from tc-ppc.c on a whim.  */
1052
      fixP->fx_done = 0;
1053
      if (fixP->fx_addsy
1054
          && !S_IS_DEFINED (fixP->fx_addsy)
1055
          && !S_IS_WEAK (fixP->fx_addsy))
1056
        S_SET_WEAK (fixP->fx_addsy);
1057
      return;
1058
 
1059
    case BFD_RELOC_VTABLE_ENTRY:
1060
      fixP->fx_done = 0;
1061
      return;
1062
 
1063
    default:
1064
      break;
1065
    }
1066
 
1067
  number_to_chars_bigendian (place, val, fixP->fx_size);
1068
  if (fixP->fx_addsy == NULL)
1069
    fixP->fx_done = 1;
1070
}
1071
 
1072
const char *md_shortopts = "";
1073
 
1074
struct option md_longopts[] =
1075
  {
1076
    {NULL, no_argument, NULL, 0}
1077
  };
1078
 
1079
size_t md_longopts_size = sizeof (md_longopts);
1080
 
1081
int
1082
md_parse_option (int c     ATTRIBUTE_UNUSED,
1083
                 char *arg ATTRIBUTE_UNUSED)
1084
{
1085
  return 0;
1086
}
1087
 
1088
void
1089
md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
1090
{
1091
}
1092
 
1093
/* This is called when a line is unrecognized.  */
1094
 
1095
int
1096
dlx_unrecognized_line (int c)
1097
{
1098
  int lab;
1099
  char *s;
1100
 
1101
  if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
1102
    return 0;
1103
 
1104
  s = input_line_pointer;
1105
 
1106
  lab = 0;
1107
  while (ISDIGIT ((unsigned char) *s))
1108
    {
1109
      lab = lab * 10 + *s - '0';
1110
      ++s;
1111
    }
1112
 
1113
  if (*s != ':')
1114
    /* Not a label definition.  */
1115
    return 0;
1116
 
1117
  if (dollar_label_defined (lab))
1118
    {
1119
      as_bad (_("label \"$%d\" redefined"), lab);
1120
      return 0;
1121
    }
1122
 
1123
  define_dollar_label (lab);
1124
  colon (dollar_label_name (lab, 0));
1125
  input_line_pointer = s + 1;
1126
 
1127
  return 1;
1128
}
1129
 
1130
/* Default the values of symbols known that should be "predefined".  We
1131
   don't bother to predefine them unless you actually use one, since there
1132
   are a lot of them.  */
1133
 
1134
symbolS *
1135
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1136
{
1137
  return NULL;
1138
}
1139
 
1140
/* Parse an operand that is machine-specific, the function was called
1141
   in expr.c by operand() function, when everything failed before it
1142
   call a quit.  */
1143
 
1144
void
1145
md_operand (expressionS* expressionP)
1146
{
1147
  /* Check for the #number representation    */
1148
  if (input_line_pointer[0] == '#' &&
1149
      ISDIGIT ((unsigned char) input_line_pointer[1]))
1150
    {
1151
      /* We have a numeric number expression.  No biggy.  */
1152
      input_line_pointer += 1;  /* Skip # */
1153
 
1154
      (void) expression (expressionP);
1155
 
1156
      if (expressionP->X_op != O_constant)
1157
        as_bad (_("Invalid expression after # number\n"));
1158
    }
1159
 
1160
  return;
1161
}
1162
 
1163
/* Round up a section size to the appropriate boundary.  */
1164
 
1165
valueT
1166
md_section_align (segT segment ATTRIBUTE_UNUSED,
1167
                  valueT size)
1168
{
1169
  /* Byte alignment is fine.  */
1170
  return size;
1171
}
1172
 
1173
/* Exactly what point is a PC-relative offset relative TO?
1174
   On the 29000, they're relative to the address of the instruction,
1175
   which we have set up as the address of the fixup too.  */
1176
 
1177
long
1178
md_pcrel_from (fixS* fixP)
1179
{
1180
  return 4 + fixP->fx_where + fixP->fx_frag->fr_address;
1181
}
1182
 
1183
/* Translate internal representation of relocation info to BFD target
1184
   format.
1185
   FIXME: To what extent can we get all relevant targets to use this?
1186
   The above FIXME is from a29k, but I think it is also needed here.    */
1187
 
1188
arelent *
1189
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1190
              fixS *fixP)
1191
{
1192
  arelent * reloc;
1193
 
1194
  reloc = xmalloc (sizeof (arelent));
1195
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1196
 
1197
  if (reloc->howto == NULL)
1198
    {
1199
      as_bad_where (fixP->fx_file, fixP->fx_line,
1200
                    _("internal error: can't export reloc type %d (`%s')"),
1201
                    fixP->fx_r_type,
1202
                    bfd_get_reloc_code_name (fixP->fx_r_type));
1203
      return NULL;
1204
    }
1205
 
1206
  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1207
 
1208
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1209
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1210
  reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1211
 
1212
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1213
    reloc->address = fixP->fx_offset;
1214
  reloc->addend = 0;
1215
 
1216
  return reloc;
1217
}
1218
 
1219
const pseudo_typeS
1220
dlx_pseudo_table[] =
1221
{
1222
  /* Some additional ops that are used by gcc-dlx.  */
1223
  {"asciiz", stringer, 8 + 1},
1224
  {"half", cons, 2},
1225
  {"dword", cons, 8},
1226
  {"word", cons, 4},
1227
  {"proc", s_proc, 0},
1228
  {"endproc", s_proc, 1},
1229
  {NULL, NULL, 0}
1230
};
1231
 
1232
void
1233
dlx_pop_insert (void)
1234
{
1235
  pop_insert (dlx_pseudo_table);
1236
  return ;
1237
}
1238
 

powered by: WebSVN 2.1.0

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