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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [openrisc-ibld.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Instruction building/extraction support for openrisc. -*- 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 "openrisc-desc.h"
34
#include "openrisc-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 * openrisc_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
openrisc_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 OPENRISC_OPERAND_ABS_26 :
573
      {
574
        long value = fields->f_abs26;
575
        value = ((unsigned int) (pc) >> (2));
576
        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_ABS_ADDR), 0, 25, 26, 32, total_length, buffer);
577
      }
578
      break;
579
    case OPENRISC_OPERAND_DISP_26 :
580
      {
581
        long value = fields->f_disp26;
582
        value = ((int) (((value) - (pc))) >> (2));
583
        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 25, 26, 32, total_length, buffer);
584
      }
585
      break;
586
    case OPENRISC_OPERAND_HI16 :
587
      errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
588
      break;
589
    case OPENRISC_OPERAND_LO16 :
590
      errmsg = insert_normal (cd, fields->f_lo16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
591
      break;
592
    case OPENRISC_OPERAND_OP_F_23 :
593
      errmsg = insert_normal (cd, fields->f_op4, 0, 0, 23, 3, 32, total_length, buffer);
594
      break;
595
    case OPENRISC_OPERAND_OP_F_3 :
596
      errmsg = insert_normal (cd, fields->f_op5, 0, 0, 25, 5, 32, total_length, buffer);
597
      break;
598
    case OPENRISC_OPERAND_RA :
599
      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 20, 5, 32, total_length, buffer);
600
      break;
601
    case OPENRISC_OPERAND_RB :
602
      errmsg = insert_normal (cd, fields->f_r3, 0, 0, 15, 5, 32, total_length, buffer);
603
      break;
604
    case OPENRISC_OPERAND_RD :
605
      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 25, 5, 32, total_length, buffer);
606
      break;
607
    case OPENRISC_OPERAND_SIMM_16 :
608
      errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
609
      break;
610
    case OPENRISC_OPERAND_UI16NC :
611
      {
612
{
613
  FLD (f_i16_2) = ((((unsigned int) (FLD (f_i16nc)) >> (11))) & (31));
614
  FLD (f_i16_1) = ((FLD (f_i16nc)) & (2047));
615
}
616
        errmsg = insert_normal (cd, fields->f_i16_1, 0, 0, 10, 11, 32, total_length, buffer);
617
        if (errmsg)
618
          break;
619
        errmsg = insert_normal (cd, fields->f_i16_2, 0, 0, 25, 5, 32, total_length, buffer);
620
        if (errmsg)
621
          break;
622
      }
623
      break;
624
    case OPENRISC_OPERAND_UIMM_16 :
625
      errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 15, 16, 32, total_length, buffer);
626
      break;
627
    case OPENRISC_OPERAND_UIMM_5 :
628
      errmsg = insert_normal (cd, fields->f_uimm5, 0, 0, 4, 5, 32, total_length, buffer);
629
      break;
630
 
631
    default :
632
      /* xgettext:c-format */
633
      fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
634
               opindex);
635
      abort ();
636
  }
637
 
638
  return errmsg;
639
}
640
 
641
int openrisc_cgen_extract_operand
642
  PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
643
           CGEN_FIELDS *, bfd_vma));
644
 
645
/* Main entry point for operand extraction.
646
   The result is <= 0 for error, >0 for success.
647
   ??? Actual values aren't well defined right now.
648
 
649
   This function is basically just a big switch statement.  Earlier versions
650
   used tables to look up the function to use, but
651
   - if the table contains both assembler and disassembler functions then
652
     the disassembler contains much of the assembler and vice-versa,
653
   - there's a lot of inlining possibilities as things grow,
654
   - using a switch statement avoids the function call overhead.
655
 
656
   This function could be moved into `print_insn_normal', but keeping it
657
   separate makes clear the interface between `print_insn_normal' and each of
658
   the handlers.  */
659
 
660
int
661
openrisc_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
662
     CGEN_CPU_DESC cd;
663
     int opindex;
664
     CGEN_EXTRACT_INFO *ex_info;
665
     CGEN_INSN_INT insn_value;
666
     CGEN_FIELDS * fields;
667
     bfd_vma pc;
668
{
669
  /* Assume success (for those operands that are nops).  */
670
  int length = 1;
671
  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
672
 
673
  switch (opindex)
674
    {
675
    case OPENRISC_OPERAND_ABS_26 :
676
      {
677
        long value;
678
        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_ABS_ADDR), 0, 25, 26, 32, total_length, pc, & value);
679
        value = ((value) << (2));
680
        fields->f_abs26 = value;
681
      }
682
      break;
683
    case OPENRISC_OPERAND_DISP_26 :
684
      {
685
        long value;
686
        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 25, 26, 32, total_length, pc, & value);
687
        value = ((((value) << (2))) + (pc));
688
        fields->f_disp26 = value;
689
      }
690
      break;
691
    case OPENRISC_OPERAND_HI16 :
692
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_simm16);
693
      break;
694
    case OPENRISC_OPERAND_LO16 :
695
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_lo16);
696
      break;
697
    case OPENRISC_OPERAND_OP_F_23 :
698
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 23, 3, 32, total_length, pc, & fields->f_op4);
699
      break;
700
    case OPENRISC_OPERAND_OP_F_3 :
701
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_op5);
702
      break;
703
    case OPENRISC_OPERAND_RA :
704
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_r2);
705
      break;
706
    case OPENRISC_OPERAND_RB :
707
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 5, 32, total_length, pc, & fields->f_r3);
708
      break;
709
    case OPENRISC_OPERAND_RD :
710
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_r1);
711
      break;
712
    case OPENRISC_OPERAND_SIMM_16 :
713
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_simm16);
714
      break;
715
    case OPENRISC_OPERAND_UI16NC :
716
      {
717
        length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 11, 32, total_length, pc, & fields->f_i16_1);
718
        if (length <= 0) break;
719
        length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_i16_2);
720
        if (length <= 0) break;
721
{
722
  FLD (f_i16nc) = openrisc_sign_extend_16bit (((((FLD (f_i16_2)) << (11))) | (FLD (f_i16_1))));
723
}
724
      }
725
      break;
726
    case OPENRISC_OPERAND_UIMM_16 :
727
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_uimm16);
728
      break;
729
    case OPENRISC_OPERAND_UIMM_5 :
730
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 5, 32, total_length, pc, & fields->f_uimm5);
731
      break;
732
 
733
    default :
734
      /* xgettext:c-format */
735
      fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
736
               opindex);
737
      abort ();
738
    }
739
 
740
  return length;
741
}
742
 
743
cgen_insert_fn * const openrisc_cgen_insert_handlers[] =
744
{
745
  insert_insn_normal,
746
};
747
 
748
cgen_extract_fn * const openrisc_cgen_extract_handlers[] =
749
{
750
  extract_insn_normal,
751
};
752
 
753
int openrisc_cgen_get_int_operand
754
  PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
755
bfd_vma openrisc_cgen_get_vma_operand
756
  PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
757
 
758
/* Getting values from cgen_fields is handled by a collection of functions.
759
   They are distinguished by the type of the VALUE argument they return.
760
   TODO: floating point, inlining support, remove cases where result type
761
   not appropriate.  */
762
 
763
int
764
openrisc_cgen_get_int_operand (cd, opindex, fields)
765
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
766
     int opindex;
767
     const CGEN_FIELDS * fields;
768
{
769
  int value;
770
 
771
  switch (opindex)
772
    {
773
    case OPENRISC_OPERAND_ABS_26 :
774
      value = fields->f_abs26;
775
      break;
776
    case OPENRISC_OPERAND_DISP_26 :
777
      value = fields->f_disp26;
778
      break;
779
    case OPENRISC_OPERAND_HI16 :
780
      value = fields->f_simm16;
781
      break;
782
    case OPENRISC_OPERAND_LO16 :
783
      value = fields->f_lo16;
784
      break;
785
    case OPENRISC_OPERAND_OP_F_23 :
786
      value = fields->f_op4;
787
      break;
788
    case OPENRISC_OPERAND_OP_F_3 :
789
      value = fields->f_op5;
790
      break;
791
    case OPENRISC_OPERAND_RA :
792
      value = fields->f_r2;
793
      break;
794
    case OPENRISC_OPERAND_RB :
795
      value = fields->f_r3;
796
      break;
797
    case OPENRISC_OPERAND_RD :
798
      value = fields->f_r1;
799
      break;
800
    case OPENRISC_OPERAND_SIMM_16 :
801
      value = fields->f_simm16;
802
      break;
803
    case OPENRISC_OPERAND_UI16NC :
804
      value = fields->f_i16nc;
805
      break;
806
    case OPENRISC_OPERAND_UIMM_16 :
807
      value = fields->f_uimm16;
808
      break;
809
    case OPENRISC_OPERAND_UIMM_5 :
810
      value = fields->f_uimm5;
811
      break;
812
 
813
    default :
814
      /* xgettext:c-format */
815
      fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
816
                       opindex);
817
      abort ();
818
  }
819
 
820
  return value;
821
}
822
 
823
bfd_vma
824
openrisc_cgen_get_vma_operand (cd, opindex, fields)
825
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
826
     int opindex;
827
     const CGEN_FIELDS * fields;
828
{
829
  bfd_vma value;
830
 
831
  switch (opindex)
832
    {
833
    case OPENRISC_OPERAND_ABS_26 :
834
      value = fields->f_abs26;
835
      break;
836
    case OPENRISC_OPERAND_DISP_26 :
837
      value = fields->f_disp26;
838
      break;
839
    case OPENRISC_OPERAND_HI16 :
840
      value = fields->f_simm16;
841
      break;
842
    case OPENRISC_OPERAND_LO16 :
843
      value = fields->f_lo16;
844
      break;
845
    case OPENRISC_OPERAND_OP_F_23 :
846
      value = fields->f_op4;
847
      break;
848
    case OPENRISC_OPERAND_OP_F_3 :
849
      value = fields->f_op5;
850
      break;
851
    case OPENRISC_OPERAND_RA :
852
      value = fields->f_r2;
853
      break;
854
    case OPENRISC_OPERAND_RB :
855
      value = fields->f_r3;
856
      break;
857
    case OPENRISC_OPERAND_RD :
858
      value = fields->f_r1;
859
      break;
860
    case OPENRISC_OPERAND_SIMM_16 :
861
      value = fields->f_simm16;
862
      break;
863
    case OPENRISC_OPERAND_UI16NC :
864
      value = fields->f_i16nc;
865
      break;
866
    case OPENRISC_OPERAND_UIMM_16 :
867
      value = fields->f_uimm16;
868
      break;
869
    case OPENRISC_OPERAND_UIMM_5 :
870
      value = fields->f_uimm5;
871
      break;
872
 
873
    default :
874
      /* xgettext:c-format */
875
      fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
876
                       opindex);
877
      abort ();
878
  }
879
 
880
  return value;
881
}
882
 
883
void openrisc_cgen_set_int_operand
884
  PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
885
void openrisc_cgen_set_vma_operand
886
  PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
887
 
888
/* Stuffing values in cgen_fields is handled by a collection of functions.
889
   They are distinguished by the type of the VALUE argument they accept.
890
   TODO: floating point, inlining support, remove cases where argument type
891
   not appropriate.  */
892
 
893
void
894
openrisc_cgen_set_int_operand (cd, opindex, fields, value)
895
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
896
     int opindex;
897
     CGEN_FIELDS * fields;
898
     int value;
899
{
900
  switch (opindex)
901
    {
902
    case OPENRISC_OPERAND_ABS_26 :
903
      fields->f_abs26 = value;
904
      break;
905
    case OPENRISC_OPERAND_DISP_26 :
906
      fields->f_disp26 = value;
907
      break;
908
    case OPENRISC_OPERAND_HI16 :
909
      fields->f_simm16 = value;
910
      break;
911
    case OPENRISC_OPERAND_LO16 :
912
      fields->f_lo16 = value;
913
      break;
914
    case OPENRISC_OPERAND_OP_F_23 :
915
      fields->f_op4 = value;
916
      break;
917
    case OPENRISC_OPERAND_OP_F_3 :
918
      fields->f_op5 = value;
919
      break;
920
    case OPENRISC_OPERAND_RA :
921
      fields->f_r2 = value;
922
      break;
923
    case OPENRISC_OPERAND_RB :
924
      fields->f_r3 = value;
925
      break;
926
    case OPENRISC_OPERAND_RD :
927
      fields->f_r1 = value;
928
      break;
929
    case OPENRISC_OPERAND_SIMM_16 :
930
      fields->f_simm16 = value;
931
      break;
932
    case OPENRISC_OPERAND_UI16NC :
933
      fields->f_i16nc = value;
934
      break;
935
    case OPENRISC_OPERAND_UIMM_16 :
936
      fields->f_uimm16 = value;
937
      break;
938
    case OPENRISC_OPERAND_UIMM_5 :
939
      fields->f_uimm5 = value;
940
      break;
941
 
942
    default :
943
      /* xgettext:c-format */
944
      fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
945
                       opindex);
946
      abort ();
947
  }
948
}
949
 
950
void
951
openrisc_cgen_set_vma_operand (cd, opindex, fields, value)
952
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
953
     int opindex;
954
     CGEN_FIELDS * fields;
955
     bfd_vma value;
956
{
957
  switch (opindex)
958
    {
959
    case OPENRISC_OPERAND_ABS_26 :
960
      fields->f_abs26 = value;
961
      break;
962
    case OPENRISC_OPERAND_DISP_26 :
963
      fields->f_disp26 = value;
964
      break;
965
    case OPENRISC_OPERAND_HI16 :
966
      fields->f_simm16 = value;
967
      break;
968
    case OPENRISC_OPERAND_LO16 :
969
      fields->f_lo16 = value;
970
      break;
971
    case OPENRISC_OPERAND_OP_F_23 :
972
      fields->f_op4 = value;
973
      break;
974
    case OPENRISC_OPERAND_OP_F_3 :
975
      fields->f_op5 = value;
976
      break;
977
    case OPENRISC_OPERAND_RA :
978
      fields->f_r2 = value;
979
      break;
980
    case OPENRISC_OPERAND_RB :
981
      fields->f_r3 = value;
982
      break;
983
    case OPENRISC_OPERAND_RD :
984
      fields->f_r1 = value;
985
      break;
986
    case OPENRISC_OPERAND_SIMM_16 :
987
      fields->f_simm16 = value;
988
      break;
989
    case OPENRISC_OPERAND_UI16NC :
990
      fields->f_i16nc = value;
991
      break;
992
    case OPENRISC_OPERAND_UIMM_16 :
993
      fields->f_uimm16 = value;
994
      break;
995
    case OPENRISC_OPERAND_UIMM_5 :
996
      fields->f_uimm5 = value;
997
      break;
998
 
999
    default :
1000
      /* xgettext:c-format */
1001
      fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1002
                       opindex);
1003
      abort ();
1004
  }
1005
}
1006
 
1007
/* Function to call before using the instruction builder tables.  */
1008
 
1009
void
1010
openrisc_cgen_init_ibld_table (cd)
1011
     CGEN_CPU_DESC cd;
1012
{
1013
  cd->insert_handlers = & openrisc_cgen_insert_handlers[0];
1014
  cd->extract_handlers = & openrisc_cgen_extract_handlers[0];
1015
 
1016
  cd->insert_operand = openrisc_cgen_insert_operand;
1017
  cd->extract_operand = openrisc_cgen_extract_operand;
1018
 
1019
  cd->get_int_operand = openrisc_cgen_get_int_operand;
1020
  cd->set_int_operand = openrisc_cgen_set_int_operand;
1021
  cd->get_vma_operand = openrisc_cgen_get_vma_operand;
1022
  cd->set_vma_operand = openrisc_cgen_set_vma_operand;
1023
}

powered by: WebSVN 2.1.0

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