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