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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [cpu/] [m32c.opc] - Blame information for rev 827

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

Line No. Rev Author Line
1 205 julius
/* m32c opcode support.  -*- C -*-
2
 
3
   Copyright 2005, 2007, 2009 Free Software Foundation, Inc.
4
 
5
   Contributed by Red Hat Inc; developed under contract from Renesas
6
 
7
   This file is part of the GNU Binutils.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
 
25
/* This file is an addendum to m32c.cpu.  Heavy use of C code isn't
26
   appropriate in .cpu files, so it resides here.  This especially applies
27
   to assembly/disassembly where parsing/printing can be quite involved.
28
   Such things aren't really part of the specification of the cpu, per se,
29
   so .cpu files provide the general framework and .opc files handle the
30
   nitty-gritty details as necessary.
31
 
32
   Each section is delimited with start and end markers.
33
 
34
   -opc.h additions use: "-- opc.h"
35
   -opc.c additions use: "-- opc.c"
36
   -asm.c additions use: "-- asm.c"
37
   -dis.c additions use: "-- dis.c"
38
   -ibd.h additions use: "-- ibd.h".  */
39
 
40
/* -- opc.h */
41
 
42
/* Needed for RTL's 'ext' and 'trunc' operators.  */
43
#include "cgen-types.h"
44
#include "cgen-ops.h"
45
 
46
/* We can't use the default hash size because many bits are used by
47
   operands.  */
48
#define CGEN_DIS_HASH_SIZE 1
49
#define CGEN_DIS_HASH(buf, value) 0
50
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
51
#define CGEN_VALIDATE_INSN_SUPPORTED
52
 
53
extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
54
 
55
#define CGEN_ASM_HASH_SIZE 0xffff
56
#define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
57
 
58
/* -- */
59
 
60
/* -- opc.c */
61
static unsigned int
62
m32c_asm_hash (const char *mnem)
63
{
64
  unsigned int h;
65
 
66
  /* The length of the mnemonic for the Jcnd insns is 1.  Hash jsri.  */
67
  if (mnem[0] == 'j' && mnem[1] != 's')
68
    return 'j';
69
 
70
  /* Don't hash scCND  */
71
  if (mnem[0] == 's' && mnem[1] == 'c')
72
    return 's';
73
 
74
  /* Don't hash bmCND  */
75
  if (mnem[0] == 'b' && mnem[1] == 'm')
76
    return 'b';
77
 
78
  for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
79
    h += *mnem;
80
  return h % CGEN_ASM_HASH_SIZE;
81
}
82
 
83
/* -- asm.c */
84
#include "safe-ctype.h"
85
 
86
#define MACH_M32C 5             /* Must match md_begin.  */
87
 
88
static int
89
m32c_cgen_isa_register (const char **strp)
90
 {
91
   int u;
92
   const char *s = *strp;
93
   static char * m32c_register_names [] =
94
     {
95
       "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
96
       "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
97
       "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
98
       "dma1", "dra0", "dra1", "dsa0", "dsa1", 0
99
     };
100
 
101
   for (u = 0; m32c_register_names[u]; u++)
102
     {
103
       int len = strlen (m32c_register_names[u]);
104
 
105
       if (memcmp (m32c_register_names[u], s, len) == 0
106
           && (s[len] == 0 || ! ISALNUM (s[len])))
107
        return 1;
108
     }
109
   return 0;
110
}
111
 
112
#define PARSE_UNSIGNED                                                  \
113
  do                                                                    \
114
    {                                                                   \
115
      /* Don't successfully parse literals beginning with '['.  */      \
116
      if (**strp == '[')                                                \
117
        return "Invalid literal"; /* Anything -- will not be seen.  */  \
118
                                                                        \
119
      errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\
120
      if (errmsg)                                                       \
121
        return errmsg;                                                  \
122
    }                                                                   \
123
  while (0)
124
 
125
#define PARSE_SIGNED                                                    \
126
  do                                                                    \
127
    {                                                                   \
128
      /* Don't successfully parse literals beginning with '['.  */      \
129
      if (**strp == '[')                                                \
130
        return "Invalid literal"; /* Anything -- will not be seen.  */  \
131
                                                                        \
132
      errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);  \
133
      if (errmsg)                                                       \
134
        return errmsg;                                                  \
135
    }                                                                   \
136
  while (0)
137
 
138
static const char *
139
parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
140
                 int opindex, unsigned long *valuep)
141
{
142
  const char *errmsg = 0;
143
  unsigned long value;
144
 
145
  PARSE_UNSIGNED;
146
 
147
  if (value > 0x3f)
148
    return _("imm:6 immediate is out of range");
149
 
150
  *valuep = value;
151
  return 0;
152
}
153
 
154
static const char *
155
parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
156
                 int opindex, unsigned long *valuep)
157
{
158
  const char *errmsg = 0;
159
  unsigned long value;
160
  long have_zero = 0;
161
 
162
  if (strncasecmp (*strp, "%dsp8(", 6) == 0)
163
    {
164
      enum cgen_parse_operand_result result_type;
165
      bfd_vma value;
166
      const char *errmsg;
167
 
168
      *strp += 6;
169
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
170
                                   & result_type, & value);
171
      if (**strp != ')')
172
        return _("missing `)'");
173
      (*strp) ++;
174
 
175
      if (errmsg == NULL
176
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
177
        {
178
          return _("%dsp8() takes a symbolic address, not a number");
179
        }
180
      *valuep = value;
181
      return errmsg;
182
    }
183
 
184
  if (strncmp (*strp, "0x0", 3) == 0
185
      || (**strp == '0' && *(*strp + 1) != 'x'))
186
    have_zero = 1;
187
 
188
  PARSE_UNSIGNED;
189
 
190
  if (value > 0xff)
191
    return _("dsp:8 immediate is out of range");
192
 
193
  /* If this field may require a relocation then use larger dsp16.  */
194
  if (! have_zero && value == 0)
195
    return _("dsp:8 immediate is out of range");
196
 
197
  *valuep = value;
198
  return 0;
199
}
200
 
201
static const char *
202
parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
203
               int opindex, signed long *valuep)
204
{
205
  const char *errmsg = 0;
206
  signed long value;
207
  long have_zero = 0;
208
 
209
  if (strncmp (*strp, "0x0", 3) == 0
210
      || (**strp == '0' && *(*strp + 1) != 'x'))
211
    have_zero = 1;
212
 
213
  PARSE_SIGNED;
214
 
215
  if (value < -8 || value > 7)
216
    return _("Immediate is out of range -8 to 7");
217
 
218
  /* If this field may require a relocation then use larger dsp16.  */
219
  if (! have_zero && value == 0)
220
    return _("Immediate is out of range -8 to 7");
221
 
222
  *valuep = value;
223
  return 0;
224
}
225
 
226
static const char *
227
parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
228
                int opindex, signed long *valuep)
229
{
230
  const char *errmsg = 0;
231
  signed long value;
232
  long have_zero = 0;
233
 
234
  if (strncmp (*strp, "0x0", 3) == 0
235
      || (**strp == '0' && *(*strp + 1) != 'x'))
236
    have_zero = 1;
237
 
238
  PARSE_SIGNED;
239
 
240
  if (value < -7 || value > 8)
241
    return _("Immediate is out of range -7 to 8");
242
 
243
  /* If this field may require a relocation then use larger dsp16.  */
244
  if (! have_zero && value == 0)
245
    return _("Immediate is out of range -7 to 8");
246
 
247
  *valuep = -value;
248
  return 0;
249
}
250
 
251
static const char *
252
parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
253
               int opindex, signed long *valuep)
254
{
255
  const char *errmsg = 0;
256
  signed long value;
257
 
258
  if (strncasecmp (*strp, "%hi8(", 5) == 0)
259
    {
260
      enum cgen_parse_operand_result result_type;
261
      bfd_vma value;
262
      const char *errmsg;
263
 
264
      *strp += 5;
265
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
266
                                   & result_type, & value);
267
      if (**strp != ')')
268
        return _("missing `)'");
269
      (*strp) ++;
270
 
271
      if (errmsg == NULL
272
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
273
        {
274
          value >>= 16;
275
        }
276
      *valuep = value;
277
      return errmsg;
278
    }
279
 
280
  PARSE_SIGNED;
281
 
282
  if (value <= 255 && value > 127)
283
    value -= 0x100;
284
 
285
  if (value < -128 || value > 127)
286
    return _("dsp:8 immediate is out of range");
287
 
288
  *valuep = value;
289
  return 0;
290
}
291
 
292
static const char *
293
parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
294
                 int opindex, unsigned long *valuep)
295
{
296
  const char *errmsg = 0;
297
  unsigned long value;
298
  long have_zero = 0;
299
 
300
  if (strncasecmp (*strp, "%dsp16(", 7) == 0)
301
    {
302
      enum cgen_parse_operand_result result_type;
303
      bfd_vma value;
304
      const char *errmsg;
305
 
306
      *strp += 7;
307
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
308
                                   & result_type, & value);
309
      if (**strp != ')')
310
        return _("missing `)'");
311
      (*strp) ++;
312
 
313
      if (errmsg == NULL
314
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
315
        {
316
          return _("%dsp16() takes a symbolic address, not a number");
317
        }
318
      *valuep = value;
319
      return errmsg;
320
    }
321
 
322
  /* Don't successfully parse literals beginning with '['.  */
323
  if (**strp == '[')
324
    return "Invalid literal"; /* Anything -- will not be seen.  */
325
 
326
  /* Don't successfully parse register names.  */
327
  if (m32c_cgen_isa_register (strp))
328
    return "Invalid literal"; /* Anything -- will not be seen.  */
329
 
330
  if (strncmp (*strp, "0x0", 3) == 0
331
      || (**strp == '0' && *(*strp + 1) != 'x'))
332
    have_zero = 1;
333
 
334
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
335
  if (errmsg)
336
    return errmsg;
337
 
338
  if (value > 0xffff)
339
    return _("dsp:16 immediate is out of range");
340
 
341
  /* If this field may require a relocation then use larger dsp24.  */
342
  if (cd->machs == MACH_M32C && ! have_zero && value == 0
343
      && (strncmp (*strp, "[a", 2) == 0
344
          || **strp == ','
345
          || **strp == 0))
346
    return _("dsp:16 immediate is out of range");
347
 
348
  *valuep = value;
349
  return 0;
350
}
351
 
352
static const char *
353
parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
354
               int opindex, signed long *valuep)
355
{
356
  const char *errmsg = 0;
357
  signed long value;
358
 
359
  if (strncasecmp (*strp, "%lo16(", 6) == 0)
360
    {
361
      enum cgen_parse_operand_result result_type;
362
      bfd_vma value;
363
      const char *errmsg;
364
 
365
      *strp += 6;
366
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
367
                                   & result_type, & value);
368
      if (**strp != ')')
369
        return _("missing `)'");
370
      (*strp) ++;
371
 
372
      if (errmsg == NULL
373
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
374
        {
375
          value &= 0xffff;
376
        }
377
      *valuep = value;
378
      return errmsg;
379
    }
380
 
381
  if (strncasecmp (*strp, "%hi16(", 6) == 0)
382
    {
383
      enum cgen_parse_operand_result result_type;
384
      bfd_vma value;
385
      const char *errmsg;
386
 
387
      *strp += 6;
388
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
389
                                   & result_type, & value);
390
      if (**strp != ')')
391
        return _("missing `)'");
392
      (*strp) ++;
393
 
394
      if (errmsg == NULL
395
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
396
        {
397
          value >>= 16;
398
        }
399
      *valuep = value;
400
      return errmsg;
401
    }
402
 
403
  PARSE_SIGNED;
404
 
405
  if (value <= 65535 && value > 32767)
406
    value -= 0x10000;
407
 
408
  if (value < -32768 || value > 32767)
409
    return _("dsp:16 immediate is out of range");
410
 
411
  *valuep = value;
412
  return 0;
413
}
414
 
415
static const char *
416
parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
417
                 int opindex, unsigned long *valuep)
418
{
419
  const char *errmsg = 0;
420
  unsigned long value;
421
 
422
  /* Don't successfully parse literals beginning with '['.  */
423
  if (**strp == '[')
424
    return "Invalid literal"; /* Anything -- will not be seen.  */
425
 
426
  /* Don't successfully parse register names.  */
427
  if (m32c_cgen_isa_register (strp))
428
    return "Invalid literal"; /* Anything -- will not be seen.  */
429
 
430
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
431
  if (errmsg)
432
    return errmsg;
433
 
434
  if (value > 0xfffff)
435
    return _("dsp:20 immediate is out of range");
436
 
437
  *valuep = value;
438
  return 0;
439
}
440
 
441
static const char *
442
parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
443
                 int opindex, unsigned long *valuep)
444
{
445
  const char *errmsg = 0;
446
  unsigned long value;
447
 
448
  /* Don't successfully parse literals beginning with '['.  */
449
  if (**strp == '[')
450
    return "Invalid literal"; /* Anything -- will not be seen.  */
451
 
452
  /* Don't successfully parse register names.  */
453
  if (m32c_cgen_isa_register (strp))
454
    return "Invalid literal"; /* Anything -- will not be seen.  */
455
 
456
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
457
  if (errmsg)
458
    return errmsg;
459
 
460
  if (value > 0xffffff)
461
    return _("dsp:24 immediate is out of range");
462
 
463
  *valuep = value;
464
  return 0;
465
}
466
 
467
/* This should only be used for #imm->reg.  */
468
static const char *
469
parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
470
                 int opindex, signed long *valuep)
471
{
472
  const char *errmsg = 0;
473
  signed long value;
474
 
475
  PARSE_SIGNED;
476
 
477
  if (value <= 0xffffff && value > 0x7fffff)
478
    value -= 0x1000000;
479
 
480
  if (value > 0xffffff)
481
    return _("dsp:24 immediate is out of range");
482
 
483
  *valuep = value;
484
  return 0;
485
}
486
 
487
static const char *
488
parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
489
                int opindex, signed long *valuep)
490
{
491
  const char *errmsg = 0;
492
  signed long value;
493
 
494
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
495
  if (errmsg)
496
    return errmsg;
497
 
498
  *valuep = value;
499
  return 0;
500
}
501
 
502
static const char *
503
parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
504
             int opindex, signed long *valuep)
505
{
506
  const char *errmsg = 0;
507
  signed long value;
508
 
509
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
510
  if (errmsg)
511
    return errmsg;
512
 
513
  if (value < 1 || value > 2)
514
    return _("immediate is out of range 1-2");
515
 
516
  *valuep = value;
517
  return 0;
518
}
519
 
520
static const char *
521
parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
522
             int opindex, signed long *valuep)
523
{
524
  const char *errmsg = 0;
525
  signed long value;
526
 
527
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
528
  if (errmsg)
529
    return errmsg;
530
 
531
  if (value < 1 || value > 8)
532
    return _("immediate is out of range 1-8");
533
 
534
  *valuep = value;
535
  return 0;
536
}
537
 
538
static const char *
539
parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
540
             int opindex, signed long *valuep)
541
{
542
  const char *errmsg = 0;
543
  signed long value;
544
 
545
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
546
  if (errmsg)
547
    return errmsg;
548
 
549
  if (value < 0 || value > 7)
550
    return _("immediate is out of range 0-7");
551
 
552
  *valuep = value;
553
  return 0;
554
}
555
 
556
static const char *
557
parse_lab_5_3 (CGEN_CPU_DESC cd,
558
               const char **strp,
559
               int opindex ATTRIBUTE_UNUSED,
560
               int opinfo,
561
               enum cgen_parse_operand_result *type_addr,
562
               bfd_vma *valuep)
563
{
564
  const char *errmsg = 0;
565
  bfd_vma value;
566
  enum cgen_parse_operand_result op_res;
567
 
568
  errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
569
                               opinfo, & op_res, & value);
570
 
571
  if (type_addr)
572
    *type_addr = op_res;
573
 
574
  if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED)
575
    {
576
      /* This is a hack; the field cannot handle near-zero signed
577
         offsets that CGEN wants to put in to indicate an "empty"
578
         operand at first.  */
579
      *valuep = 2;
580
      return 0;
581
    }
582
  if (errmsg)
583
    return errmsg;
584
 
585
  if (value < 2 || value > 9)
586
    return _("immediate is out of range 2-9");
587
 
588
  *valuep = value;
589
  return 0;
590
}
591
 
592
static const char *
593
parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
594
                int opindex, unsigned long *valuep)
595
{
596
  const char *errmsg = 0;
597
  unsigned long value;
598
 
599
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
600
  if (errmsg)
601
    return errmsg;
602
 
603
  if (value > 15)
604
    return _("Bit number for indexing general register is out of range 0-15");
605
 
606
  *valuep = value;
607
  return 0;
608
}
609
 
610
static const char *
611
parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
612
                        int opindex, unsigned long *valuep,
613
                        unsigned bits, int allow_syms)
614
{
615
  const char *errmsg = 0;
616
  unsigned long bit;
617
  unsigned long base;
618
  const char *newp = *strp;
619
  unsigned long long bitbase;
620
  long have_zero = 0;
621
 
622
  errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
623
  if (errmsg)
624
    return errmsg;
625
 
626
  if (*newp != ',')
627
    return "Missing base for bit,base:8";
628
 
629
  ++newp;
630
 
631
  if (strncmp (newp, "0x0", 3) == 0
632
      || (newp[0] == '0' && newp[1] != 'x'))
633
    have_zero = 1;
634
 
635
  errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
636
  if (errmsg)
637
    return errmsg;
638
 
639
  bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
640
 
641
  if (bitbase >= (1ull << bits))
642
    return _("bit,base is out of range");
643
 
644
  /* If this field may require a relocation then use larger displacement.  */
645
  if (! have_zero && base == 0)
646
    {
647
      switch (allow_syms) {
648
      case 0:
649
        return _("bit,base out of range for symbol");
650
      case 1:
651
        break;
652
      case 2:
653
        if (strncmp (newp, "[sb]", 4) != 0)
654
          return _("bit,base out of range for symbol");
655
        break;
656
      }
657
    }
658
 
659
  *valuep = bitbase;
660
  *strp = newp;
661
  return 0;
662
}
663
 
664
static const char *
665
parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
666
                      int opindex, signed long *valuep,
667
                      unsigned bits, int allow_syms)
668
{
669
  const char *errmsg = 0;
670
  unsigned long bit;
671
  signed long base;
672
  const char *newp = *strp;
673
  long long bitbase;
674
  long long limit;
675
  long have_zero = 0;
676
 
677
  errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
678
  if (errmsg)
679
    return errmsg;
680
 
681
  if (*newp != ',')
682
    return "Missing base for bit,base:8";
683
 
684
  ++newp;
685
 
686
  if (strncmp (newp, "0x0", 3) == 0
687
      || (newp[0] == '0' && newp[1] != 'x'))
688
    have_zero = 1;
689
 
690
  errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
691
  if (errmsg)
692
    return errmsg;
693
 
694
  bitbase = (long long)bit + ((long long)base * 8);
695
 
696
  limit = 1ll << (bits - 1);
697
  if (bitbase < -limit || bitbase >= limit)
698
    return _("bit,base is out of range");
699
 
700
  /* If this field may require a relocation then use larger displacement.  */
701
  if (! have_zero && base == 0 && ! allow_syms)
702
    return _("bit,base out of range for symbol");
703
 
704
  *valuep = bitbase;
705
  *strp = newp;
706
  return 0;
707
}
708
 
709
static const char *
710
parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
711
                         int opindex, unsigned long *valuep)
712
{
713
  return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
714
}
715
 
716
static const char *
717
parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
718
                         int opindex, unsigned long *valuep)
719
{
720
  return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
721
}
722
 
723
static const char *
724
parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
725
                          int opindex, unsigned long *valuep)
726
{
727
  return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
728
}
729
 
730
static const char *
731
parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
732
                         int opindex, unsigned long *valuep)
733
{
734
  return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
735
}
736
 
737
static const char *
738
parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
739
                         int opindex, unsigned long *valuep)
740
{
741
  return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
742
}
743
 
744
static const char *
745
parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
746
                       int opindex, signed long *valuep)
747
{
748
  return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
749
}
750
 
751
static const char *
752
parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
753
                       int opindex, signed long *valuep)
754
{
755
  return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
756
}
757
 
758
static const char *
759
parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
760
                       int opindex, signed long *valuep)
761
{
762
  return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
763
}
764
 
765
/* Parse the suffix as : or as nothing followed by a whitespace.  */
766
 
767
static const char *
768
parse_suffix (const char **strp, char suffix)
769
{
770
  const char *newp = *strp;
771
 
772
  if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
773
    newp = *strp + 2;
774
 
775
  if (ISSPACE (*newp))
776
    {
777
      *strp = newp;
778
      return 0;
779
    }
780
 
781
  return "Invalid suffix"; /* Anything -- will not be seen.  */
782
}
783
 
784
static const char *
785
parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
786
         int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
787
{
788
  return parse_suffix (strp, 's');
789
}
790
 
791
static const char *
792
parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
793
         int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
794
{
795
  return parse_suffix (strp, 'g');
796
}
797
 
798
static const char *
799
parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
800
         int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
801
{
802
  return parse_suffix (strp, 'q');
803
}
804
 
805
static const char *
806
parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
807
         int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
808
{
809
  return parse_suffix (strp, 'z');
810
}
811
 
812
/* Parse an empty suffix. Fail if the next char is ':'.  */
813
 
814
static const char *
815
parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
816
         int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
817
{
818
  if (**strp == ':')
819
    return "Unexpected suffix";
820
  return 0;
821
}
822
 
823
static const char *
824
parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
825
               int opindex ATTRIBUTE_UNUSED, signed long *valuep)
826
{
827
  const char *errmsg;
828
  signed long value;
829
  signed long junk;
830
  const char *newp = *strp;
831
 
832
  /* Parse r0[hl].  */
833
  errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
834
  if (errmsg)
835
    return errmsg;
836
 
837
  if (*newp != ',')
838
    return _("not a valid r0l/r0h pair");
839
  ++newp;
840
 
841
  /* Parse the second register in the pair.  */
842
  if (value == 0) /* r0l */
843
    errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
844
  else
845
    errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
846
  if (errmsg)
847
    return errmsg;
848
 
849
  *strp = newp;
850
  *valuep = ! value;
851
  return 0;
852
}
853
 
854
/* Accept .b or .w in any case.  */
855
 
856
static const char *
857
parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
858
            int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
859
{
860
  if (**strp == '.'
861
      && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
862
          || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
863
    {
864
      *strp += 2;
865
      return NULL;
866
    }
867
 
868
  return _("Invalid size specifier");
869
}
870
 
871
/* Special check to ensure that instruction exists for given machine.  */
872
 
873
int
874
m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
875
                          const CGEN_INSN *insn)
876
{
877
  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
878
  CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
879
 
880
  /* If attributes are absent, assume no restriction.  */
881
  if (machs == 0)
882
    machs = ~0;
883
 
884
  return ((machs & cd->machs)
885
          && cgen_bitset_intersect_p (& isas, cd->isas));
886
}
887
 
888
/* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
889
 
890
static const char *
891
parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
892
              const char **strp,
893
              int opindex ATTRIBUTE_UNUSED,
894
              unsigned long *valuep,
895
              int push)
896
{
897
  const char *errmsg = 0;
898
  int regno = 0;
899
 
900
  *valuep = 0;
901
  while (**strp && **strp != ')')
902
    {
903
      if (**strp == 'r' || **strp == 'R')
904
        {
905
          ++*strp;
906
          regno = **strp - '0';
907
          if (regno > 4)
908
            errmsg = _("Register number is not valid");
909
        }
910
      else if (**strp == 'a' || **strp == 'A')
911
        {
912
          ++*strp;
913
          regno = **strp - '0';
914
          if (regno > 2)
915
            errmsg = _("Register number is not valid");
916
          regno = **strp - '0' + 4;
917
        }
918
 
919
      else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
920
        {
921
          regno = 6;
922
          ++*strp;
923
        }
924
 
925
      else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
926
        {
927
          regno = 7;
928
          ++*strp;
929
        }
930
 
931
      if (push) /* Mask is reversed for push.  */
932
        *valuep |= 0x80 >> regno;
933
      else
934
        *valuep |= 1 << regno;
935
 
936
      ++*strp;
937
      if (**strp == ',')
938
        {
939
          if (*(*strp + 1) == ')')
940
            break;
941
          ++*strp;
942
        }
943
    }
944
 
945
  if (!*strp)
946
    errmsg = _("Register list is not valid");
947
 
948
  return errmsg;
949
}
950
 
951
#define POP  0
952
#define PUSH 1
953
 
954
static const char *
955
parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
956
                  const char **strp,
957
                  int opindex ATTRIBUTE_UNUSED,
958
                  unsigned long *valuep)
959
{
960
  return parse_regset (cd, strp, opindex, valuep, POP);
961
}
962
 
963
static const char *
964
parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
965
                   const char **strp,
966
                   int opindex ATTRIBUTE_UNUSED,
967
                   unsigned long *valuep)
968
{
969
  return parse_regset (cd, strp, opindex, valuep, PUSH);
970
}
971
 
972
/* -- dis.c */
973
 
974
#include "elf/m32c.h"
975
#include "elf-bfd.h"
976
 
977
/* Always print the short insn format suffix as ':'.  */
978
 
979
static void
980
print_suffix (void * dis_info, char suffix)
981
{
982
  disassemble_info *info = dis_info;
983
 
984
  (*info->fprintf_func) (info->stream, ":%c", suffix);
985
}
986
 
987
static void
988
print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
989
         void * dis_info,
990
         long value ATTRIBUTE_UNUSED,
991
         unsigned int attrs ATTRIBUTE_UNUSED,
992
         bfd_vma pc ATTRIBUTE_UNUSED,
993
         int length ATTRIBUTE_UNUSED)
994
{
995
  print_suffix (dis_info, 's');
996
}
997
 
998
 
999
static void
1000
print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1001
         void * dis_info,
1002
         long value ATTRIBUTE_UNUSED,
1003
         unsigned int attrs ATTRIBUTE_UNUSED,
1004
         bfd_vma pc ATTRIBUTE_UNUSED,
1005
         int length ATTRIBUTE_UNUSED)
1006
{
1007
  print_suffix (dis_info, 'g');
1008
}
1009
 
1010
static void
1011
print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1012
         void * dis_info,
1013
         long value ATTRIBUTE_UNUSED,
1014
         unsigned int attrs ATTRIBUTE_UNUSED,
1015
         bfd_vma pc ATTRIBUTE_UNUSED,
1016
         int length ATTRIBUTE_UNUSED)
1017
{
1018
  print_suffix (dis_info, 'q');
1019
}
1020
 
1021
static void
1022
print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1023
         void * dis_info,
1024
         long value ATTRIBUTE_UNUSED,
1025
         unsigned int attrs ATTRIBUTE_UNUSED,
1026
         bfd_vma pc ATTRIBUTE_UNUSED,
1027
         int length ATTRIBUTE_UNUSED)
1028
{
1029
  print_suffix (dis_info, 'z');
1030
}
1031
 
1032
/* Print the empty suffix.  */
1033
 
1034
static void
1035
print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1036
         void * dis_info ATTRIBUTE_UNUSED,
1037
         long value ATTRIBUTE_UNUSED,
1038
         unsigned int attrs ATTRIBUTE_UNUSED,
1039
         bfd_vma pc ATTRIBUTE_UNUSED,
1040
         int length ATTRIBUTE_UNUSED)
1041
{
1042
  return;
1043
}
1044
 
1045
static void
1046
print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1047
               void * dis_info,
1048
               long value,
1049
               unsigned int attrs ATTRIBUTE_UNUSED,
1050
               bfd_vma pc ATTRIBUTE_UNUSED,
1051
               int length ATTRIBUTE_UNUSED)
1052
{
1053
  disassemble_info *info = dis_info;
1054
 
1055
  if (value == 0)
1056
    (*info->fprintf_func) (info->stream, "r0h,r0l");
1057
  else
1058
    (*info->fprintf_func) (info->stream, "r0l,r0h");
1059
}
1060
 
1061
static void
1062
print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1063
                        void * dis_info,
1064
                        unsigned long value,
1065
                        unsigned int attrs ATTRIBUTE_UNUSED,
1066
                        bfd_vma pc ATTRIBUTE_UNUSED,
1067
                        int length ATTRIBUTE_UNUSED)
1068
{
1069
  disassemble_info *info = dis_info;
1070
 
1071
  (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1072
}
1073
 
1074
static void
1075
print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1076
                      void * dis_info,
1077
                      signed long value,
1078
                      unsigned int attrs ATTRIBUTE_UNUSED,
1079
                      bfd_vma pc ATTRIBUTE_UNUSED,
1080
                      int length ATTRIBUTE_UNUSED)
1081
{
1082
  disassemble_info *info = dis_info;
1083
 
1084
  (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1085
}
1086
 
1087
static void
1088
print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1089
            void * dis_info,
1090
            long value ATTRIBUTE_UNUSED,
1091
            unsigned int attrs ATTRIBUTE_UNUSED,
1092
            bfd_vma pc ATTRIBUTE_UNUSED,
1093
            int length ATTRIBUTE_UNUSED)
1094
{
1095
  /* Always print the size as '.w'.  */
1096
  disassemble_info *info = dis_info;
1097
 
1098
  (*info->fprintf_func) (info->stream, ".w");
1099
}
1100
 
1101
#define POP  0
1102
#define PUSH 1
1103
 
1104
static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1105
static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1106
 
1107
/* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1108
 
1109
static void
1110
print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1111
              void * dis_info,
1112
              long value,
1113
              unsigned int attrs ATTRIBUTE_UNUSED,
1114
              bfd_vma pc ATTRIBUTE_UNUSED,
1115
              int length ATTRIBUTE_UNUSED,
1116
              int push)
1117
{
1118
  static char * m16c_register_names [] =
1119
  {
1120
    "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1121
  };
1122
  disassemble_info *info = dis_info;
1123
  int mask;
1124
  int index = 0;
1125
  char* comma = "";
1126
 
1127
  if (push)
1128
    mask = 0x80;
1129
  else
1130
    mask = 1;
1131
 
1132
  if (value & mask)
1133
    {
1134
      (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1135
      comma = ",";
1136
    }
1137
 
1138
  for (index = 1; index <= 7; ++index)
1139
    {
1140
      if (push)
1141
        mask >>= 1;
1142
      else
1143
        mask <<= 1;
1144
 
1145
      if (value & mask)
1146
        {
1147
          (*info->fprintf_func) (info->stream, "%s%s", comma,
1148
                                 m16c_register_names [index]);
1149
          comma = ",";
1150
        }
1151
    }
1152
}
1153
 
1154
static void
1155
print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1156
                  void * dis_info,
1157
                  long value,
1158
                  unsigned int attrs ATTRIBUTE_UNUSED,
1159
                  bfd_vma pc ATTRIBUTE_UNUSED,
1160
                  int length ATTRIBUTE_UNUSED)
1161
{
1162
  print_regset (cd, dis_info, value, attrs, pc, length, POP);
1163
}
1164
 
1165
static void
1166
print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1167
                   void * dis_info,
1168
                   long value,
1169
                   unsigned int attrs ATTRIBUTE_UNUSED,
1170
                   bfd_vma pc ATTRIBUTE_UNUSED,
1171
                   int length ATTRIBUTE_UNUSED)
1172
{
1173
  print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1174
}
1175
 
1176
static void
1177
print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1178
                void * dis_info,
1179
                signed long value,
1180
                unsigned int attrs ATTRIBUTE_UNUSED,
1181
                bfd_vma pc ATTRIBUTE_UNUSED,
1182
                int length ATTRIBUTE_UNUSED)
1183
{
1184
  disassemble_info *info = dis_info;
1185
 
1186
  (*info->fprintf_func) (info->stream, "%ld", -value);
1187
}

powered by: WebSVN 2.1.0

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