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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [opcodes/] [ip2k-ibld.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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