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