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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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