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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [tc-dlx.c] - Blame information for rev 158

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

Line No. Rev Author Line
1 16 khays
/* tc-ldx.c -- Assemble for the DLX
2
   Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010
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
  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
  opcode = insn->opcode;
709
  memset (&the_insn, '\0', sizeof (the_insn));
710
  the_insn.reloc = NO_RELOC;
711
  the_insn.pcrel = 0;
712
 
713
  /* Set the sip reloc HI16 flag.  */
714
  if (!set_dlx_skip_hi16_flag (1))
715
    as_bad (_("Can not set dlx_skip_hi16_flag"));
716
 
717
  /* Fix the operand string if it is one of load store instructions.  */
718
  s = fix_ld_st_operand (opcode, s);
719
 
720
  /* Build the opcode, checking as we go to make sure that the
721
     operands match.
722
     If an operand matches, we modify the_insn or opcode appropriately,
723
     and do a "continue".  If an operand fails to match, we "break".  */
724
  if (insn->args[0] != '\0' && insn->args[0] != 'N')
725
    {
726
      /* Prime the pump.  */
727
      if (*s == '\0')
728
        {
729
          as_bad (_("Missing arguments for opcode <%s>."), str);
730
          return;
731
        }
732
      else
733
        s = parse_operand (s, operand);
734
    }
735
  else if (insn->args[0] == 'N')
736
    {
737
      /* Clean up the insn and done!  */
738
      the_insn.opcode = opcode;
739
      return;
740
    }
741
 
742
  /* Parse through the args (this is from opcode table), *s point to
743
     the current character of the instruction stream.  */
744
  for (args = insn->args;; ++args)
745
    {
746
      switch (*args)
747
        {
748
          /* End of Line.  */
749
        case '\0':
750
          /* End of args.  */
751
          if (*s == '\0')
752
            {
753
              /* We are truly done.  */
754
              the_insn.opcode = opcode;
755
              /* Clean up the HI and LO mark.  */
756
              the_insn.HI = 0;
757
              the_insn.LO = 0;
758
              return;
759
            }
760
 
761
          the_insn.HI = 0;
762
          the_insn.LO = 0;
763
          as_bad (_("Too many operands: %s"), s);
764
          break;
765
 
766
          /* ',' Args separator */
767
        case ',':
768
          /* Must match a comma.  */
769
          if (*s++ == ',')
770
            {
771
              /* Parse next operand.  */
772
              s = parse_operand (s, operand);
773
              continue;
774
            }
775
          break;
776
 
777
          /* It can be a 'a' register or 'i' operand.  */
778
        case 'P':
779
          /* Macro move operand/reg.  */
780
          if (operand->X_op == O_register)
781
            {
782
              /* Its a register.  */
783
              reg_shift = 21;
784
              goto general_reg;
785
            }
786
 
787
          /* The immediate 16 bits literal, bit 0-15.  */
788
        case 'i':
789
          /* offset, unsigned.  */
790
        case 'I':
791
          /* offset, signed.  */
792
          if (operand->X_op == O_constant)
793
            {
794
              if (the_insn.HI)
795
                operand->X_add_number >>= 16;
796
 
797
              opcode |= operand->X_add_number & 0xFFFF;
798
 
799
              if (the_insn.HI && the_insn.LO)
800
                as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s);
801
              else
802
                {
803
                  the_insn.HI = 0;
804
                  the_insn.LO = 0;
805
                }
806
              continue;
807
            }
808
 
809
          the_insn.reloc        = (the_insn.HI) ? RELOC_DLX_HI16
810
            : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16);
811
          the_insn.reloc_offset = 2;
812
          the_insn.size         = 2;
813
          the_insn.pcrel        = 0;
814
          the_insn.exp          = * operand;
815
          the_insn.HI           = 0;
816
          the_insn.LO           = 0;
817
          continue;
818
 
819
        case 'd':
820
          /* offset, signed.  */
821
          if (operand->X_op == O_constant)
822
            {
823
              opcode |= operand->X_add_number & 0xFFFF;
824
              continue;
825
            }
826
          the_insn.reloc        = RELOC_DLX_REL16;
827
          the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
828
          the_insn.size         = 4;
829
          the_insn.pcrel        = 1;
830
          the_insn.exp          = *operand;
831
          continue;
832
 
833
          /* The immediate 26 bits literal, bit 0-25.  */
834
        case 'D':
835
          /* offset, signed.  */
836
          if (operand->X_op == O_constant)
837
            {
838
              opcode |= operand->X_add_number & 0x3FFFFFF;
839
              continue;
840
            }
841
          the_insn.reloc = RELOC_DLX_REL26;
842
          the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
843
          the_insn.size  = 4;
844
          the_insn.pcrel = 1;
845
          the_insn.exp = *operand;
846
          continue;
847
 
848
          /* Type 'a' Register.  */
849
        case 'a':
850
          /* A general register at bits 21-25, rs1.  */
851
          reg_shift = 21;
852
          goto general_reg;
853
 
854
          /* Type 'b' Register.  */
855
        case 'b':
856
          /* A general register at bits 16-20, rs2/rd.  */
857
          reg_shift = 16;
858
          goto general_reg;
859
 
860
          /* Type 'c' Register.  */
861
        case 'c':
862
          /* A general register at bits 11-15, rd.  */
863
          reg_shift = 11;
864
 
865
        general_reg:
866
          know (operand->X_add_symbol == 0);
867
          know (operand->X_op_symbol == 0);
868
          reg = operand->X_add_number;
869
          if (reg & 0xffffffe0)
870
            as_fatal (_("failed regnum sanity check."));
871
          else
872
            /* Got the register, now figure out where it goes in the opcode.  */
873
            opcode |= reg << reg_shift;
874
 
875
          switch (*args)
876
            {
877
            case 'a':
878
            case 'b':
879
            case 'c':
880
            case 'P':
881
              continue;
882
            }
883
          as_fatal (_("failed general register sanity check."));
884
          break;
885
 
886
        default:
887
          BAD_CASE (*args);
888
        }
889
 
890
      /* Types or values of args don't match.  */
891
      as_bad (_("Invalid operands"));
892
      return;
893
    }
894
}
895
 
896
/* Assemble a single instruction.  Its label has already been handled
897
   by the generic front end.  We just parse opcode and operands, and
898
   produce the bytes of data and relocation.  */
899
 
900
void
901
md_assemble (char *str)
902
{
903
  char *toP;
904
  fixS *fixP;
905
  bit_fixS *bitP;
906
 
907
  know (str);
908
  machine_ip (str);
909
  toP = frag_more (4);
910
  dwarf2_emit_insn (4);
911
 
912
  /* Put out the opcode.  */
913
  md_number_to_chars (toP, the_insn.opcode, 4);
914
 
915
  /* Put out the symbol-dependent stuff.  */
916
  if (the_insn.reloc != NO_RELOC)
917
    {
918
      fixP = fix_new_exp (frag_now,
919
                          (toP - frag_now->fr_literal + the_insn.reloc_offset),
920
                          the_insn.size, & the_insn.exp, the_insn.pcrel,
921
                          the_insn.reloc);
922
 
923
      /* Turn off complaints that the addend is
924
         too large for things like foo+100000@ha.  */
925
      switch (the_insn.reloc)
926
        {
927
        case RELOC_DLX_HI16:
928
        case RELOC_DLX_LO16:
929
          fixP->fx_no_overflow = 1;
930
          break;
931
        default:
932
          break;
933
        }
934
 
935
      switch (fixP->fx_r_type)
936
        {
937
        case RELOC_DLX_REL26:
938
          bitP = malloc (sizeof (bit_fixS));
939
          bitP->fx_bit_size = 26;
940
          bitP->fx_bit_offset = 25;
941
          bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
942
          bitP->fx_bit_base_adj = 0;
943
          bitP->fx_bit_max = 0;
944
          bitP->fx_bit_min = 0;
945
          bitP->fx_bit_add = 0x03FFFFFF;
946
          fixP->fx_bit_fixP = bitP;
947
          break;
948
        case RELOC_DLX_LO16:
949
        case RELOC_DLX_REL16:
950
          bitP = malloc (sizeof (bit_fixS));
951
          bitP->fx_bit_size = 16;
952
          bitP->fx_bit_offset = 15;
953
          bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
954
          bitP->fx_bit_base_adj = 0;
955
          bitP->fx_bit_max = 0;
956
          bitP->fx_bit_min = 0;
957
          bitP->fx_bit_add = 0x0000FFFF;
958
          fixP->fx_bit_fixP = bitP;
959
          break;
960
        case RELOC_DLX_HI16:
961
          bitP = malloc (sizeof (bit_fixS));
962
          bitP->fx_bit_size = 16;
963
          bitP->fx_bit_offset = 15;
964
          bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
965
          bitP->fx_bit_base_adj = 0;
966
          bitP->fx_bit_max = 0;
967
          bitP->fx_bit_min = 0;
968
          bitP->fx_bit_add = 0x0000FFFF;
969
          fixP->fx_bit_fixP = bitP;
970
          break;
971
        default:
972
          fixP->fx_bit_fixP = NULL;
973
          break;
974
        }
975
    }
976
}
977
 
978
/* This is identical to the md_atof in m68k.c.  I think this is right,
979
   but I'm not sure.  Dlx will not use it anyway, so I just leave it
980
   here for now.  */
981
 
982
char *
983
md_atof (int type, char *litP, int *sizeP)
984
{
985
  return ieee_md_atof (type, litP, sizeP, TRUE);
986
}
987
 
988
/* Write out big-endian.  */
989
void
990
md_number_to_chars (char *buf, valueT val, int n)
991
{
992
  number_to_chars_bigendian (buf, val, n);
993
}
994
 
995
bfd_boolean
996
md_dlx_fix_adjustable (fixS *fixP)
997
{
998
  /* We need the symbol name for the VTABLE entries.  */
999
  return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT
1000
          && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY);
1001
}
1002
 
1003
void
1004
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1005
{
1006
  long val = *valP;
1007
  char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
1008
 
1009
  switch (fixP->fx_r_type)
1010
    {
1011
    case RELOC_DLX_LO16:
1012
    case RELOC_DLX_REL16:
1013
      if (fixP->fx_bit_fixP != NULL)
1014
        {
1015
          val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base;
1016
          free (fixP->fx_bit_fixP);
1017
          fixP->fx_bit_fixP = NULL;
1018
        }
1019
#ifdef DEBUG
1020
      else
1021
        know ((fixP->fx_bit_fixP != NULL));
1022
#endif
1023
      break;
1024
 
1025
    case RELOC_DLX_HI16:
1026
      if (fixP->fx_bit_fixP != NULL)
1027
        {
1028
          val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base;
1029
          free (fixP->fx_bit_fixP);
1030
          fixP->fx_bit_fixP = NULL;
1031
        }
1032
#ifdef DEBUG
1033
      else
1034
        know ((fixP->fx_bit_fixP != NULL));
1035
#endif
1036
      break;
1037
 
1038
    case RELOC_DLX_REL26:
1039
      if (fixP->fx_bit_fixP != NULL)
1040
        {
1041
          val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base;
1042
          free (fixP->fx_bit_fixP);
1043
          fixP->fx_bit_fixP = NULL;
1044
        }
1045
#ifdef DEBUG
1046
      else
1047
        know ((fixP->fx_bit_fixP != NULL));
1048
#endif
1049
      break;
1050
 
1051
    case BFD_RELOC_VTABLE_INHERIT:
1052
      /* This borrowed from tc-ppc.c on a whim.  */
1053
      fixP->fx_done = 0;
1054
      if (fixP->fx_addsy
1055
          && !S_IS_DEFINED (fixP->fx_addsy)
1056
          && !S_IS_WEAK (fixP->fx_addsy))
1057
        S_SET_WEAK (fixP->fx_addsy);
1058
      return;
1059
 
1060
    case BFD_RELOC_VTABLE_ENTRY:
1061
      fixP->fx_done = 0;
1062
      return;
1063
 
1064
    default:
1065
      break;
1066
    }
1067
 
1068
  number_to_chars_bigendian (place, val, fixP->fx_size);
1069
  if (fixP->fx_addsy == NULL)
1070
    fixP->fx_done = 1;
1071
}
1072
 
1073
const char *md_shortopts = "";
1074
 
1075
struct option md_longopts[] =
1076
  {
1077
    {NULL, no_argument, NULL, 0}
1078
  };
1079
 
1080
size_t md_longopts_size = sizeof (md_longopts);
1081
 
1082
int
1083
md_parse_option (int c     ATTRIBUTE_UNUSED,
1084
                 char *arg ATTRIBUTE_UNUSED)
1085
{
1086
  return 0;
1087
}
1088
 
1089
void
1090
md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
1091
{
1092
}
1093
 
1094
/* This is called when a line is unrecognized.  */
1095
 
1096
int
1097
dlx_unrecognized_line (int c)
1098
{
1099
  int lab;
1100
  char *s;
1101
 
1102
  if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
1103
    return 0;
1104
 
1105
  s = input_line_pointer;
1106
 
1107
  lab = 0;
1108
  while (ISDIGIT ((unsigned char) *s))
1109
    {
1110
      lab = lab * 10 + *s - '0';
1111
      ++s;
1112
    }
1113
 
1114
  if (*s != ':')
1115
    /* Not a label definition.  */
1116
    return 0;
1117
 
1118
  if (dollar_label_defined (lab))
1119
    {
1120
      as_bad (_("label \"$%d\" redefined"), lab);
1121
      return 0;
1122
    }
1123
 
1124
  define_dollar_label (lab);
1125
  colon (dollar_label_name (lab, 0));
1126
  input_line_pointer = s + 1;
1127
 
1128
  return 1;
1129
}
1130
 
1131
/* Default the values of symbols known that should be "predefined".  We
1132
   don't bother to predefine them unless you actually use one, since there
1133
   are a lot of them.  */
1134
 
1135
symbolS *
1136
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1137
{
1138
  return NULL;
1139
}
1140
 
1141
/* Parse an operand that is machine-specific, the function was called
1142
   in expr.c by operand() function, when everything failed before it
1143
   call a quit.  */
1144
 
1145
void
1146
md_operand (expressionS* expressionP)
1147
{
1148
  /* Check for the #number representation    */
1149
  if (input_line_pointer[0] == '#' &&
1150
      ISDIGIT ((unsigned char) input_line_pointer[1]))
1151
    {
1152
      /* We have a numeric number expression.  No biggy.  */
1153
      input_line_pointer += 1;  /* Skip # */
1154
 
1155
      (void) expression (expressionP);
1156
 
1157
      if (expressionP->X_op != O_constant)
1158
        as_bad (_("Invalid expression after # number\n"));
1159
    }
1160
 
1161
  return;
1162
}
1163
 
1164
/* Round up a section size to the appropriate boundary.  */
1165
 
1166
valueT
1167
md_section_align (segT segment ATTRIBUTE_UNUSED,
1168
                  valueT size)
1169
{
1170
  /* Byte alignment is fine.  */
1171
  return size;
1172
}
1173
 
1174
/* Exactly what point is a PC-relative offset relative TO?
1175
   On the 29000, they're relative to the address of the instruction,
1176
   which we have set up as the address of the fixup too.  */
1177
 
1178
long
1179
md_pcrel_from (fixS* fixP)
1180
{
1181
  return 4 + fixP->fx_where + fixP->fx_frag->fr_address;
1182
}
1183
 
1184
/* Translate internal representation of relocation info to BFD target
1185
   format.
1186
   FIXME: To what extent can we get all relevant targets to use this?
1187
   The above FIXME is from a29k, but I think it is also needed here.    */
1188
 
1189
arelent *
1190
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1191
              fixS *fixP)
1192
{
1193
  arelent * reloc;
1194
 
1195
  reloc = xmalloc (sizeof (arelent));
1196
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1197
 
1198
  if (reloc->howto == NULL)
1199
    {
1200
      as_bad_where (fixP->fx_file, fixP->fx_line,
1201
                    _("internal error: can't export reloc type %d (`%s')"),
1202
                    fixP->fx_r_type,
1203
                    bfd_get_reloc_code_name (fixP->fx_r_type));
1204
      return NULL;
1205
    }
1206
 
1207
  gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1208
 
1209
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1210
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1211
  reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1212
 
1213
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1214
    reloc->address = fixP->fx_offset;
1215
  reloc->addend = 0;
1216
 
1217
  return reloc;
1218
}
1219
 
1220
const pseudo_typeS
1221
dlx_pseudo_table[] =
1222
{
1223
  /* Some additional ops that are used by gcc-dlx.  */
1224
  {"asciiz", stringer, 8 + 1},
1225
  {"half", cons, 2},
1226
  {"dword", cons, 8},
1227
  {"word", cons, 4},
1228
  {"proc", s_proc, 0},
1229
  {"endproc", s_proc, 1},
1230
  {NULL, NULL, 0}
1231
};
1232
 
1233
void
1234
dlx_pop_insert (void)
1235
{
1236
  pop_insert (dlx_pseudo_table);
1237
  return ;
1238
}

powered by: WebSVN 2.1.0

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