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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [opcodes/] [cgen-ibld.in] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* 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 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 
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
 
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_SIGN_OPT))
149
    {
150
      long minval = - (1L << (length - 1));
151
      unsigned long maxval = mask;
152
 
153
      if ((value > 0 && (unsigned long) value > maxval)
154
          || value < minval)
155
        {
156
          /* xgettext:c-format */
157
          sprintf (errbuf,
158
                   _("operand out of range (%ld not between %ld and %lu)"),
159
                   value, minval, maxval);
160
          return errbuf;
161
        }
162
    }
163
  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
164
    {
165
      unsigned long maxval = mask;
166
 
167
      if ((unsigned long) value > maxval)
168
        {
169
          /* xgettext:c-format */
170
          sprintf (errbuf,
171
                   _("operand out of range (%lu not between 0 and %lu)"),
172
                   value, maxval);
173
          return errbuf;
174
        }
175
    }
176
  else
177
    {
178
      if (! cgen_signed_overflow_ok_p (cd))
179
        {
180
          long minval = - (1L << (length - 1));
181
          long maxval =   (1L << (length - 1)) - 1;
182
 
183
          if (value < minval || value > maxval)
184
            {
185
              sprintf
186
                /* xgettext:c-format */
187
                (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
188
                 value, minval, maxval);
189
              return errbuf;
190
            }
191
        }
192
    }
193
 
194
#if CGEN_INT_INSN_P
195
 
196
  {
197
    int shift;
198
 
199
    if (CGEN_INSN_LSB0_P)
200
      shift = (word_offset + start + 1) - length;
201
    else
202
      shift = total_length - (word_offset + start + length);
203
    *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
204
  }
205
 
206
#else /* ! CGEN_INT_INSN_P */
207
 
208
  {
209
    unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
210
 
211
    insert_1 (cd, value, start, length, word_length, bufp);
212
  }
213
 
214
#endif /* ! CGEN_INT_INSN_P */
215
 
216
  return NULL;
217
}
218
 
219
/* Default insn builder (insert handler).
220
   The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
221
   that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
222
   recorded in host byte order, otherwise BUFFER is an array of bytes
223
   and the value is recorded in target byte order).
224
   The result is an error message or NULL if success.  */
225
 
226
static const char *
227
insert_insn_normal (cd, insn, fields, buffer, pc)
228
     CGEN_CPU_DESC cd;
229
     const CGEN_INSN * insn;
230
     CGEN_FIELDS * fields;
231
     CGEN_INSN_BYTES_PTR buffer;
232
     bfd_vma pc;
233
{
234
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
235
  unsigned long value;
236
  const CGEN_SYNTAX_CHAR_TYPE * syn;
237
 
238
  CGEN_INIT_INSERT (cd);
239
  value = CGEN_INSN_BASE_VALUE (insn);
240
 
241
  /* If we're recording insns as numbers (rather than a string of bytes),
242
     target byte order handling is deferred until later.  */
243
 
244
#if CGEN_INT_INSN_P
245
 
246
  put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
247
                      CGEN_FIELDS_BITSIZE (fields), value);
248
 
249
#else
250
 
251
  cgen_put_insn_value (cd, buffer, min (cd->base_insn_bitsize,
252
                                        CGEN_FIELDS_BITSIZE (fields)),
253
                       value);
254
 
255
#endif /* ! CGEN_INT_INSN_P */
256
 
257
  /* ??? It would be better to scan the format's fields.
258
     Still need to be able to insert a value based on the operand though;
259
     e.g. storing a branch displacement that got resolved later.
260
     Needs more thought first.  */
261
 
262
  for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
263
    {
264
      const char *errmsg;
265
 
266
      if (CGEN_SYNTAX_CHAR_P (* syn))
267
        continue;
268
 
269
      errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
270
                                       fields, buffer, pc);
271
      if (errmsg)
272
        return errmsg;
273
    }
274
 
275
  return NULL;
276
}
277
 
278
/* Cover function to store an insn value into an integral insn.  Must go here
279
 because it needs -desc.h for CGEN_INT_INSN_P.  */
280
 
281
static void
282
put_insn_int_value (cd, buf, length, insn_length, value)
283
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
284
     CGEN_INSN_BYTES_PTR buf;
285
     int length;
286
     int insn_length;
287
     CGEN_INSN_INT value;
288
{
289
  /* For architectures with insns smaller than the base-insn-bitsize,
290
     length may be too big.  */
291
  if (length > insn_length)
292
    *buf = value;
293
  else
294
    {
295
      int shift = insn_length - length;
296
      /* Written this way to avoid undefined behaviour.  */
297
      CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
298
      *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
299
    }
300
}
301
 
302
/* Operand extraction.  */
303
 
304
#if ! CGEN_INT_INSN_P
305
 
306
/* Subroutine of extract_normal.
307
   Ensure sufficient bytes are cached in EX_INFO.
308
   OFFSET is the offset in bytes from the start of the insn of the value.
309
   BYTES is the length of the needed value.
310
   Returns 1 for success, 0 for failure.  */
311
 
312
static CGEN_INLINE int
313
fill_cache (cd, ex_info, offset, bytes, pc)
314
     CGEN_CPU_DESC cd;
315
     CGEN_EXTRACT_INFO *ex_info;
316
     int offset, bytes;
317
     bfd_vma pc;
318
{
319
  /* It's doubtful that the middle part has already been fetched so
320
     we don't optimize that case.  kiss.  */
321
  int mask;
322
  disassemble_info *info = (disassemble_info *) ex_info->dis_info;
323
 
324
  /* First do a quick check.  */
325
  mask = (1 << bytes) - 1;
326
  if (((ex_info->valid >> offset) & mask) == mask)
327
    return 1;
328
 
329
  /* Search for the first byte we need to read.  */
330
  for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
331
    if (! (mask & ex_info->valid))
332
      break;
333
 
334
  if (bytes)
335
    {
336
      int status;
337
 
338
      pc += offset;
339
      status = (*info->read_memory_func)
340
        (pc, ex_info->insn_bytes + offset, bytes, info);
341
 
342
      if (status != 0)
343
        {
344
          (*info->memory_error_func) (status, pc, info);
345
          return 0;
346
        }
347
 
348
      ex_info->valid |= ((1 << bytes) - 1) << offset;
349
    }
350
 
351
  return 1;
352
}
353
 
354
/* Subroutine of extract_normal.  */
355
 
356
static CGEN_INLINE long
357
extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
358
     CGEN_CPU_DESC cd;
359
     CGEN_EXTRACT_INFO *ex_info;
360
     int start,length,word_length;
361
     unsigned char *bufp;
362
     bfd_vma pc;
363
{
364
  unsigned long x;
365
  int shift;
366
  int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
367
 
368
  x = bfd_get_bits (bufp, word_length, big_p);
369
 
370
  if (CGEN_INSN_LSB0_P)
371
    shift = (start + 1) - length;
372
  else
373
    shift = (word_length - (start + length));
374
  return x >> shift;
375
}
376
 
377
#endif /* ! CGEN_INT_INSN_P */
378
 
379
/* Default extraction routine.
380
 
381
   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
382
   or sometimes less for cases like the m32r where the base insn size is 32
383
   but some insns are 16 bits.
384
   ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
385
   but for generality we take a bitmask of all of them.
386
   WORD_OFFSET is the offset in bits from the start of the insn of the value.
387
   WORD_LENGTH is the length of the word in bits in which the value resides.
388
   START is the starting bit number in the word, architecture origin.
389
   LENGTH is the length of VALUE in bits.
390
   TOTAL_LENGTH is the total length of the insn in bits.
391
 
392
   Returns 1 for success, 0 for failure.  */
393
 
394
/* ??? The return code isn't properly used.  wip.  */
395
 
396
/* ??? This doesn't handle bfd_vma's.  Create another function when
397
   necessary.  */
398
 
399
static int
400
extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
401
                word_length, total_length, pc, valuep)
402
     CGEN_CPU_DESC cd;
403
#if ! CGEN_INT_INSN_P
404
     CGEN_EXTRACT_INFO *ex_info;
405
#else
406
     CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
407
#endif
408
     CGEN_INSN_INT insn_value;
409
     unsigned int attrs;
410
     unsigned int word_offset, start, length, word_length, total_length;
411
#if ! CGEN_INT_INSN_P
412
     bfd_vma pc;
413
#else
414
     bfd_vma pc ATTRIBUTE_UNUSED;
415
#endif
416
     long *valuep;
417
{
418
  CGEN_INSN_INT value, mask;
419
 
420
  /* If LENGTH is zero, this operand doesn't contribute to the value
421
     so give it a standard value of zero.  */
422
  if (length == 0)
423
    {
424
      *valuep = 0;
425
      return 1;
426
    }
427
 
428
#if 0
429
  if (CGEN_INT_INSN_P
430
      && word_offset != 0)
431
    abort ();
432
#endif
433
 
434
  if (word_length > 32)
435
    abort ();
436
 
437
  /* For architectures with insns smaller than the insn-base-bitsize,
438
     word_length may be too big.  */
439
  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
440
    {
441
      if (word_offset == 0
442
          && word_length > total_length)
443
        word_length = total_length;
444
    }
445
 
446
  /* Does the value reside in INSN_VALUE, and at the right alignment?  */
447
 
448
  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
449
    {
450
      if (CGEN_INSN_LSB0_P)
451
        value = insn_value >> ((word_offset + start + 1) - length);
452
      else
453
        value = insn_value >> (total_length - ( word_offset + start + length));
454
    }
455
 
456
#if ! CGEN_INT_INSN_P
457
 
458
  else
459
    {
460
      unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
461
 
462
      if (word_length > 32)
463
        abort ();
464
 
465
      if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
466
        return 0;
467
 
468
      value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
469
    }
470
 
471
#endif /* ! CGEN_INT_INSN_P */
472
 
473
  /* Written this way to avoid undefined behaviour.  */
474
  mask = (((1L << (length - 1)) - 1) << 1) | 1;
475
 
476
  value &= mask;
477
  /* sign extend? */
478
  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
479
      && (value & (1L << (length - 1))))
480
    value |= ~mask;
481
 
482
  *valuep = value;
483
 
484
  return 1;
485
}
486
 
487
/* Default insn extractor.
488
 
489
   INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
490
   The extracted fields are stored in FIELDS.
491
   EX_INFO is used to handle reading variable length insns.
492
   Return the length of the insn in bits, or 0 if no match,
493
   or -1 if an error occurs fetching data (memory_error_func will have
494
   been called).  */
495
 
496
static int
497
extract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)
498
     CGEN_CPU_DESC cd;
499
     const CGEN_INSN *insn;
500
     CGEN_EXTRACT_INFO *ex_info;
501
     CGEN_INSN_INT insn_value;
502
     CGEN_FIELDS *fields;
503
     bfd_vma pc;
504
{
505
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
506
  const CGEN_SYNTAX_CHAR_TYPE *syn;
507
 
508
  CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
509
 
510
  CGEN_INIT_EXTRACT (cd);
511
 
512
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
513
    {
514
      int length;
515
 
516
      if (CGEN_SYNTAX_CHAR_P (*syn))
517
        continue;
518
 
519
      length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
520
                                        ex_info, insn_value, fields, pc);
521
      if (length <= 0)
522
        return length;
523
    }
524
 
525
  /* We recognized and successfully extracted this insn.  */
526
  return CGEN_INSN_BITSIZE (insn);
527
}
528
 
529
/* 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.