1
/* Instruction building/extraction support for @arch@. -*- C -*-
3
THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4
- the resultant file is machine generated, cgen-ibld.in isn't
6
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
This file is part of the GNU Binutils and GDB, the GNU debugger.
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)
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.
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. */
24
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
33
#include "@prefix@-desc.h"
34
#include "@prefix@-opc.h"
36
#include "safe-ctype.h"
39
#define min(a,b) ((a) < (b) ? (a) : (b))
41
#define max(a,b) ((a) > (b) ? (a) : (b))
43
/* Used by the ifield rtx function. */
44
#define FLD(f) (fields->f)
46
static const char * insert_normal
47
(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
(CGEN_CPU_DESC, const CGEN_INSN *,
51
CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
52
static int extract_normal
53
(CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
54
unsigned int, unsigned int, unsigned int, unsigned int,
55
unsigned int, unsigned int, bfd_vma, long *);
56
static int extract_insn_normal
57
(CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58
CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
60
static void put_insn_int_value
61
(CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
64
static CGEN_INLINE void insert_1
65
(CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
66
static CGEN_INLINE int fill_cache
67
(CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
68
static CGEN_INLINE long extract_1
69
(CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
72
/* Operand insertion. */
76
/* Subroutine of insert_normal. */
78
static CGEN_INLINE void
79
insert_1 (CGEN_CPU_DESC cd,
89
x = cgen_get_insn_value (cd, bufp, word_length);
91
/* Written this way to avoid undefined behaviour. */
92
mask = (((1L << (length - 1)) - 1) << 1) | 1;
94
shift = (start + 1) - length;
96
shift = (word_length - (start + length));
97
x = (x & ~(mask << shift)) | ((value & mask) << shift);
99
cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
102
#endif /* ! CGEN_INT_INSN_P */
104
/* Default insertion routine.
106
ATTRS is a mask of the boolean attributes.
107
WORD_OFFSET is the offset in bits from the start of the insn of the value.
108
WORD_LENGTH is the length of the word in bits in which the value resides.
109
START is the starting bit number in the word, architecture origin.
110
LENGTH is the length of VALUE in bits.
111
TOTAL_LENGTH is the total length of the insn in bits.
113
The result is an error message or NULL if success. */
115
/* ??? This duplicates functionality with bfd's howto table and
116
bfd_install_relocation. */
117
/* ??? This doesn't handle bfd_vma's. Create another function when
121
insert_normal (CGEN_CPU_DESC cd,
124
unsigned int word_offset,
127
unsigned int word_length,
128
unsigned int total_length,
129
CGEN_INSN_BYTES_PTR buffer)
131
static char errbuf[100];
132
/* Written this way to avoid undefined behaviour. */
133
unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
135
/* If LENGTH is zero, this operand doesn't contribute to the value. */
145
if (word_length > 32)
148
/* For architectures with insns smaller than the base-insn-bitsize,
149
word_length may be too big. */
150
if (cd->min_insn_bitsize < cd->base_insn_bitsize)
153
&& word_length > total_length)
154
word_length = total_length;
157
/* Ensure VALUE will fit. */
158
if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
160
long minval = - (1L << (length - 1));
161
unsigned long maxval = mask;
163
if ((value > 0 && (unsigned long) value > maxval)
166
/* xgettext:c-format */
168
_("operand out of range (%ld not between %ld and %lu)"),
169
value, minval, maxval);
173
else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
175
unsigned long maxval = mask;
177
if ((unsigned long) value > maxval)
179
/* xgettext:c-format */
181
_("operand out of range (%lu not between 0 and %lu)"),
188
if (! cgen_signed_overflow_ok_p (cd))
190
long minval = - (1L << (length - 1));
191
long maxval = (1L << (length - 1)) - 1;
193
if (value < minval || value > maxval)
196
/* xgettext:c-format */
197
(errbuf, _("operand out of range (%ld not between %ld and %ld)"),
198
value, minval, maxval);
209
if (CGEN_INSN_LSB0_P)
210
shift = (word_offset + start + 1) - length;
212
shift = total_length - (word_offset + start + length);
213
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
216
#else /* ! CGEN_INT_INSN_P */
219
unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
221
insert_1 (cd, value, start, length, word_length, bufp);
224
#endif /* ! CGEN_INT_INSN_P */
229
/* Default insn builder (insert handler).
230
The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
231
that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
232
recorded in host byte order, otherwise BUFFER is an array of bytes
233
and the value is recorded in target byte order).
234
The result is an error message or NULL if success. */
237
insert_insn_normal (CGEN_CPU_DESC cd,
238
const CGEN_INSN * insn,
239
CGEN_FIELDS * fields,
240
CGEN_INSN_BYTES_PTR buffer,
243
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
245
const CGEN_SYNTAX_CHAR_TYPE * syn;
247
CGEN_INIT_INSERT (cd);
248
value = CGEN_INSN_BASE_VALUE (insn);
250
/* If we're recording insns as numbers (rather than a string of bytes),
251
target byte order handling is deferred until later. */
255
put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
256
CGEN_FIELDS_BITSIZE (fields), value);
260
cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
261
(unsigned) CGEN_FIELDS_BITSIZE (fields)),
264
#endif /* ! CGEN_INT_INSN_P */
266
/* ??? It would be better to scan the format's fields.
267
Still need to be able to insert a value based on the operand though;
268
e.g. storing a branch displacement that got resolved later.
269
Needs more thought first. */
271
for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
275
if (CGEN_SYNTAX_CHAR_P (* syn))
278
errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
288
/* Cover function to store an insn value into an integral insn. Must go here
289
because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
292
put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
293
CGEN_INSN_BYTES_PTR buf,
298
/* For architectures with insns smaller than the base-insn-bitsize,
299
length may be too big. */
300
if (length > insn_length)
304
int shift = insn_length - length;
305
/* Written this way to avoid undefined behaviour. */
306
CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
307
*buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
312
/* Operand extraction. */
314
#if ! CGEN_INT_INSN_P
316
/* Subroutine of extract_normal.
317
Ensure sufficient bytes are cached in EX_INFO.
318
OFFSET is the offset in bytes from the start of the insn of the value.
319
BYTES is the length of the needed value.
320
Returns 1 for success, 0 for failure. */
322
static CGEN_INLINE int
323
fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
324
CGEN_EXTRACT_INFO *ex_info,
329
/* It's doubtful that the middle part has already been fetched so
330
we don't optimize that case. kiss. */
332
disassemble_info *info = (disassemble_info *) ex_info->dis_info;
334
/* First do a quick check. */
335
mask = (1 << bytes) - 1;
336
if (((ex_info->valid >> offset) & mask) == mask)
339
/* Search for the first byte we need to read. */
340
for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
341
if (! (mask & ex_info->valid))
349
status = (*info->read_memory_func)
350
(pc, ex_info->insn_bytes + offset, bytes, info);
354
(*info->memory_error_func) (status, pc, info);
358
ex_info->valid |= ((1 << bytes) - 1) << offset;
364
/* Subroutine of extract_normal. */
366
static CGEN_INLINE long
367
extract_1 (CGEN_CPU_DESC cd,
368
CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
373
bfd_vma pc ATTRIBUTE_UNUSED)
378
int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
380
x = cgen_get_insn_value (cd, bufp, word_length);
382
if (CGEN_INSN_LSB0_P)
383
shift = (start + 1) - length;
385
shift = (word_length - (start + length));
389
#endif /* ! CGEN_INT_INSN_P */
391
/* Default extraction routine.
393
INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
394
or sometimes less for cases like the m32r where the base insn size is 32
395
but some insns are 16 bits.
396
ATTRS is a mask of the boolean attributes. We only need `SIGNED',
397
but for generality we take a bitmask of all of them.
398
WORD_OFFSET is the offset in bits from the start of the insn of the value.
399
WORD_LENGTH is the length of the word in bits in which the value resides.
400
START is the starting bit number in the word, architecture origin.
401
LENGTH is the length of VALUE in bits.
402
TOTAL_LENGTH is the total length of the insn in bits.
404
Returns 1 for success, 0 for failure. */
406
/* ??? The return code isn't properly used. wip. */
408
/* ??? This doesn't handle bfd_vma's. Create another function when
412
extract_normal (CGEN_CPU_DESC cd,
413
#if ! CGEN_INT_INSN_P
414
CGEN_EXTRACT_INFO *ex_info,
416
CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
418
CGEN_INSN_INT insn_value,
420
unsigned int word_offset,
423
unsigned int word_length,
424
unsigned int total_length,
425
#if ! CGEN_INT_INSN_P
428
bfd_vma pc ATTRIBUTE_UNUSED,
434
/* If LENGTH is zero, this operand doesn't contribute to the value
435
so give it a standard value of zero. */
448
if (word_length > 32)
451
/* For architectures with insns smaller than the insn-base-bitsize,
452
word_length may be too big. */
453
if (cd->min_insn_bitsize < cd->base_insn_bitsize)
456
&& word_length > total_length)
457
word_length = total_length;
460
/* Does the value reside in INSN_VALUE, and at the right alignment? */
462
if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
464
if (CGEN_INSN_LSB0_P)
465
value = insn_value >> ((word_offset + start + 1) - length);
467
value = insn_value >> (total_length - ( word_offset + start + length));
470
#if ! CGEN_INT_INSN_P
474
unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
476
if (word_length > 32)
479
if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
482
value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
485
#endif /* ! CGEN_INT_INSN_P */
487
/* Written this way to avoid undefined behaviour. */
488
mask = (((1L << (length - 1)) - 1) << 1) | 1;
492
if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
493
&& (value & (1L << (length - 1))))
501
/* Default insn extractor.
503
INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
504
The extracted fields are stored in FIELDS.
505
EX_INFO is used to handle reading variable length insns.
506
Return the length of the insn in bits, or 0 if no match,
507
or -1 if an error occurs fetching data (memory_error_func will have
511
extract_insn_normal (CGEN_CPU_DESC cd,
512
const CGEN_INSN *insn,
513
CGEN_EXTRACT_INFO *ex_info,
514
CGEN_INSN_INT insn_value,
518
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
519
const CGEN_SYNTAX_CHAR_TYPE *syn;
521
CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
523
CGEN_INIT_EXTRACT (cd);
525
for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
529
if (CGEN_SYNTAX_CHAR_P (*syn))
532
length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
533
ex_info, insn_value, fields, pc);
538
/* We recognized and successfully extracted this insn. */
539
return CGEN_INSN_BITSIZE (insn);
542
/* machine generated code added here */