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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [cpu/] [m32c.opc] - Blame information for rev 165

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

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

powered by: WebSVN 2.1.0

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