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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [ip2k-ibld.c] - Blame information for rev 856

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

Line No. Rev Author Line
1 38 julius
/* Instruction building/extraction support for ip2k. -*- C -*-
2
 
3
   THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4
   - the resultant file is machine generated, cgen-ibld.in isn't
5
 
6
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2006, 2007
7
   Free Software Foundation, Inc.
8
 
9
   This file is part of libopcodes.
10
 
11
   This library is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3, or (at your option)
14
   any later version.
15
 
16
   It is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19
   License for more details.
20
 
21
   You should have received a copy of the GNU General Public License
22
   along with this program; if not, write to the Free Software Foundation, Inc.,
23
   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
24
 
25
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26
   Keep that in mind.  */
27
 
28
#include "sysdep.h"
29
#include <stdio.h>
30
#include "ansidecl.h"
31
#include "dis-asm.h"
32
#include "bfd.h"
33
#include "symcat.h"
34
#include "ip2k-desc.h"
35
#include "ip2k-opc.h"
36
#include "opintl.h"
37
#include "safe-ctype.h"
38
 
39
#undef  min
40
#define min(a,b) ((a) < (b) ? (a) : (b))
41
#undef  max
42
#define max(a,b) ((a) > (b) ? (a) : (b))
43
 
44
/* Used by the ifield rtx function.  */
45
#define FLD(f) (fields->f)
46
 
47
static const char * insert_normal
48
  (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
49
   unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
50
static const char * insert_insn_normal
51
  (CGEN_CPU_DESC, const CGEN_INSN *,
52
   CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
53
static int extract_normal
54
  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
55
   unsigned int, unsigned int, unsigned int, unsigned int,
56
   unsigned int, unsigned int, bfd_vma, long *);
57
static int extract_insn_normal
58
  (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59
   CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
60
#if CGEN_INT_INSN_P
61
static void put_insn_int_value
62
  (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
63
#endif
64
#if ! CGEN_INT_INSN_P
65
static CGEN_INLINE void insert_1
66
  (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
67
static CGEN_INLINE int fill_cache
68
  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma);
69
static CGEN_INLINE long extract_1
70
  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
71
#endif
72
 
73
/* Operand insertion.  */
74
 
75
#if ! CGEN_INT_INSN_P
76
 
77
/* Subroutine of insert_normal.  */
78
 
79
static CGEN_INLINE void
80
insert_1 (CGEN_CPU_DESC cd,
81
          unsigned long value,
82
          int start,
83
          int length,
84
          int word_length,
85
          unsigned char *bufp)
86
{
87
  unsigned long x,mask;
88
  int shift;
89
 
90
  x = cgen_get_insn_value (cd, bufp, word_length);
91
 
92
  /* Written this way to avoid undefined behaviour.  */
93
  mask = (((1L << (length - 1)) - 1) << 1) | 1;
94
  if (CGEN_INSN_LSB0_P)
95
    shift = (start + 1) - length;
96
  else
97
    shift = (word_length - (start + length));
98
  x = (x & ~(mask << shift)) | ((value & mask) << shift);
99
 
100
  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
101
}
102
 
103
#endif /* ! CGEN_INT_INSN_P */
104
 
105
/* Default insertion routine.
106
 
107
   ATTRS is a mask of the boolean attributes.
108
   WORD_OFFSET is the offset in bits from the start of the insn of the value.
109
   WORD_LENGTH is the length of the word in bits in which the value resides.
110
   START is the starting bit number in the word, architecture origin.
111
   LENGTH is the length of VALUE in bits.
112
   TOTAL_LENGTH is the total length of the insn in bits.
113
 
114
   The result is an error message or NULL if success.  */
115
 
116
/* ??? This duplicates functionality with bfd's howto table and
117
   bfd_install_relocation.  */
118
/* ??? This doesn't handle bfd_vma's.  Create another function when
119
   necessary.  */
120
 
121
static const char *
122
insert_normal (CGEN_CPU_DESC cd,
123
               long value,
124
               unsigned int attrs,
125
               unsigned int word_offset,
126
               unsigned int start,
127
               unsigned int length,
128
               unsigned int word_length,
129
               unsigned int total_length,
130
               CGEN_INSN_BYTES_PTR buffer)
131
{
132
  static char errbuf[100];
133
  /* Written this way to avoid undefined behaviour.  */
134
  unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
135
 
136
  /* If LENGTH is zero, this operand doesn't contribute to the value.  */
137
  if (length == 0)
138
    return NULL;
139
 
140
  if (word_length > 32)
141
    abort ();
142
 
143
  /* For architectures with insns smaller than the base-insn-bitsize,
144
     word_length may be too big.  */
145
  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
146
    {
147
      if (word_offset == 0
148
          && word_length > total_length)
149
        word_length = total_length;
150
    }
151
 
152
  /* Ensure VALUE will fit.  */
153
  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
154
    {
155
      long minval = - (1L << (length - 1));
156
      unsigned long maxval = mask;
157
 
158
      if ((value > 0 && (unsigned long) value > maxval)
159
          || value < minval)
160
        {
161
          /* xgettext:c-format */
162
          sprintf (errbuf,
163
                   _("operand out of range (%ld not between %ld and %lu)"),
164
                   value, minval, maxval);
165
          return errbuf;
166
        }
167
    }
168
  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
169
    {
170
      unsigned long maxval = mask;
171
      unsigned long val = (unsigned long) value;
172
 
173
      /* For hosts with a word size > 32 check to see if value has been sign
174
         extended beyond 32 bits.  If so then ignore these higher sign bits
175
         as the user is attempting to store a 32-bit signed value into an
176
         unsigned 32-bit field which is allowed.  */
177
      if (sizeof (unsigned long) > 4 && ((value >> 32) == -1))
178
        val &= 0xFFFFFFFF;
179
 
180
      if (val > maxval)
181
        {
182
          /* xgettext:c-format */
183
          sprintf (errbuf,
184
                   _("operand out of range (0x%lx not between 0 and 0x%lx)"),
185
                   val, maxval);
186
          return errbuf;
187
        }
188
    }
189
  else
190
    {
191
      if (! cgen_signed_overflow_ok_p (cd))
192
        {
193
          long minval = - (1L << (length - 1));
194
          long maxval =   (1L << (length - 1)) - 1;
195
 
196
          if (value < minval || value > maxval)
197
            {
198
              sprintf
199
                /* xgettext:c-format */
200
                (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
201
                 value, minval, maxval);
202
              return errbuf;
203
            }
204
        }
205
    }
206
 
207
#if CGEN_INT_INSN_P
208
 
209
  {
210
    int shift;
211
 
212
    if (CGEN_INSN_LSB0_P)
213
      shift = (word_offset + start + 1) - length;
214
    else
215
      shift = total_length - (word_offset + start + length);
216
    *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
217
  }
218
 
219
#else /* ! CGEN_INT_INSN_P */
220
 
221
  {
222
    unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
223
 
224
    insert_1 (cd, value, start, length, word_length, bufp);
225
  }
226
 
227
#endif /* ! CGEN_INT_INSN_P */
228
 
229
  return NULL;
230
}
231
 
232
/* Default insn builder (insert handler).
233
   The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
234
   that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
235
   recorded in host byte order, otherwise BUFFER is an array of bytes
236
   and the value is recorded in target byte order).
237
   The result is an error message or NULL if success.  */
238
 
239
static const char *
240
insert_insn_normal (CGEN_CPU_DESC cd,
241
                    const CGEN_INSN * insn,
242
                    CGEN_FIELDS * fields,
243
                    CGEN_INSN_BYTES_PTR buffer,
244
                    bfd_vma pc)
245
{
246
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
247
  unsigned long value;
248
  const CGEN_SYNTAX_CHAR_TYPE * syn;
249
 
250
  CGEN_INIT_INSERT (cd);
251
  value = CGEN_INSN_BASE_VALUE (insn);
252
 
253
  /* If we're recording insns as numbers (rather than a string of bytes),
254
     target byte order handling is deferred until later.  */
255
 
256
#if CGEN_INT_INSN_P
257
 
258
  put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
259
                      CGEN_FIELDS_BITSIZE (fields), value);
260
 
261
#else
262
 
263
  cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
264
                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
265
                       value);
266
 
267
#endif /* ! CGEN_INT_INSN_P */
268
 
269
  /* ??? It would be better to scan the format's fields.
270
     Still need to be able to insert a value based on the operand though;
271
     e.g. storing a branch displacement that got resolved later.
272
     Needs more thought first.  */
273
 
274
  for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
275
    {
276
      const char *errmsg;
277
 
278
      if (CGEN_SYNTAX_CHAR_P (* syn))
279
        continue;
280
 
281
      errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
282
                                       fields, buffer, pc);
283
      if (errmsg)
284
        return errmsg;
285
    }
286
 
287
  return NULL;
288
}
289
 
290
#if CGEN_INT_INSN_P
291
/* Cover function to store an insn value into an integral insn.  Must go here
292
   because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
293
 
294
static void
295
put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
296
                    CGEN_INSN_BYTES_PTR buf,
297
                    int length,
298
                    int insn_length,
299
                    CGEN_INSN_INT value)
300
{
301
  /* For architectures with insns smaller than the base-insn-bitsize,
302
     length may be too big.  */
303
  if (length > insn_length)
304
    *buf = value;
305
  else
306
    {
307
      int shift = insn_length - length;
308
      /* Written this way to avoid undefined behaviour.  */
309
      CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
310
 
311
      *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
312
    }
313
}
314
#endif
315
 
316
/* Operand extraction.  */
317
 
318
#if ! CGEN_INT_INSN_P
319
 
320
/* Subroutine of extract_normal.
321
   Ensure sufficient bytes are cached in EX_INFO.
322
   OFFSET is the offset in bytes from the start of the insn of the value.
323
   BYTES is the length of the needed value.
324
   Returns 1 for success, 0 for failure.  */
325
 
326
static CGEN_INLINE int
327
fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
328
            CGEN_EXTRACT_INFO *ex_info,
329
            int offset,
330
            int bytes,
331
            bfd_vma pc)
332
{
333
  /* It's doubtful that the middle part has already been fetched so
334
     we don't optimize that case.  kiss.  */
335
  unsigned int mask;
336
  disassemble_info *info = (disassemble_info *) ex_info->dis_info;
337
 
338
  /* First do a quick check.  */
339
  mask = (1 << bytes) - 1;
340
  if (((ex_info->valid >> offset) & mask) == mask)
341
    return 1;
342
 
343
  /* Search for the first byte we need to read.  */
344
  for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
345
    if (! (mask & ex_info->valid))
346
      break;
347
 
348
  if (bytes)
349
    {
350
      int status;
351
 
352
      pc += offset;
353
      status = (*info->read_memory_func)
354
        (pc, ex_info->insn_bytes + offset, bytes, info);
355
 
356
      if (status != 0)
357
        {
358
          (*info->memory_error_func) (status, pc, info);
359
          return 0;
360
        }
361
 
362
      ex_info->valid |= ((1 << bytes) - 1) << offset;
363
    }
364
 
365
  return 1;
366
}
367
 
368
/* Subroutine of extract_normal.  */
369
 
370
static CGEN_INLINE long
371
extract_1 (CGEN_CPU_DESC cd,
372
           CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
373
           int start,
374
           int length,
375
           int word_length,
376
           unsigned char *bufp,
377
           bfd_vma pc ATTRIBUTE_UNUSED)
378
{
379
  unsigned long x;
380
  int shift;
381
 
382
  x = cgen_get_insn_value (cd, bufp, word_length);
383
 
384
  if (CGEN_INSN_LSB0_P)
385
    shift = (start + 1) - length;
386
  else
387
    shift = (word_length - (start + length));
388
  return x >> shift;
389
}
390
 
391
#endif /* ! CGEN_INT_INSN_P */
392
 
393
/* Default extraction routine.
394
 
395
   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
396
   or sometimes less for cases like the m32r where the base insn size is 32
397
   but some insns are 16 bits.
398
   ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
399
   but for generality we take a bitmask of all of them.
400
   WORD_OFFSET is the offset in bits from the start of the insn of the value.
401
   WORD_LENGTH is the length of the word in bits in which the value resides.
402
   START is the starting bit number in the word, architecture origin.
403
   LENGTH is the length of VALUE in bits.
404
   TOTAL_LENGTH is the total length of the insn in bits.
405
 
406
   Returns 1 for success, 0 for failure.  */
407
 
408
/* ??? The return code isn't properly used.  wip.  */
409
 
410
/* ??? This doesn't handle bfd_vma's.  Create another function when
411
   necessary.  */
412
 
413
static int
414
extract_normal (CGEN_CPU_DESC cd,
415
#if ! CGEN_INT_INSN_P
416
                CGEN_EXTRACT_INFO *ex_info,
417
#else
418
                CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
419
#endif
420
                CGEN_INSN_INT insn_value,
421
                unsigned int attrs,
422
                unsigned int word_offset,
423
                unsigned int start,
424
                unsigned int length,
425
                unsigned int word_length,
426
                unsigned int total_length,
427
#if ! CGEN_INT_INSN_P
428
                bfd_vma pc,
429
#else
430
                bfd_vma pc ATTRIBUTE_UNUSED,
431
#endif
432
                long *valuep)
433
{
434
  long value, mask;
435
 
436
  /* If LENGTH is zero, this operand doesn't contribute to the value
437
     so give it a standard value of zero.  */
438
  if (length == 0)
439
    {
440
      *valuep = 0;
441
      return 1;
442
    }
443
 
444
  if (word_length > 32)
445
    abort ();
446
 
447
  /* For architectures with insns smaller than the insn-base-bitsize,
448
     word_length may be too big.  */
449
  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
450
    {
451
      if (word_offset + word_length > total_length)
452
        word_length = total_length - word_offset;
453
    }
454
 
455
  /* Does the value reside in INSN_VALUE, and at the right alignment?  */
456
 
457
  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
458
    {
459
      if (CGEN_INSN_LSB0_P)
460
        value = insn_value >> ((word_offset + start + 1) - length);
461
      else
462
        value = insn_value >> (total_length - ( word_offset + start + length));
463
    }
464
 
465
#if ! CGEN_INT_INSN_P
466
 
467
  else
468
    {
469
      unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
470
 
471
      if (word_length > 32)
472
        abort ();
473
 
474
      if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
475
        return 0;
476
 
477
      value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
478
    }
479
 
480
#endif /* ! CGEN_INT_INSN_P */
481
 
482
  /* Written this way to avoid undefined behaviour.  */
483
  mask = (((1L << (length - 1)) - 1) << 1) | 1;
484
 
485
  value &= mask;
486
  /* sign extend? */
487
  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
488
      && (value & (1L << (length - 1))))
489
    value |= ~mask;
490
 
491
  *valuep = value;
492
 
493
  return 1;
494
}
495
 
496
/* Default insn extractor.
497
 
498
   INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
499
   The extracted fields are stored in FIELDS.
500
   EX_INFO is used to handle reading variable length insns.
501
   Return the length of the insn in bits, or 0 if no match,
502
   or -1 if an error occurs fetching data (memory_error_func will have
503
   been called).  */
504
 
505
static int
506
extract_insn_normal (CGEN_CPU_DESC cd,
507
                     const CGEN_INSN *insn,
508
                     CGEN_EXTRACT_INFO *ex_info,
509
                     CGEN_INSN_INT insn_value,
510
                     CGEN_FIELDS *fields,
511
                     bfd_vma pc)
512
{
513
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
514
  const CGEN_SYNTAX_CHAR_TYPE *syn;
515
 
516
  CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
517
 
518
  CGEN_INIT_EXTRACT (cd);
519
 
520
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
521
    {
522
      int length;
523
 
524
      if (CGEN_SYNTAX_CHAR_P (*syn))
525
        continue;
526
 
527
      length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
528
                                        ex_info, insn_value, fields, pc);
529
      if (length <= 0)
530
        return length;
531
    }
532
 
533
  /* We recognized and successfully extracted this insn.  */
534
  return CGEN_INSN_BITSIZE (insn);
535
}
536
 
537
/* Machine generated code added here.  */
538
 
539
const char * ip2k_cgen_insert_operand
540
  (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
541
 
542
/* Main entry point for operand insertion.
543
 
544
   This function is basically just a big switch statement.  Earlier versions
545
   used tables to look up the function to use, but
546
   - if the table contains both assembler and disassembler functions then
547
     the disassembler contains much of the assembler and vice-versa,
548
   - there's a lot of inlining possibilities as things grow,
549
   - using a switch statement avoids the function call overhead.
550
 
551
   This function could be moved into `parse_insn_normal', but keeping it
552
   separate makes clear the interface between `parse_insn_normal' and each of
553
   the handlers.  It's also needed by GAS to insert operands that couldn't be
554
   resolved during parsing.  */
555
 
556
const char *
557
ip2k_cgen_insert_operand (CGEN_CPU_DESC cd,
558
                             int opindex,
559
                             CGEN_FIELDS * fields,
560
                             CGEN_INSN_BYTES_PTR buffer,
561
                             bfd_vma pc ATTRIBUTE_UNUSED)
562
{
563
  const char * errmsg = NULL;
564
  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
565
 
566
  switch (opindex)
567
    {
568
    case IP2K_OPERAND_ADDR16CJP :
569
      errmsg = insert_normal (cd, fields->f_addr16cjp, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, buffer);
570
      break;
571
    case IP2K_OPERAND_ADDR16H :
572
      errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
573
      break;
574
    case IP2K_OPERAND_ADDR16L :
575
      errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
576
      break;
577
    case IP2K_OPERAND_ADDR16P :
578
      errmsg = insert_normal (cd, fields->f_page3, 0, 0, 2, 3, 16, total_length, buffer);
579
      break;
580
    case IP2K_OPERAND_BITNO :
581
      errmsg = insert_normal (cd, fields->f_bitno, 0, 0, 11, 3, 16, total_length, buffer);
582
      break;
583
    case IP2K_OPERAND_CBIT :
584
      break;
585
    case IP2K_OPERAND_DCBIT :
586
      break;
587
    case IP2K_OPERAND_FR :
588
      errmsg = insert_normal (cd, fields->f_reg, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, buffer);
589
      break;
590
    case IP2K_OPERAND_LIT8 :
591
      errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
592
      break;
593
    case IP2K_OPERAND_PABITS :
594
      break;
595
    case IP2K_OPERAND_RETI3 :
596
      errmsg = insert_normal (cd, fields->f_reti3, 0, 0, 2, 3, 16, total_length, buffer);
597
      break;
598
    case IP2K_OPERAND_ZBIT :
599
      break;
600
 
601
    default :
602
      /* xgettext:c-format */
603
      fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
604
               opindex);
605
      abort ();
606
  }
607
 
608
  return errmsg;
609
}
610
 
611
int ip2k_cgen_extract_operand
612
  (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
613
 
614
/* Main entry point for operand extraction.
615
   The result is <= 0 for error, >0 for success.
616
   ??? Actual values aren't well defined right now.
617
 
618
   This function is basically just a big switch statement.  Earlier versions
619
   used tables to look up the function to use, but
620
   - if the table contains both assembler and disassembler functions then
621
     the disassembler contains much of the assembler and vice-versa,
622
   - there's a lot of inlining possibilities as things grow,
623
   - using a switch statement avoids the function call overhead.
624
 
625
   This function could be moved into `print_insn_normal', but keeping it
626
   separate makes clear the interface between `print_insn_normal' and each of
627
   the handlers.  */
628
 
629
int
630
ip2k_cgen_extract_operand (CGEN_CPU_DESC cd,
631
                             int opindex,
632
                             CGEN_EXTRACT_INFO *ex_info,
633
                             CGEN_INSN_INT insn_value,
634
                             CGEN_FIELDS * fields,
635
                             bfd_vma pc)
636
{
637
  /* Assume success (for those operands that are nops).  */
638
  int length = 1;
639
  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
640
 
641
  switch (opindex)
642
    {
643
    case IP2K_OPERAND_ADDR16CJP :
644
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, pc, & fields->f_addr16cjp);
645
      break;
646
    case IP2K_OPERAND_ADDR16H :
647
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
648
      break;
649
    case IP2K_OPERAND_ADDR16L :
650
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
651
      break;
652
    case IP2K_OPERAND_ADDR16P :
653
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_page3);
654
      break;
655
    case IP2K_OPERAND_BITNO :
656
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 3, 16, total_length, pc, & fields->f_bitno);
657
      break;
658
    case IP2K_OPERAND_CBIT :
659
      break;
660
    case IP2K_OPERAND_DCBIT :
661
      break;
662
    case IP2K_OPERAND_FR :
663
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, pc, & fields->f_reg);
664
      break;
665
    case IP2K_OPERAND_LIT8 :
666
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
667
      break;
668
    case IP2K_OPERAND_PABITS :
669
      break;
670
    case IP2K_OPERAND_RETI3 :
671
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_reti3);
672
      break;
673
    case IP2K_OPERAND_ZBIT :
674
      break;
675
 
676
    default :
677
      /* xgettext:c-format */
678
      fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
679
               opindex);
680
      abort ();
681
    }
682
 
683
  return length;
684
}
685
 
686
cgen_insert_fn * const ip2k_cgen_insert_handlers[] =
687
{
688
  insert_insn_normal,
689
};
690
 
691
cgen_extract_fn * const ip2k_cgen_extract_handlers[] =
692
{
693
  extract_insn_normal,
694
};
695
 
696
int ip2k_cgen_get_int_operand     (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
697
bfd_vma ip2k_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
698
 
699
/* Getting values from cgen_fields is handled by a collection of functions.
700
   They are distinguished by the type of the VALUE argument they return.
701
   TODO: floating point, inlining support, remove cases where result type
702
   not appropriate.  */
703
 
704
int
705
ip2k_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
706
                             int opindex,
707
                             const CGEN_FIELDS * fields)
708
{
709
  int value;
710
 
711
  switch (opindex)
712
    {
713
    case IP2K_OPERAND_ADDR16CJP :
714
      value = fields->f_addr16cjp;
715
      break;
716
    case IP2K_OPERAND_ADDR16H :
717
      value = fields->f_imm8;
718
      break;
719
    case IP2K_OPERAND_ADDR16L :
720
      value = fields->f_imm8;
721
      break;
722
    case IP2K_OPERAND_ADDR16P :
723
      value = fields->f_page3;
724
      break;
725
    case IP2K_OPERAND_BITNO :
726
      value = fields->f_bitno;
727
      break;
728
    case IP2K_OPERAND_CBIT :
729
      value = 0;
730
      break;
731
    case IP2K_OPERAND_DCBIT :
732
      value = 0;
733
      break;
734
    case IP2K_OPERAND_FR :
735
      value = fields->f_reg;
736
      break;
737
    case IP2K_OPERAND_LIT8 :
738
      value = fields->f_imm8;
739
      break;
740
    case IP2K_OPERAND_PABITS :
741
      value = 0;
742
      break;
743
    case IP2K_OPERAND_RETI3 :
744
      value = fields->f_reti3;
745
      break;
746
    case IP2K_OPERAND_ZBIT :
747
      value = 0;
748
      break;
749
 
750
    default :
751
      /* xgettext:c-format */
752
      fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
753
                       opindex);
754
      abort ();
755
  }
756
 
757
  return value;
758
}
759
 
760
bfd_vma
761
ip2k_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
762
                             int opindex,
763
                             const CGEN_FIELDS * fields)
764
{
765
  bfd_vma value;
766
 
767
  switch (opindex)
768
    {
769
    case IP2K_OPERAND_ADDR16CJP :
770
      value = fields->f_addr16cjp;
771
      break;
772
    case IP2K_OPERAND_ADDR16H :
773
      value = fields->f_imm8;
774
      break;
775
    case IP2K_OPERAND_ADDR16L :
776
      value = fields->f_imm8;
777
      break;
778
    case IP2K_OPERAND_ADDR16P :
779
      value = fields->f_page3;
780
      break;
781
    case IP2K_OPERAND_BITNO :
782
      value = fields->f_bitno;
783
      break;
784
    case IP2K_OPERAND_CBIT :
785
      value = 0;
786
      break;
787
    case IP2K_OPERAND_DCBIT :
788
      value = 0;
789
      break;
790
    case IP2K_OPERAND_FR :
791
      value = fields->f_reg;
792
      break;
793
    case IP2K_OPERAND_LIT8 :
794
      value = fields->f_imm8;
795
      break;
796
    case IP2K_OPERAND_PABITS :
797
      value = 0;
798
      break;
799
    case IP2K_OPERAND_RETI3 :
800
      value = fields->f_reti3;
801
      break;
802
    case IP2K_OPERAND_ZBIT :
803
      value = 0;
804
      break;
805
 
806
    default :
807
      /* xgettext:c-format */
808
      fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
809
                       opindex);
810
      abort ();
811
  }
812
 
813
  return value;
814
}
815
 
816
void ip2k_cgen_set_int_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
817
void ip2k_cgen_set_vma_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
818
 
819
/* Stuffing values in cgen_fields is handled by a collection of functions.
820
   They are distinguished by the type of the VALUE argument they accept.
821
   TODO: floating point, inlining support, remove cases where argument type
822
   not appropriate.  */
823
 
824
void
825
ip2k_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
826
                             int opindex,
827
                             CGEN_FIELDS * fields,
828
                             int value)
829
{
830
  switch (opindex)
831
    {
832
    case IP2K_OPERAND_ADDR16CJP :
833
      fields->f_addr16cjp = value;
834
      break;
835
    case IP2K_OPERAND_ADDR16H :
836
      fields->f_imm8 = value;
837
      break;
838
    case IP2K_OPERAND_ADDR16L :
839
      fields->f_imm8 = value;
840
      break;
841
    case IP2K_OPERAND_ADDR16P :
842
      fields->f_page3 = value;
843
      break;
844
    case IP2K_OPERAND_BITNO :
845
      fields->f_bitno = value;
846
      break;
847
    case IP2K_OPERAND_CBIT :
848
      break;
849
    case IP2K_OPERAND_DCBIT :
850
      break;
851
    case IP2K_OPERAND_FR :
852
      fields->f_reg = value;
853
      break;
854
    case IP2K_OPERAND_LIT8 :
855
      fields->f_imm8 = value;
856
      break;
857
    case IP2K_OPERAND_PABITS :
858
      break;
859
    case IP2K_OPERAND_RETI3 :
860
      fields->f_reti3 = value;
861
      break;
862
    case IP2K_OPERAND_ZBIT :
863
      break;
864
 
865
    default :
866
      /* xgettext:c-format */
867
      fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
868
                       opindex);
869
      abort ();
870
  }
871
}
872
 
873
void
874
ip2k_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
875
                             int opindex,
876
                             CGEN_FIELDS * fields,
877
                             bfd_vma value)
878
{
879
  switch (opindex)
880
    {
881
    case IP2K_OPERAND_ADDR16CJP :
882
      fields->f_addr16cjp = value;
883
      break;
884
    case IP2K_OPERAND_ADDR16H :
885
      fields->f_imm8 = value;
886
      break;
887
    case IP2K_OPERAND_ADDR16L :
888
      fields->f_imm8 = value;
889
      break;
890
    case IP2K_OPERAND_ADDR16P :
891
      fields->f_page3 = value;
892
      break;
893
    case IP2K_OPERAND_BITNO :
894
      fields->f_bitno = value;
895
      break;
896
    case IP2K_OPERAND_CBIT :
897
      break;
898
    case IP2K_OPERAND_DCBIT :
899
      break;
900
    case IP2K_OPERAND_FR :
901
      fields->f_reg = value;
902
      break;
903
    case IP2K_OPERAND_LIT8 :
904
      fields->f_imm8 = value;
905
      break;
906
    case IP2K_OPERAND_PABITS :
907
      break;
908
    case IP2K_OPERAND_RETI3 :
909
      fields->f_reti3 = value;
910
      break;
911
    case IP2K_OPERAND_ZBIT :
912
      break;
913
 
914
    default :
915
      /* xgettext:c-format */
916
      fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
917
                       opindex);
918
      abort ();
919
  }
920
}
921
 
922
/* Function to call before using the instruction builder tables.  */
923
 
924
void
925
ip2k_cgen_init_ibld_table (CGEN_CPU_DESC cd)
926
{
927
  cd->insert_handlers = & ip2k_cgen_insert_handlers[0];
928
  cd->extract_handlers = & ip2k_cgen_extract_handlers[0];
929
 
930
  cd->insert_operand = ip2k_cgen_insert_operand;
931
  cd->extract_operand = ip2k_cgen_extract_operand;
932
 
933
  cd->get_int_operand = ip2k_cgen_get_int_operand;
934
  cd->set_int_operand = ip2k_cgen_set_int_operand;
935
  cd->get_vma_operand = ip2k_cgen_get_vma_operand;
936
  cd->set_vma_operand = ip2k_cgen_set_vma_operand;
937
}

powered by: WebSVN 2.1.0

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