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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* Instruction building/extraction support for @arch@. -*- 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 
30
#include "ansidecl.h"
31
#include "dis-asm.h"
32
#include "bfd.h"
33
#include "symcat.h"
34
#include "@prefix@-desc.h"
35
#include "@prefix@-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 -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.  */

powered by: WebSVN 2.1.0

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