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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [opcodes/] [openrisc-ibld.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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