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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [opcodes/] [lm32-ibld.c] - Blame information for rev 818

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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