* NEWS (Multi-arched targets): Document that all hppa-hpux targets
[deliverable/binutils-gdb.git] / opcodes / cgen-ibld.in
CommitLineData
f6e6b40f
BE
1/* Instruction building/extraction support for @arch@. -*- C -*-
2
3THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4- the resultant file is machine generated, cgen-ibld.in isn't
5
060d22b0 6Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
f6e6b40f
BE
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 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"
f6e6b40f
BE
28#include <stdio.h>
29#include "ansidecl.h"
30#include "dis-asm.h"
31#include "bfd.h"
32#include "symcat.h"
33#include "@prefix@-desc.h"
34#include "@prefix@-opc.h"
35#include "opintl.h"
37111cc7 36#include "safe-ctype.h"
f6e6b40f
BE
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
46static const char * insert_normal
10e05405
MM
47 (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
48 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
f6e6b40f 49static const char * insert_insn_normal
10e05405
MM
50 (CGEN_CPU_DESC, const CGEN_INSN *,
51 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
f6e6b40f 52static int extract_normal
10e05405
MM
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 *);
f6e6b40f 56static int extract_insn_normal
10e05405
MM
57 (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
0e2ee3ca 59#if CGEN_INT_INSN_P
6bb95a0f 60static void put_insn_int_value
10e05405 61 (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
0e2ee3ca
NC
62#endif
63#if ! CGEN_INT_INSN_P
64static CGEN_INLINE void insert_1
10e05405 65 (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
0e2ee3ca 66static CGEN_INLINE int fill_cache
10e05405 67 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
0e2ee3ca 68static CGEN_INLINE long extract_1
10e05405 69 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
0e2ee3ca 70#endif
f6e6b40f
BE
71\f
72/* Operand insertion. */
73
74#if ! CGEN_INT_INSN_P
75
76/* Subroutine of insert_normal. */
77
78static CGEN_INLINE void
10e05405
MM
79insert_1 (CGEN_CPU_DESC cd,
80 unsigned long value,
81 int start,length,word_length,
82 unsigned char *bufp)
f6e6b40f
BE
83{
84 unsigned long x,mask;
85 int shift;
f6e6b40f 86
545ae501 87 x = cgen_get_insn_value (cd, bufp, word_length);
f6e6b40f
BE
88
89 /* Written this way to avoid undefined behaviour. */
90 mask = (((1L << (length - 1)) - 1) << 1) | 1;
91 if (CGEN_INSN_LSB0_P)
92 shift = (start + 1) - length;
93 else
94 shift = (word_length - (start + length));
95 x = (x & ~(mask << shift)) | ((value & mask) << shift);
96
545ae501 97 cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
f6e6b40f
BE
98}
99
100#endif /* ! CGEN_INT_INSN_P */
101
102/* Default insertion routine.
103
104 ATTRS is a mask of the boolean attributes.
105 WORD_OFFSET is the offset in bits from the start of the insn of the value.
106 WORD_LENGTH is the length of the word in bits in which the value resides.
107 START is the starting bit number in the word, architecture origin.
108 LENGTH is the length of VALUE in bits.
109 TOTAL_LENGTH is the total length of the insn in bits.
110
111 The result is an error message or NULL if success. */
112
113/* ??? This duplicates functionality with bfd's howto table and
114 bfd_install_relocation. */
115/* ??? This doesn't handle bfd_vma's. Create another function when
116 necessary. */
117
118static const char *
10e05405
MM
119insert_normal (CGEN_CPU_DESC cd,
120 long value,
121 unsigned int attrs,
122 unsigned int word_offset,
123 unsigned int start,
124 unsigned int length,
125 unsigned int word_length,
126 unsigned int total_length,
127 CGEN_INSN_BYTES_PTR buffer)
f6e6b40f
BE
128{
129 static char errbuf[100];
130 /* Written this way to avoid undefined behaviour. */
131 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
132
133 /* If LENGTH is zero, this operand doesn't contribute to the value. */
134 if (length == 0)
135 return NULL;
136
6bb95a0f 137#if 0
f6e6b40f
BE
138 if (CGEN_INT_INSN_P
139 && word_offset != 0)
140 abort ();
6bb95a0f 141#endif
f6e6b40f
BE
142
143 if (word_length > 32)
144 abort ();
145
146 /* For architectures with insns smaller than the base-insn-bitsize,
147 word_length may be too big. */
148 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
149 {
150 if (word_offset == 0
151 && word_length > total_length)
152 word_length = total_length;
153 }
154
155 /* Ensure VALUE will fit. */
17f0ac84
GK
156 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
157 {
158 long minval = - (1L << (length - 1));
159 unsigned long maxval = mask;
160
161 if ((value > 0 && (unsigned long) value > maxval)
162 || value < minval)
163 {
164 /* xgettext:c-format */
165 sprintf (errbuf,
166 _("operand out of range (%ld not between %ld and %lu)"),
167 value, minval, maxval);
168 return errbuf;
169 }
170 }
171 else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
f6e6b40f
BE
172 {
173 unsigned long maxval = mask;
174
175 if ((unsigned long) value > maxval)
176 {
177 /* xgettext:c-format */
178 sprintf (errbuf,
179 _("operand out of range (%lu not between 0 and %lu)"),
180 value, maxval);
181 return errbuf;
182 }
183 }
184 else
185 {
186 if (! cgen_signed_overflow_ok_p (cd))
187 {
188 long minval = - (1L << (length - 1));
189 long maxval = (1L << (length - 1)) - 1;
190
191 if (value < minval || value > maxval)
192 {
193 sprintf
194 /* xgettext:c-format */
195 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
196 value, minval, maxval);
197 return errbuf;
198 }
199 }
200 }
201
202#if CGEN_INT_INSN_P
203
204 {
205 int shift;
206
207 if (CGEN_INSN_LSB0_P)
6bb95a0f 208 shift = (word_offset + start + 1) - length;
f6e6b40f 209 else
6bb95a0f 210 shift = total_length - (word_offset + start + length);
f6e6b40f
BE
211 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
212 }
213
214#else /* ! CGEN_INT_INSN_P */
215
216 {
217 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
218
219 insert_1 (cd, value, start, length, word_length, bufp);
220 }
221
222#endif /* ! CGEN_INT_INSN_P */
223
224 return NULL;
225}
226
227/* Default insn builder (insert handler).
0e70c820
BE
228 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
229 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
230 recorded in host byte order, otherwise BUFFER is an array of bytes
231 and the value is recorded in target byte order).
f6e6b40f
BE
232 The result is an error message or NULL if success. */
233
234static const char *
10e05405
MM
235insert_insn_normal (CGEN_CPU_DESC cd,
236 const CGEN_INSN * insn,
237 CGEN_FIELDS * fields,
238 CGEN_INSN_BYTES_PTR buffer,
239 bfd_vma pc)
f6e6b40f
BE
240{
241 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
242 unsigned long value;
4a9f416d 243 const CGEN_SYNTAX_CHAR_TYPE * syn;
f6e6b40f
BE
244
245 CGEN_INIT_INSERT (cd);
246 value = CGEN_INSN_BASE_VALUE (insn);
247
248 /* If we're recording insns as numbers (rather than a string of bytes),
249 target byte order handling is deferred until later. */
250
251#if CGEN_INT_INSN_P
252
6bb95a0f
DB
253 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
254 CGEN_FIELDS_BITSIZE (fields), value);
f6e6b40f
BE
255
256#else
257
0e2ee3ca
NC
258 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
259 (unsigned) CGEN_FIELDS_BITSIZE (fields)),
f6e6b40f
BE
260 value);
261
262#endif /* ! CGEN_INT_INSN_P */
263
264 /* ??? It would be better to scan the format's fields.
265 Still need to be able to insert a value based on the operand though;
266 e.g. storing a branch displacement that got resolved later.
267 Needs more thought first. */
268
4a9f416d 269 for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
f6e6b40f
BE
270 {
271 const char *errmsg;
272
273 if (CGEN_SYNTAX_CHAR_P (* syn))
274 continue;
275
276 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
277 fields, buffer, pc);
278 if (errmsg)
279 return errmsg;
280 }
281
282 return NULL;
283}
6bb95a0f 284
0e2ee3ca 285#if CGEN_INT_INSN_P
6bb95a0f
DB
286/* Cover function to store an insn value into an integral insn. Must go here
287 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
288
289static void
10e05405
MM
290put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
291 CGEN_INSN_BYTES_PTR buf,
292 int length,
293 int insn_length,
294 CGEN_INSN_INT value)
6bb95a0f
DB
295{
296 /* For architectures with insns smaller than the base-insn-bitsize,
297 length may be too big. */
298 if (length > insn_length)
299 *buf = value;
300 else
301 {
302 int shift = insn_length - length;
303 /* Written this way to avoid undefined behaviour. */
304 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
305 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
306 }
307}
0e2ee3ca 308#endif
f6e6b40f
BE
309\f
310/* Operand extraction. */
311
312#if ! CGEN_INT_INSN_P
313
314/* Subroutine of extract_normal.
315 Ensure sufficient bytes are cached in EX_INFO.
316 OFFSET is the offset in bytes from the start of the insn of the value.
317 BYTES is the length of the needed value.
318 Returns 1 for success, 0 for failure. */
319
320static CGEN_INLINE int
10e05405
MM
321fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
322 CGEN_EXTRACT_INFO *ex_info,
323 int offset, bytes,
324 bfd_vma pc)
f6e6b40f
BE
325{
326 /* It's doubtful that the middle part has already been fetched so
327 we don't optimize that case. kiss. */
0e2ee3ca 328 unsigned int mask;
f6e6b40f
BE
329 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
330
331 /* First do a quick check. */
332 mask = (1 << bytes) - 1;
333 if (((ex_info->valid >> offset) & mask) == mask)
334 return 1;
335
336 /* Search for the first byte we need to read. */
337 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
338 if (! (mask & ex_info->valid))
339 break;
340
341 if (bytes)
342 {
343 int status;
344
345 pc += offset;
346 status = (*info->read_memory_func)
347 (pc, ex_info->insn_bytes + offset, bytes, info);
348
349 if (status != 0)
350 {
351 (*info->memory_error_func) (status, pc, info);
352 return 0;
353 }
354
355 ex_info->valid |= ((1 << bytes) - 1) << offset;
356 }
357
358 return 1;
359}
360
361/* Subroutine of extract_normal. */
362
363static CGEN_INLINE long
10e05405
MM
364extract_1 (CGEN_CPU_DESC cd,
365 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
366 int start,
367 int length,
368 int word_length,
369 unsigned char *bufp,
370 bfd_vma pc ATTRIBUTE_UNUSED)
f6e6b40f 371{
aed80dae 372 unsigned long x;
f6e6b40f 373 int shift;
0e2ee3ca 374#if 0
f6e6b40f 375 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
0e2ee3ca 376#endif
e333d2c4
NC
377 x = cgen_get_insn_value (cd, bufp, word_length);
378
f6e6b40f
BE
379 if (CGEN_INSN_LSB0_P)
380 shift = (start + 1) - length;
381 else
382 shift = (word_length - (start + length));
aed80dae 383 return x >> shift;
f6e6b40f
BE
384}
385
386#endif /* ! CGEN_INT_INSN_P */
387
388/* Default extraction routine.
389
390 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
391 or sometimes less for cases like the m32r where the base insn size is 32
392 but some insns are 16 bits.
393 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
394 but for generality we take a bitmask of all of them.
395 WORD_OFFSET is the offset in bits from the start of the insn of the value.
396 WORD_LENGTH is the length of the word in bits in which the value resides.
397 START is the starting bit number in the word, architecture origin.
398 LENGTH is the length of VALUE in bits.
399 TOTAL_LENGTH is the total length of the insn in bits.
400
401 Returns 1 for success, 0 for failure. */
402
403/* ??? The return code isn't properly used. wip. */
404
405/* ??? This doesn't handle bfd_vma's. Create another function when
406 necessary. */
407
408static int
10e05405 409extract_normal (CGEN_CPU_DESC cd;
f6e6b40f 410#if ! CGEN_INT_INSN_P
10e05405 411 CGEN_EXTRACT_INFO *ex_info,
f6e6b40f 412#else
10e05405 413 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
f6e6b40f 414#endif
10e05405
MM
415 CGEN_INSN_INT insn_value,
416 unsigned int attrs,
417 unsigned int word_offset,
418 unsigned int start,
419 unsigned int length,
420 unsigned int word_length,
421 unsigned int total_length,
f6e6b40f 422#if ! CGEN_INT_INSN_P
10e05405 423 bfd_vma pc,
f6e6b40f 424#else
10e05405 425 bfd_vma pc ATTRIBUTE_UNUSED,
f6e6b40f 426#endif
10e05405 427 long *valuep)
f6e6b40f 428{
fc7bc883 429 long value, mask;
f6e6b40f
BE
430
431 /* If LENGTH is zero, this operand doesn't contribute to the value
432 so give it a standard value of zero. */
433 if (length == 0)
434 {
435 *valuep = 0;
436 return 1;
437 }
438
6bb95a0f 439#if 0
f6e6b40f
BE
440 if (CGEN_INT_INSN_P
441 && word_offset != 0)
442 abort ();
6bb95a0f 443#endif
f6e6b40f
BE
444
445 if (word_length > 32)
446 abort ();
447
448 /* For architectures with insns smaller than the insn-base-bitsize,
449 word_length may be too big. */
450 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
451 {
452 if (word_offset == 0
453 && word_length > total_length)
454 word_length = total_length;
455 }
456
a00ad97d 457 /* Does the value reside in INSN_VALUE, and at the right alignment? */
f6e6b40f 458
a00ad97d 459 if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
f6e6b40f 460 {
f6e6b40f 461 if (CGEN_INSN_LSB0_P)
6bb95a0f 462 value = insn_value >> ((word_offset + start + 1) - length);
f6e6b40f 463 else
6bb95a0f 464 value = insn_value >> (total_length - ( word_offset + start + length));
f6e6b40f
BE
465 }
466
467#if ! CGEN_INT_INSN_P
468
469 else
470 {
471 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
472
473 if (word_length > 32)
474 abort ();
475
476 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
477 return 0;
478
479 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
480 }
481
482#endif /* ! CGEN_INT_INSN_P */
483
aed80dae
FCE
484 /* Written this way to avoid undefined behaviour. */
485 mask = (((1L << (length - 1)) - 1) << 1) | 1;
486
487 value &= mask;
488 /* sign extend? */
489 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
490 && (value & (1L << (length - 1))))
491 value |= ~mask;
492
f6e6b40f
BE
493 *valuep = value;
494
495 return 1;
496}
497
498/* Default insn extractor.
499
500 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
501 The extracted fields are stored in FIELDS.
502 EX_INFO is used to handle reading variable length insns.
503 Return the length of the insn in bits, or 0 if no match,
504 or -1 if an error occurs fetching data (memory_error_func will have
505 been called). */
506
507static int
10e05405
MM
508extract_insn_normal (CGEN_CPU_DESC cd,
509 const CGEN_INSN *insn,
510 CGEN_EXTRACT_INFO *ex_info,
511 CGEN_INSN_INT insn_value,
512 CGEN_FIELDS *fields,
513 bfd_vma pc)
f6e6b40f
BE
514{
515 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
4a9f416d 516 const CGEN_SYNTAX_CHAR_TYPE *syn;
f6e6b40f
BE
517
518 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
519
520 CGEN_INIT_EXTRACT (cd);
521
522 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
523 {
524 int length;
525
526 if (CGEN_SYNTAX_CHAR_P (*syn))
527 continue;
528
529 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
530 ex_info, insn_value, fields, pc);
531 if (length <= 0)
532 return length;
533 }
534
535 /* We recognized and successfully extracted this insn. */
536 return CGEN_INSN_BITSIZE (insn);
537}
538\f
539/* machine generated code added here */
This page took 0.259178 seconds and 4 git commands to generate.