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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [cpu/] [ip2k.opc] - Blame information for rev 161

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 161 khays
/* IP2K opcode support.  -*- C -*-
2
   Copyright 2002, 2005, 2011 Free Software Foundation, Inc.
3
 
4
   Contributed by Red Hat Inc;
5
 
6
   This file is part of the GNU Binutils.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
/*
24
   Each section is delimited with start and end markers.
25
 
26
   -opc.h additions use: "-- opc.h"
27
   -opc.c additions use: "-- opc.c"
28
   -asm.c additions use: "-- asm.c"
29
   -dis.c additions use: "-- dis.c"
30
   -ibd.h additions use: "-- ibd.h".  */
31
 
32
/* -- opc.h */
33
 
34
/* Check applicability of instructions against machines.  */
35
#define CGEN_VALIDATE_INSN_SUPPORTED
36
 
37
/* Allows reason codes to be output when assembler errors occur.  */
38
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
39
 
40
/* Override disassembly hashing - there are variable bits in the top
41
   byte of these instructions.  */
42
#define CGEN_DIS_HASH_SIZE 8
43
#define CGEN_DIS_HASH(buf, value) \
44
  (((* (unsigned char*) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
45
 
46
#define CGEN_ASM_HASH_SIZE 127
47
#define CGEN_ASM_HASH(insn) ip2k_asm_hash (insn)
48
 
49
extern unsigned int ip2k_asm_hash (const char *);
50
extern int ip2k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
51
 
52
/* -- opc.c */
53
 
54
#include "safe-ctype.h"
55
 
56
/* A better hash function for instruction mnemonics.  */
57
unsigned int
58
ip2k_asm_hash (const char* insn)
59
{
60
  unsigned int hash;
61
  const char* m = insn;
62
 
63
  for (hash = 0; *m && ! ISSPACE (*m); m++)
64
    hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
65
 
66
  /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
67
 
68
  return hash % CGEN_ASM_HASH_SIZE;
69
}
70
 
71
 
72
/* Special check to ensure that instruction exists for given machine.  */
73
 
74
int
75
ip2k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
76
{
77
  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
78
 
79
  /* No mach attribute?  Assume it's supported for all machs.  */
80
  if (machs == 0)
81
    return 1;
82
 
83
  return (machs & cd->machs) != 0;
84
}
85
 
86
 
87
/* -- asm.c */
88
 
89
static const char *
90
parse_fr (CGEN_CPU_DESC cd,
91
          const char **strp,
92
          int opindex,
93
          unsigned long *valuep)
94
{
95
  const char *errmsg;
96
  const char *old_strp;
97
  char *afteroffset;
98
  enum cgen_parse_operand_result result_type;
99
  bfd_vma value;
100
  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
101
  bfd_vma tempvalue;
102
 
103
  old_strp = *strp;
104
  afteroffset = NULL;
105
 
106
  /* Check here to see if you're about to try parsing a w as the first arg
107
     and return an error if you are.  */
108
  if ((strncmp (*strp, "w", 1) == 0) || (strncmp (*strp, "W", 1) == 0))
109
    {
110
      (*strp)++;
111
 
112
      if ((strncmp (*strp, ",", 1) == 0) || ISSPACE (**strp))
113
        {
114
          /* We've been passed a w.  Return with an error message so that
115
             cgen will try the next parsing option.  */
116
          errmsg = _("W keyword invalid in FR operand slot.");
117
          return errmsg;
118
        }
119
      *strp = old_strp;
120
    }
121
 
122
  /* Attempt parse as register keyword. */
123
  errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names,
124
                               (long *) valuep);
125
  if (*strp != NULL
126
      && errmsg == NULL)
127
    return errmsg;
128
 
129
  /* Attempt to parse for "(IP)".  */
130
  afteroffset = strstr (*strp, "(IP)");
131
 
132
  if (afteroffset == NULL)
133
    /* Make sure it's not in lower case.  */
134
    afteroffset = strstr (*strp, "(ip)");
135
 
136
  if (afteroffset != NULL)
137
    {
138
      if (afteroffset != *strp)
139
        {
140
          /* Invalid offset present.  */
141
          errmsg = _("offset(IP) is not a valid form");
142
          return errmsg;
143
        }
144
      else
145
        {
146
          *strp += 4;
147
          *valuep = 0;
148
          errmsg = NULL;
149
          return errmsg;
150
        }
151
    }
152
 
153
  /* Attempt to parse for DP. ex: mov w, offset(DP)
154
                                  mov offset(DP),w   */
155
 
156
  /* Try parsing it as an address and see what comes back.  */
157
  afteroffset = strstr (*strp, "(DP)");
158
 
159
  if (afteroffset == NULL)
160
    /* Maybe it's in lower case.  */
161
    afteroffset = strstr (*strp, "(dp)");
162
 
163
  if (afteroffset != NULL)
164
    {
165
      if (afteroffset == *strp)
166
        {
167
          /* No offset present. Use 0 by default.  */
168
          tempvalue = 0;
169
          errmsg = NULL;
170
        }
171
      else
172
        errmsg = cgen_parse_address (cd, strp, opindex,
173
                                     BFD_RELOC_IP2K_FR_OFFSET,
174
                                     & result_type, & tempvalue);
175
 
176
      if (errmsg == NULL)
177
        {
178
          if (tempvalue <= 127)
179
            {
180
              /* Value is ok.  Fix up the first 2 bits and return.  */
181
              *valuep = 0x0100 | tempvalue;
182
              *strp += 4; /* Skip over the (DP) in *strp.  */
183
              return errmsg;
184
            }
185
          else
186
            {
187
              /* Found something there in front of (DP) but it's out
188
                 of range.  */
189
              errmsg = _("(DP) offset out of range.");
190
              return errmsg;
191
            }
192
        }
193
    }
194
 
195
 
196
  /* Attempt to parse for SP. ex: mov w, offset(SP)
197
                                  mov offset(SP), w.  */
198
  afteroffset = strstr (*strp, "(SP)");
199
 
200
  if (afteroffset == NULL)
201
    /* Maybe it's in lower case.  */
202
    afteroffset = strstr (*strp, "(sp)");
203
 
204
  if (afteroffset != NULL)
205
    {
206
      if (afteroffset == *strp)
207
        {
208
          /* No offset present. Use 0 by default.  */
209
          tempvalue = 0;
210
          errmsg = NULL;
211
        }
212
      else
213
        errmsg = cgen_parse_address (cd, strp, opindex,
214
                                     BFD_RELOC_IP2K_FR_OFFSET,
215
                                     & result_type, & tempvalue);
216
 
217
      if (errmsg == NULL)
218
        {
219
          if (tempvalue <= 127)
220
            {
221
              /* Value is ok.  Fix up the first 2 bits and return.  */
222
              *valuep = 0x0180 | tempvalue;
223
              *strp += 4; /* Skip over the (SP) in *strp.  */
224
              return errmsg;
225
            }
226
          else
227
            {
228
              /* Found something there in front of (SP) but it's out
229
                 of range.  */
230
              errmsg = _("(SP) offset out of range.");
231
              return errmsg;
232
            }
233
        }
234
    }
235
 
236
  /* Attempt to parse as an address.  */
237
  *strp = old_strp;
238
  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
239
                               & result_type, & value);
240
  if (errmsg == NULL)
241
    {
242
      *valuep = value;
243
 
244
      /* If a parenthesis is found, warn about invalid form.  */
245
      if (**strp == '(')
246
        errmsg = _("illegal use of parentheses");
247
 
248
      /* If a numeric value is specified, ensure that it is between
249
         1 and 255.  */
250
      else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
251
        {
252
          if (value < 0x1 || value > 0xff)
253
            errmsg = _("operand out of range (not between 1 and 255)");
254
        }
255
    }
256
  return errmsg;
257
}
258
 
259
static const char *
260
parse_addr16 (CGEN_CPU_DESC cd,
261
              const char **strp,
262
              int opindex,
263
              unsigned long *valuep)
264
{
265
  const char *errmsg;
266
  enum cgen_parse_operand_result result_type;
267
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
268
  bfd_vma value;
269
 
270
  if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16H)
271
    code = BFD_RELOC_IP2K_HI8DATA;
272
  else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16L)
273
    code = BFD_RELOC_IP2K_LO8DATA;
274
  else
275
    {
276
      /* Something is very wrong. opindex has to be one of the above.  */
277
      errmsg = _("parse_addr16: invalid opindex.");
278
      return errmsg;
279
    }
280
 
281
  errmsg = cgen_parse_address (cd, strp, opindex, code,
282
                               & result_type, & value);
283
  if (errmsg == NULL)
284
    {
285
      /* We either have a relocation or a number now.  */
286
      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
287
        {
288
          /* We got a number back.  */
289
          if (code == BFD_RELOC_IP2K_HI8DATA)
290
            value >>= 8;
291
          else
292
            /* code = BFD_RELOC_IP2K_LOW8DATA.  */
293
            value &= 0x00FF;
294
        }
295
      *valuep = value;
296
    }
297
 
298
  return errmsg;
299
}
300
 
301
static const char *
302
parse_addr16_cjp (CGEN_CPU_DESC cd,
303
                  const char **strp,
304
                  int opindex,
305
                  unsigned long *valuep)
306
{
307
  const char *errmsg;
308
  enum cgen_parse_operand_result result_type;
309
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
310
  bfd_vma value;
311
 
312
  if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
313
    code = BFD_RELOC_IP2K_ADDR16CJP;
314
  else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
315
    code = BFD_RELOC_IP2K_PAGE3;
316
 
317
  errmsg = cgen_parse_address (cd, strp, opindex, code,
318
                               & result_type, & value);
319
  if (errmsg == NULL)
320
    {
321
      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
322
        {
323
          if ((value & 0x1) == 0)  /* If the address is even .... */
324
            {
325
              if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
326
                *valuep = (value >> 1) & 0x1FFF;  /* Should mask be 1FFF?  */
327
              else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
328
                *valuep = (value >> 14) & 0x7;
329
            }
330
          else
331
            errmsg = _("Byte address required. - must be even.");
332
        }
333
      else if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
334
        {
335
          /* This will happen for things like (s2-s1) where s2 and s1
336
             are labels.  */
337
          *valuep = value;
338
        }
339
      else
340
        errmsg = _("cgen_parse_address returned a symbol. Literal required.");
341
    }
342
  return errmsg;
343
}
344
 
345
static const char *
346
parse_lit8 (CGEN_CPU_DESC cd,
347
            const char **strp,
348
            int opindex,
349
            long *valuep)
350
{
351
  const char *errmsg;
352
  enum cgen_parse_operand_result result_type;
353
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
354
  bfd_vma value;
355
 
356
  /* Parse %OP relocating operators.  */
357
  if (strncmp (*strp, "%bank", 5) == 0)
358
    {
359
      *strp += 5;
360
      code = BFD_RELOC_IP2K_BANK;
361
    }
362
  else if (strncmp (*strp, "%lo8data", 8) == 0)
363
    {
364
      *strp += 8;
365
      code = BFD_RELOC_IP2K_LO8DATA;
366
    }
367
  else if (strncmp (*strp, "%hi8data", 8) == 0)
368
    {
369
      *strp += 8;
370
      code = BFD_RELOC_IP2K_HI8DATA;
371
    }
372
  else if (strncmp (*strp, "%ex8data", 8) == 0)
373
    {
374
      *strp += 8;
375
      code = BFD_RELOC_IP2K_EX8DATA;
376
    }
377
  else if (strncmp (*strp, "%lo8insn", 8) == 0)
378
    {
379
      *strp += 8;
380
      code = BFD_RELOC_IP2K_LO8INSN;
381
    }
382
  else if (strncmp (*strp, "%hi8insn", 8) == 0)
383
    {
384
      *strp += 8;
385
      code = BFD_RELOC_IP2K_HI8INSN;
386
    }
387
 
388
  /* Parse %op operand.  */
389
  if (code != BFD_RELOC_NONE)
390
    {
391
      errmsg = cgen_parse_address (cd, strp, opindex, code,
392
                                   & result_type, & value);
393
      if ((errmsg == NULL) &&
394
          (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
395
        errmsg = _("percent-operator operand is not a symbol");
396
 
397
      *valuep = value;
398
    }
399
  /* Parse as a number.  */
400
  else
401
    {
402
      errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
403
 
404
      /* Truncate to eight bits to accept both signed and unsigned input.  */
405
      if (errmsg == NULL)
406
        *valuep &= 0xFF;
407
    }
408
 
409
  return errmsg;
410
}
411
 
412
static const char *
413
parse_bit3 (CGEN_CPU_DESC cd,
414
            const char **strp,
415
            int opindex,
416
            unsigned long *valuep)
417
{
418
  const char *errmsg;
419
  char mode = 0;
420
  long count = 0;
421
  unsigned long value;
422
 
423
  if (strncmp (*strp, "%bit", 4) == 0)
424
    {
425
      *strp += 4;
426
      mode = 1;
427
    }
428
  else if (strncmp (*strp, "%msbbit", 7) == 0)
429
    {
430
      *strp += 7;
431
      mode = 1;
432
    }
433
  else if (strncmp (*strp, "%lsbbit", 7) == 0)
434
    {
435
      *strp += 7;
436
      mode = 2;
437
    }
438
 
439
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
440
  if (errmsg)
441
    return errmsg;
442
 
443
  if (mode)
444
    {
445
      value = * valuep;
446
      if (value == 0)
447
        {
448
          errmsg = _("Attempt to find bit index of 0");
449
          return errmsg;
450
        }
451
 
452
      if (mode == 1)
453
        {
454
          count = 31;
455
          while ((value & 0x80000000) == 0)
456
            {
457
              count--;
458
              value <<= 1;
459
            }
460
        }
461
      else if (mode == 2)
462
        {
463
          count = 0;
464
          while ((value & 0x00000001) == 0)
465
            {
466
              count++;
467
              value >>= 1;
468
            }
469
        }
470
 
471
      *valuep = count;
472
    }
473
 
474
  return errmsg;
475
}
476
 
477
/* -- dis.c */
478
 
479
static void
480
print_fr (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
481
          void * dis_info,
482
          long value,
483
          unsigned int attrs ATTRIBUTE_UNUSED,
484
          bfd_vma pc ATTRIBUTE_UNUSED,
485
          int length ATTRIBUTE_UNUSED)
486
{
487
  disassemble_info *info = (disassemble_info *) dis_info;
488
  const CGEN_KEYWORD_ENTRY *ke;
489
  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
490
  long offsettest;
491
  long offsetvalue;
492
 
493
  if (value == 0) /* This is (IP).  */
494
    {
495
      (*info->fprintf_func) (info->stream, "%s", "(IP)");
496
      return;
497
    }
498
 
499
  offsettest = value >> 7;
500
  offsetvalue = value & 0x7F;
501
 
502
  /* Check to see if first two bits are 10 -> (DP).  */
503
  if (offsettest == 2)
504
    {
505
      if (offsetvalue == 0)
506
        (*info->fprintf_func) (info->stream, "%s","(DP)");
507
      else
508
        (*info->fprintf_func) (info->stream, "$%lx%s", offsetvalue, "(DP)");
509
      return;
510
    }
511
 
512
  /* Check to see if first two bits are 11 -> (SP).  */
513
  if (offsettest == 3)
514
    {
515
      if (offsetvalue == 0)
516
        (*info->fprintf_func) (info->stream, "%s", "(SP)");
517
      else
518
        (*info->fprintf_func) (info->stream, "$%lx%s", offsetvalue,"(SP)");
519
      return;
520
    }
521
 
522
  /* Attempt to print as a register keyword.  */
523
  ke = cgen_keyword_lookup_value (& ip2k_cgen_opval_register_names, value);
524
 
525
  if (ke != NULL)
526
    (*info->fprintf_func) (info->stream, "%s", ke->name);
527
  else
528
    /* Print as an address literal.  */
529
    (*info->fprintf_func) (info->stream, "$%02lx", value);
530
}
531
 
532
static void
533
print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
534
                 void * dis_info,
535
                 long value,
536
                 unsigned int attrs ATTRIBUTE_UNUSED,
537
                 bfd_vma pc ATTRIBUTE_UNUSED,
538
                 int length ATTRIBUTE_UNUSED)
539
{
540
  disassemble_info *info = (disassemble_info *) dis_info;
541
 
542
  (*info->fprintf_func) (info->stream, "$%lx", value);
543
}
544
 
545
static void
546
print_dollarhex8 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
547
                  void * dis_info,
548
                  long value,
549
                  unsigned int attrs ATTRIBUTE_UNUSED,
550
                  bfd_vma pc ATTRIBUTE_UNUSED,
551
                  int length ATTRIBUTE_UNUSED)
552
{
553
  disassemble_info *info = (disassemble_info *) dis_info;
554
 
555
  (*info->fprintf_func) (info->stream, "$%02lx", value);
556
}
557
 
558
static void
559
print_dollarhex_addr16h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
560
                         void * dis_info,
561
                         long value,
562
                         unsigned int attrs ATTRIBUTE_UNUSED,
563
                         bfd_vma pc ATTRIBUTE_UNUSED,
564
                         int length ATTRIBUTE_UNUSED)
565
{
566
  disassemble_info *info = (disassemble_info *) dis_info;
567
 
568
  /* This is a loadh instruction. Shift the value to the left
569
     by 8 bits so that disassembled code will reassemble properly.  */
570
  value = ((value << 8) & 0xFF00);
571
 
572
  (*info->fprintf_func) (info->stream, "$%04lx", value);
573
}
574
 
575
static void
576
print_dollarhex_addr16l (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
577
                         void * dis_info,
578
                         long value,
579
                         unsigned int attrs ATTRIBUTE_UNUSED,
580
                         bfd_vma pc ATTRIBUTE_UNUSED,
581
                         int length ATTRIBUTE_UNUSED)
582
{
583
  disassemble_info *info = (disassemble_info *) dis_info;
584
 
585
  (*info->fprintf_func) (info->stream, "$%04lx", value);
586
}
587
 
588
static void
589
print_dollarhex_p (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
590
                   void * dis_info,
591
                   long value,
592
                   unsigned int attrs ATTRIBUTE_UNUSED,
593
                   bfd_vma pc ATTRIBUTE_UNUSED,
594
                   int length ATTRIBUTE_UNUSED)
595
{
596
  disassemble_info *info = (disassemble_info *) dis_info;
597
 
598
  value = ((value << 14) & 0x1C000);
599
  ;value = (value  & 0x1FFFF);
600
  (*info->fprintf_func) (info->stream, "$%05lx", value);
601
}
602
 
603
static void
604
print_dollarhex_cj (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
605
                    void * dis_info,
606
                    long value,
607
                    unsigned int attrs ATTRIBUTE_UNUSED,
608
                    bfd_vma pc ATTRIBUTE_UNUSED,
609
                    int length ATTRIBUTE_UNUSED)
610
{
611
  disassemble_info *info = (disassemble_info *) dis_info;
612
 
613
  value = ((value << 1) & 0x1FFFF);
614
  (*info->fprintf_func) (info->stream, "$%05lx", value);
615
}
616
 
617
static void
618
print_decimal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
619
               void * dis_info,
620
               long value,
621
               unsigned int attrs ATTRIBUTE_UNUSED,
622
               bfd_vma pc ATTRIBUTE_UNUSED,
623
               int length ATTRIBUTE_UNUSED)
624
{
625
  disassemble_info *info = (disassemble_info *) dis_info;
626
 
627
  (*info->fprintf_func) (info->stream, "%ld", value);
628
}
629
 
630
 
631
 
632
/* -- */
633
 

powered by: WebSVN 2.1.0

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