1/* CPU data for ip2k.
2
3THIS FILE IS MACHINE GENERATED WITH CGEN.
4
5Copyright 1996-2005 Free Software Foundation, Inc.
6
7This file is part of the GNU Binutils and/or GDB, the GNU debugger.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program; if not, write to the Free Software Foundation, Inc.,
2151 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
22
23*/
24
25#include "sysdep.h"
26#include <stdio.h>
27#include <stdarg.h>
28#include "ansidecl.h"
29#include "bfd.h"
30#include "symcat.h"
31#include "ip2k-desc.h"
32#include "ip2k-opc.h"
33#include "opintl.h"
34#include "libiberty.h"
35#include "xregex.h"
36
37/* Attributes.  */
38
39static const CGEN_ATTR_ENTRY bool_attr[] =
40{
41  { "#f", 0 },
42  { "#t", 1 },
43  { 0, 0 }
44};
45
46static const CGEN_ATTR_ENTRY MACH_attr[] ATTRIBUTE_UNUSED =
47{
48  { "base", MACH_BASE },
49  { "ip2022", MACH_IP2022 },
50  { "ip2022ext", MACH_IP2022EXT },
51  { "max", MACH_MAX },
52  { 0, 0 }
53};
54
55static const CGEN_ATTR_ENTRY ISA_attr[] ATTRIBUTE_UNUSED =
56{
57  { "ip2k", ISA_IP2K },
58  { "max", ISA_MAX },
59  { 0, 0 }
60};
61
62const CGEN_ATTR_TABLE ip2k_cgen_ifield_attr_table[] =
63{
64  { "MACH", & MACH_attr[0], & MACH_attr[0] },
65  { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
66  { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] },
67  { "ABS-ADDR", &bool_attr[0], &bool_attr[0] },
68  { "RESERVED", &bool_attr[0], &bool_attr[0] },
69  { "SIGN-OPT", &bool_attr[0], &bool_attr[0] },
70  { "SIGNED", &bool_attr[0], &bool_attr[0] },
71  { 0, 0, 0 }
72};
73
74const CGEN_ATTR_TABLE ip2k_cgen_hardware_attr_table[] =
75{
76  { "MACH", & MACH_attr[0], & MACH_attr[0] },
77  { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
78  { "CACHE-ADDR", &bool_attr[0], &bool_attr[0] },
79  { "PC", &bool_attr[0], &bool_attr[0] },
80  { "PROFILE", &bool_attr[0], &bool_attr[0] },
81  { 0, 0, 0 }
82};
83
84const CGEN_ATTR_TABLE ip2k_cgen_operand_attr_table[] =
85{
86  { "MACH", & MACH_attr[0], & MACH_attr[0] },
87  { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
88  { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] },
89  { "ABS-ADDR", &bool_attr[0], &bool_attr[0] },
90  { "SIGN-OPT", &bool_attr[0], &bool_attr[0] },
91  { "SIGNED", &bool_attr[0], &bool_attr[0] },
92  { "NEGATIVE", &bool_attr[0], &bool_attr[0] },
93  { "RELAX", &bool_attr[0], &bool_attr[0] },
94  { "SEM-ONLY", &bool_attr[0], &bool_attr[0] },
95  { 0, 0, 0 }
96};
97
98const CGEN_ATTR_TABLE ip2k_cgen_insn_attr_table[] =
99{
100  { "MACH", & MACH_attr[0], & MACH_attr[0] },
101  { "ALIAS", &bool_attr[0], &bool_attr[0] },
102  { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
103  { "UNCOND-CTI", &bool_attr[0], &bool_attr[0] },
104  { "COND-CTI", &bool_attr[0], &bool_attr[0] },
105  { "SKIP-CTI", &bool_attr[0], &bool_attr[0] },
106  { "DELAY-SLOT", &bool_attr[0], &bool_attr[0] },
107  { "RELAXABLE", &bool_attr[0], &bool_attr[0] },
108  { "RELAXED", &bool_attr[0], &bool_attr[0] },
109  { "NO-DIS", &bool_attr[0], &bool_attr[0] },
110  { "PBB", &bool_attr[0], &bool_attr[0] },
111  { "EXT-SKIP-INSN", &bool_attr[0], &bool_attr[0] },
112  { "SKIPA", &bool_attr[0], &bool_attr[0] },
113  { 0, 0, 0 }
114};
115
116/* Instruction set variants.  */
117
118static const CGEN_ISA ip2k_cgen_isa_table[] = {
119  { "ip2k", 16, 16, 16, 16 },
120  { 0, 0, 0, 0, 0 }
121};
122
123/* Machine variants.  */
124
125static const CGEN_MACH ip2k_cgen_mach_table[] = {
126  { "ip2022", "ip2022", MACH_IP2022, 0 },
127  { "ip2022ext", "ip2022ext", MACH_IP2022EXT, 0 },
128  { 0, 0, 0, 0 }
129};
130
131static CGEN_KEYWORD_ENTRY ip2k_cgen_opval_register_names_entries[] =
132{
133  { "ADDRSEL", 2, {0, {{{0, 0}}}}, 0, 0 },
134  { "ADDRX", 3, {0, {{{0, 0}}}}, 0, 0 },
135  { "IPH", 4, {0, {{{0, 0}}}}, 0, 0 },
136  { "IPL", 5, {0, {{{0, 0}}}}, 0, 0 },
137  { "SPH", 6, {0, {{{0, 0}}}}, 0, 0 },
138  { "SPL", 7, {0, {{{0, 0}}}}, 0, 0 },
139  { "PCH", 8, {0, {{{0, 0}}}}, 0, 0 },
140  { "PCL", 9, {0, {{{0, 0}}}}, 0, 0 },
141  { "WREG", 10, {0, {{{0, 0}}}}, 0, 0 },
142  { "STATUS", 11, {0, {{{0, 0}}}}, 0, 0 },
143  { "DPH", 12, {0, {{{0, 0}}}}, 0, 0 },
144  { "DPL", 13, {0, {{{0, 0}}}}, 0, 0 },
145  { "SPDREG", 14, {0, {{{0, 0}}}}, 0, 0 },
146  { "MULH", 15, {0, {{{0, 0}}}}, 0, 0 },
147  { "ADDRH", 16, {0, {{{0, 0}}}}, 0, 0 },
148  { "ADDRL", 17, {0, {{{0, 0}}}}, 0, 0 },
149  { "DATAH", 18, {0, {{{0, 0}}}}, 0, 0 },
150  { "DATAL", 19, {0, {{{0, 0}}}}, 0, 0 },
151  { "INTVECH", 20, {0, {{{0, 0}}}}, 0, 0 },
152  { "INTVECL", 21, {0, {{{0, 0}}}}, 0, 0 },
153  { "INTSPD", 22, {0, {{{0, 0}}}}, 0, 0 },
154  { "INTF", 23, {0, {{{0, 0}}}}, 0, 0 },
155  { "INTE", 24, {0, {{{0, 0}}}}, 0, 0 },
156  { "INTED", 25, {0, {{{0, 0}}}}, 0, 0 },
157  { "FCFG", 26, {0, {{{0, 0}}}}, 0, 0 },
158  { "TCTRL", 27, {0, {{{0, 0}}}}, 0, 0 },
159  { "XCFG", 28, {0, {{{0, 0}}}}, 0, 0 },
160  { "EMCFG", 29, {0, {{{0, 0}}}}, 0, 0 },
161  { "IPCH", 30, {0, {{{0, 0}}}}, 0, 0 },
162  { "IPCL", 31, {0, {{{0, 0}}}}, 0, 0 },
163  { "RAIN", 32, {0, {{{0, 0}}}}, 0, 0 },
164  { "RAOUT", 33, {0, {{{0, 0}}}}, 0, 0 },
165  { "RADIR", 34, {0, {{{0, 0}}}}, 0, 0 },
166  { "LFSRH", 35, {0, {{{0, 0}}}}, 0, 0 },
167  { "RBIN", 36, {0, {{{0, 0}}}}, 0, 0 },
168  { "RBOUT", 37, {0, {{{0, 0}}}}, 0, 0 },
169  { "RBDIR", 38, {0, {{{0, 0}}}}, 0, 0 },
170  { "LFSRL", 39, {0, {{{0, 0}}}}, 0, 0 },
171  { "RCIN", 40, {0, {{{0, 0}}}}, 0, 0 },
172  { "RCOUT", 41, {0, {{{0, 0}}}}, 0, 0 },
173  { "RCDIR", 42, {0, {{{0, 0}}}}, 0, 0 },
174  { "LFSRA", 43, {0, {{{0, 0}}}}, 0, 0 },
175  { "RDIN", 44, {0, {{{0, 0}}}}, 0, 0 },
176  { "RDOUT", 45, {0, {{{0, 0}}}}, 0, 0 },
177  { "RDDIR", 46, {0, {{{0, 0}}}}, 0, 0 },
178  { "REIN", 48, {0, {{{0, 0}}}}, 0, 0 },
179  { "REOUT", 49, {0, {{{0, 0}}}}, 0, 0 },
180  { "REDIR", 50, {0, {{{0, 0}}}}, 0, 0 },
181  { "RFIN", 52, {0, {{{0, 0}}}}, 0, 0 },
182  { "RFOUT", 53, {0, {{{0, 0}}}}, 0, 0 },
183  { "RFDIR", 54, {0, {{{0, 0}}}}, 0, 0 },
184  { "RGOUT", 57, {0, {{{0, 0}}}}, 0, 0 },
185  { "RGDIR", 58, {0, {{{0, 0}}}}, 0, 0 },
186  { "RTTMR", 64, {0, {{{0, 0}}}}, 0, 0 },
187  { "RTCFG", 65, {0, {{{0, 0}}}}, 0, 0 },
188  { "T0TMR", 66, {0, {{{0, 0}}}}, 0, 0 },
189  { "T0CFG", 67, {0, {{{0, 0}}}}, 0, 0 },
190  { "T1CNTH", 68, {0, {{{0, 0}}}}, 0, 0 },
191  { "T1CNTL", 69, {0, {{{0, 0}}}}, 0, 0 },
192  { "T1CAP1H", 70, {0, {{{0, 0}}}}, 0, 0 },
193  { "T1CAP1L", 71, {0, {{{0, 0}}}}, 0, 0 },
194  { "T1CAP2H", 72, {0, {{{0, 0}}}}, 0, 0 },
195  { "T1CMP2H", 72, {0, {{{0, 0}}}}, 0, 0 },
196  { "T1CAP2L", 73, {0, {{{0, 0}}}}, 0, 0 },
197  { "T1CMP2L", 73, {0, {{{0, 0}}}}, 0, 0 },
198  { "T1CMP1H", 74, {0, {{{0, 0}}}}, 0, 0 },
199  { "T1CMP1L", 75, {0, {{{0, 0}}}}, 0, 0 },
200  { "T1CFG1H", 76, {0, {{{0, 0}}}}, 0, 0 },
201  { "T1CFG1L", 77, {0, {{{0, 0}}}}, 0, 0 },
202  { "T1CFG2H", 78, {0, {{{0, 0}}}}, 0, 0 },
203  { "T1CFG2L", 79, {0, {{{0, 0}}}}, 0, 0 },
204  { "ADCH", 80, {0, {{{0, 0}}}}, 0, 0 },
205  { "ADCL", 81, {0, {{{0, 0}}}}, 0, 0 },
206  { "ADCCFG", 82, {0, {{{0, 0}}}}, 0, 0 },
207  { "ADCTMR", 83, {0, {{{0, 0}}}}, 0, 0 },
208  { "T2CNTH", 84, {0, {{{0, 0}}}}, 0, 0 },
209  { "T2CNTL", 85, {0, {{{0, 0}}}}, 0, 0 },
210  { "T2CAP1H", 86, {0, {{{0, 0}}}}, 0, 0 },
211  { "T2CAP1L", 87, {0, {{{0, 0}}}}, 0, 0 },
212  { "T2CAP2H", 88, {0, {{{0, 0}}}}, 0, 0 },
213  { "T2CMP2H", 88, {0, {{{0, 0}}}}, 0, 0 },
214  { "T2CAP2L", 89, {0, {{{0, 0}}}}, 0, 0 },
215  { "T2CMP2L", 89, {0, {{{0, 0}}}}, 0, 0 },
216  { "T2CMP1H", 90, {0, {{{0, 0}}}}, 0, 0 },
217  { "T2CMP1L", 91, {0, {{{0, 0}}}}, 0, 0 },
218  { "T2CFG1H", 92, {0, {{{0, 0}}}}, 0, 0 },
219  { "T2CFG1L", 93, {0, {{{0, 0}}}}, 0, 0 },
220  { "T2CFG2H", 94, {0, {{{0, 0}}}}, 0, 0 },
221  { "T2CFG2L", 95, {0, {{{0, 0}}}}, 0, 0 },
222  { "S1TMRH", 96, {0, {{{0, 0}}}}, 0, 0 },
223  { "S1TMRL", 97, {0, {{{0, 0}}}}, 0, 0 },
224  { "S1TBUFH", 98, {0, {{{0, 0}}}}, 0, 0 },
225  { "S1TBUFL", 99, {0, {{{0, 0}}}}, 0, 0 },
226  { "S1TCFG", 100, {0, {{{0, 0}}}}, 0, 0 },
227  { "S1RCNT", 101, {0, {{{0, 0}}}}, 0, 0 },
228  { "S1RBUFH", 102, {0, {{{0, 0}}}}, 0, 0 },
229  { "S1RBUFL", 103, {0, {{{0, 0}}}}, 0, 0 },
230  { "S1RCFG", 104, {0, {{{0, 0}}}}, 0, 0 },
231  { "S1RSYNC", 105, {0, {{{0, 0}}}}, 0, 0 },
232  { "S1INTF", 106, {0, {{{0, 0}}}}, 0, 0 },
233  { "S1INTE", 107, {0, {{{0, 0}}}}, 0, 0 },
234  { "S1MODE", 108, {0, {{{0, 0}}}}, 0, 0 },
235  { "S1SMASK", 109, {0, {{{0, 0}}}}, 0, 0 },
236  { "PSPCFG", 110, {0, {{{0, 0}}}}, 0, 0 },
237  { "CMPCFG", 111, {0, {{{0, 0}}}}, 0, 0 },
238  { "S2TMRH", 112, {0, {{{0, 0}}}}, 0, 0 },
239  { "S2TMRL", 113, {0, {{{0, 0}}}}, 0, 0 },
240  { "S2TBUFH", 114, {0, {{{0, 0}}}}, 0, 0 },
241  { "S2TBUFL", 115, {0, {{{0, 0}}}}, 0, 0 },
242  { "S2TCFG", 116, {0, {{{0, 0}}}}, 0, 0 },
243  { "S2RCNT", 117, {0, {{{0, 0}}}}, 0, 0 },
244  { "S2RBUFH", 118, {0, {{{0, 0}}}}, 0, 0 },
245  { "S2RBUFL", 119, {0, {{{0, 0}}}}, 0, 0 },
246  { "S2RCFG", 120, {0, {{{0, 0}}}}, 0, 0 },
247  { "S2RSYNC", 121, {0, {{{0, 0}}}}, 0, 0 },
248  { "S2INTF", 122, {0, {{{0, 0}}}}, 0, 0 },
249  { "S2INTE", 123, {0, {{{0, 0}}}}, 0, 0 },
250  { "S2MODE", 124, {0, {{{0, 0}}}}, 0, 0 },
251  { "S2SMASK", 125, {0, {{{0, 0}}}}, 0, 0 },
252  { "CALLH", 126, {0, {{{0, 0}}}}, 0, 0 },
253  { "CALLL", 127, {0, {{{0, 0}}}}, 0, 0 }
254};
255
256CGEN_KEYWORD ip2k_cgen_opval_register_names =
257{
258  & ip2k_cgen_opval_register_names_entries[0],
259  121,
260  0, 0, 0, 0, ""
261};
262
263
264/* The hardware table.  */
265
266#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
267#define A(a) (1 << CGEN_HW_##a)
268#else
269#define A(a) (1 << CGEN_HW_/**/a)
270#endif
271
272const CGEN_HW_ENTRY ip2k_cgen_hw_table[] =
273{
274  { "h-memory", HW_H_MEMORY, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
275  { "h-sint", HW_H_SINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
276  { "h-uint", HW_H_UINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
277  { "h-addr", HW_H_ADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
278  { "h-iaddr", HW_H_IADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
279  { "h-spr", HW_H_SPR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
280  { "h-registers", HW_H_REGISTERS, CGEN_ASM_NONE, 0, { 0|A(VIRTUAL), { { { (1<<MACH_BASE), 0 } } } } },
281  { "h-stack", HW_H_STACK, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
282  { "h-pabits", HW_H_PABITS, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
283  { "h-zbit", HW_H_ZBIT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
284  { "h-cbit", HW_H_CBIT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
285  { "h-dcbit", HW_H_DCBIT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
286  { "h-pc", HW_H_PC, CGEN_ASM_NONE, 0, { 0|A(PROFILE)|A(PC), { { { (1<<MACH_BASE), 0 } } } } },
287  { 0, 0, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } }
288};
289
290#undef A
291
292
293/* The instruction field table.  */
294
295#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
296#define A(a) (1 << CGEN_IFLD_##a)
297#else
298#define A(a) (1 << CGEN_IFLD_/**/a)
299#endif
300
301const CGEN_IFLD ip2k_cgen_ifld_table[] =
302{
303  { IP2K_F_NIL, "f-nil", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
304  { IP2K_F_ANYOF, "f-anyof", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
305  { IP2K_F_IMM8, "f-imm8", 0, 16, 7, 8, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
306  { IP2K_F_REG, "f-reg", 0, 16, 8, 9, { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
307  { IP2K_F_ADDR16CJP, "f-addr16cjp", 0, 16, 12, 13, { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
308  { IP2K_F_DIR, "f-dir", 0, 16, 9, 1, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
309  { IP2K_F_BITNO, "f-bitno", 0, 16, 11, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
310  { IP2K_F_OP3, "f-op3", 0, 16, 15, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
311  { IP2K_F_OP4, "f-op4", 0, 16, 15, 4, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
312  { IP2K_F_OP4MID, "f-op4mid", 0, 16, 11, 4, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
313  { IP2K_F_OP6, "f-op6", 0, 16, 15, 6, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
314  { IP2K_F_OP8, "f-op8", 0, 16, 15, 8, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
315  { IP2K_F_OP6_10LOW, "f-op6-10low", 0, 16, 9, 10, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
316  { IP2K_F_OP6_7LOW, "f-op6-7low", 0, 16, 9, 7, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
317  { IP2K_F_RETI3, "f-reti3", 0, 16, 2, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
318  { IP2K_F_SKIPB, "f-skipb", 0, 16, 12, 1, { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
319  { IP2K_F_PAGE3, "f-page3", 0, 16, 2, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
320  { 0, 0, 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } }
321};
322
323#undef A
324
325
326
327/* multi ifield declarations */
328
329
330
331/* multi ifield definitions */
332
333
334/* The operand table.  */
335
336#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
337#define A(a) (1 << CGEN_OPERAND_##a)
338#else
339#define A(a) (1 << CGEN_OPERAND_/**/a)
340#endif
341#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
342#define OPERAND(op) IP2K_OPERAND_##op
343#else
344#define OPERAND(op) IP2K_OPERAND_/**/op
345#endif
346
347const CGEN_OPERAND ip2k_cgen_operand_table[] =
348{
349/* pc: program counter */
350  { "pc", IP2K_OPERAND_PC, HW_H_PC, 0, 0,
351    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_NIL] } },
352    { 0|A(SEM_ONLY), { { { (1<<MACH_BASE), 0 } } } }  },
353/* addr16cjp: 13-bit address */
354  { "addr16cjp", IP2K_OPERAND_ADDR16CJP, HW_H_UINT, 12, 13,
355    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_ADDR16CJP] } },
356    { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
357/* fr: register */
358  { "fr", IP2K_OPERAND_FR, HW_H_REGISTERS, 8, 9,
359    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_REG] } },
360    { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
361/* lit8: 8-bit signed literal */
362  { "lit8", IP2K_OPERAND_LIT8, HW_H_SINT, 7, 8,
363    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_IMM8] } },
364    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
365/* bitno: bit number */
366  { "bitno", IP2K_OPERAND_BITNO, HW_H_UINT, 11, 3,
367    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_BITNO] } },
368    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
369/* addr16p: page number */
370  { "addr16p", IP2K_OPERAND_ADDR16P, HW_H_UINT, 2, 3,
371    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_PAGE3] } },
372    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
373/* addr16h: high 8 bits of address */
374  { "addr16h", IP2K_OPERAND_ADDR16H, HW_H_UINT, 7, 8,
375    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_IMM8] } },
376    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
377/* addr16l: low 8 bits of address */
378  { "addr16l", IP2K_OPERAND_ADDR16L, HW_H_UINT, 7, 8,
379    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_IMM8] } },
380    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
381/* reti3: reti flags */
382  { "reti3", IP2K_OPERAND_RETI3, HW_H_UINT, 2, 3,
383    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_RETI3] } },
384    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
385/* pabits: page bits */
386  { "pabits", IP2K_OPERAND_PABITS, HW_H_PABITS, 0, 0,
387    { 0, { (const PTR) 0 } },
388    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
389/* zbit: zero bit */
390  { "zbit", IP2K_OPERAND_ZBIT, HW_H_ZBIT, 0, 0,
391    { 0, { (const PTR) 0 } },
392    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
393/* cbit: carry bit */
394  { "cbit", IP2K_OPERAND_CBIT, HW_H_CBIT, 0, 0,
395    { 0, { (const PTR) 0 } },
396    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
397/* dcbit: digit carry bit */
398  { "dcbit", IP2K_OPERAND_DCBIT, HW_H_DCBIT, 0, 0,
399    { 0, { (const PTR) 0 } },
400    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
401/* sentinel */
402  { 0, 0, 0, 0, 0,
403    { 0, { (const PTR) 0 } },
404    { 0, { { { (1<<MACH_BASE), 0 } } } } }
405};
406
407#undef A
408
409
410/* The instruction table.  */
411
412#define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
413#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
414#define A(a) (1 << CGEN_INSN_##a)
415#else
416#define A(a) (1 << CGEN_INSN_/**/a)
417#endif
418
419static const CGEN_IBASE ip2k_cgen_insn_table[MAX_INSNS] =
420{
421  /* Special null first entry.
422     A `num' value of zero is thus invalid.
423     Also, the special `invalid' insn resides here.  */
424  { 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
425/* jmp $addr16cjp */
426  {
427    IP2K_INSN_JMP, "jmp", "jmp", 16,
428    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
429  },
430/* call $addr16cjp */
431  {
432    IP2K_INSN_CALL, "call", "call", 16,
433    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
434  },
435/* sb $fr,$bitno */
436  {
437    IP2K_INSN_SB, "sb", "sb", 16,
438    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
439  },
440/* snb $fr,$bitno */
441  {
442    IP2K_INSN_SNB, "snb", "snb", 16,
443    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
444  },
445/* setb $fr,$bitno */
446  {
447    IP2K_INSN_SETB, "setb", "setb", 16,
448    { 0, { { { (1<<MACH_BASE), 0 } } } }
449  },
450/* clrb $fr,$bitno */
451  {
452    IP2K_INSN_CLRB, "clrb", "clrb", 16,
453    { 0, { { { (1<<MACH_BASE), 0 } } } }
454  },
455/* xor W,#$lit8 */
456  {
457    IP2K_INSN_XORW_L, "xorw_l", "xor", 16,
458    { 0, { { { (1<<MACH_BASE), 0 } } } }
459  },
460/* and W,#$lit8 */
461  {
462    IP2K_INSN_ANDW_L, "andw_l", "and", 16,
463    { 0, { { { (1<<MACH_BASE), 0 } } } }
464  },
465/* or W,#$lit8 */
466  {
467    IP2K_INSN_ORW_L, "orw_l", "or", 16,
468    { 0, { { { (1<<MACH_BASE), 0 } } } }
469  },
470/* add W,#$lit8 */
471  {
472    IP2K_INSN_ADDW_L, "addw_l", "add", 16,
473    { 0, { { { (1<<MACH_BASE), 0 } } } }
474  },
475/* sub W,#$lit8 */
476  {
477    IP2K_INSN_SUBW_L, "subw_l", "sub", 16,
478    { 0, { { { (1<<MACH_BASE), 0 } } } }
479  },
480/* cmp W,#$lit8 */
481  {
482    IP2K_INSN_CMPW_L, "cmpw_l", "cmp", 16,
483    { 0, { { { (1<<MACH_BASE), 0 } } } }
484  },
485/* retw #$lit8 */
486  {
487    IP2K_INSN_RETW_L, "retw_l", "retw", 16,
488    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
489  },
490/* cse W,#$lit8 */
491  {
492    IP2K_INSN_CSEW_L, "csew_l", "cse", 16,
493    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
494  },
495/* csne W,#$lit8 */
496  {
497    IP2K_INSN_CSNEW_L, "csnew_l", "csne", 16,
498    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
499  },
500/* push #$lit8 */
501  {
502    IP2K_INSN_PUSH_L, "push_l", "push", 16,
503    { 0, { { { (1<<MACH_BASE), 0 } } } }
504  },
505/* muls W,#$lit8 */
506  {
507    IP2K_INSN_MULSW_L, "mulsw_l", "muls", 16,
508    { 0, { { { (1<<MACH_BASE), 0 } } } }
509  },
510/* mulu W,#$lit8 */
511  {
512    IP2K_INSN_MULUW_L, "muluw_l", "mulu", 16,
513    { 0, { { { (1<<MACH_BASE), 0 } } } }
514  },
515/* loadl #$lit8 */
516  {
517    IP2K_INSN_LOADL_L, "loadl_l", "loadl", 16,
518    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
519  },
520/* loadh #$lit8 */
521  {
522    IP2K_INSN_LOADH_L, "loadh_l", "loadh", 16,
523    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
524  },
525/* loadl $addr16l */
526  {
527    IP2K_INSN_LOADL_A, "loadl_a", "loadl", 16,
528    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
529  },
530/* loadh $addr16h */
531  {
532    IP2K_INSN_LOADH_A, "loadh_a", "loadh", 16,
533    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
534  },
535/* addc $fr,W */
536  {
537    IP2K_INSN_ADDCFR_W, "addcfr_w", "addc", 16,
538    { 0, { { { (1<<MACH_BASE), 0 } } } }
539  },
540/* addc W,$fr */
541  {
542    IP2K_INSN_ADDCW_FR, "addcw_fr", "addc", 16,
543    { 0, { { { (1<<MACH_BASE), 0 } } } }
544  },
545/* incsnz $fr */
546  {
547    IP2K_INSN_INCSNZ_FR, "incsnz_fr", "incsnz", 16,
548    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
549  },
550/* incsnz W,$fr */
551  {
552    IP2K_INSN_INCSNZW_FR, "incsnzw_fr", "incsnz", 16,
553    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
554  },
555/* muls W,$fr */
556  {
557    IP2K_INSN_MULSW_FR, "mulsw_fr", "muls", 16,
558    { 0, { { { (1<<MACH_BASE), 0 } } } }
559  },
560/* mulu W,$fr */
561  {
562    IP2K_INSN_MULUW_FR, "muluw_fr", "mulu", 16,
563    { 0, { { { (1<<MACH_BASE), 0 } } } }
564  },
565/* decsnz $fr */
566  {
567    IP2K_INSN_DECSNZ_FR, "decsnz_fr", "decsnz", 16,
568    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
569  },
570/* decsnz W,$fr */
571  {
572    IP2K_INSN_DECSNZW_FR, "decsnzw_fr", "decsnz", 16,
573    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
574  },
575/* subc W,$fr */
576  {
577    IP2K_INSN_SUBCW_FR, "subcw_fr", "subc", 16,
578    { 0, { { { (1<<MACH_BASE), 0 } } } }
579  },
580/* subc $fr,W */
581  {
582    IP2K_INSN_SUBCFR_W, "subcfr_w", "subc", 16,
583    { 0, { { { (1<<MACH_BASE), 0 } } } }
584  },
585/* pop $fr */
586  {
587    IP2K_INSN_POP_FR, "pop_fr", "pop", 16,
588    { 0, { { { (1<<MACH_BASE), 0 } } } }
589  },
590/* push $fr */
591  {
592    IP2K_INSN_PUSH_FR, "push_fr", "push", 16,
593    { 0, { { { (1<<MACH_BASE), 0 } } } }
594  },
595/* cse W,$fr */
596  {
597    IP2K_INSN_CSEW_FR, "csew_fr", "cse", 16,
598    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
599  },
600/* csne W,$fr */
601  {
602    IP2K_INSN_CSNEW_FR, "csnew_fr", "csne", 16,
603    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
604  },
605/* incsz $fr */
606  {
607    IP2K_INSN_INCSZ_FR, "incsz_fr", "incsz", 16,
608    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
609  },
610/* incsz W,$fr */
611  {
612    IP2K_INSN_INCSZW_FR, "incszw_fr", "incsz", 16,
613    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
614  },
615/* swap $fr */
616  {
617    IP2K_INSN_SWAP_FR, "swap_fr", "swap", 16,
618    { 0, { { { (1<<MACH_BASE), 0 } } } }
619  },
620/* swap W,$fr */
621  {
622    IP2K_INSN_SWAPW_FR, "swapw_fr", "swap", 16,
623    { 0, { { { (1<<MACH_BASE), 0 } } } }
624  },
625/* rl $fr */
626  {
627    IP2K_INSN_RL_FR, "rl_fr", "rl", 16,
628    { 0, { { { (1<<MACH_BASE), 0 } } } }
629  },
630/* rl W,$fr */
631  {
632    IP2K_INSN_RLW_FR, "rlw_fr", "rl", 16,
633    { 0, { { { (1<<MACH_BASE), 0 } } } }
634  },
635/* rr $fr */
636  {
637    IP2K_INSN_RR_FR, "rr_fr", "rr", 16,
638    { 0, { { { (1<<MACH_BASE), 0 } } } }
639  },
640/* rr W,$fr */
641  {
642    IP2K_INSN_RRW_FR, "rrw_fr", "rr", 16,
643    { 0, { { { (1<<MACH_BASE), 0 } } } }
644  },
645/* decsz $fr */
646  {
647    IP2K_INSN_DECSZ_FR, "decsz_fr", "decsz", 16,
648    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
649  },
650/* decsz W,$fr */
651  {
652    IP2K_INSN_DECSZW_FR, "decszw_fr", "decsz", 16,
653    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
654  },
655/* inc $fr */
656  {
657    IP2K_INSN_INC_FR, "inc_fr", "inc", 16,
658    { 0, { { { (1<<MACH_BASE), 0 } } } }
659  },
660/* inc W,$fr */
661  {
662    IP2K_INSN_INCW_FR, "incw_fr", "inc", 16,
663    { 0, { { { (1<<MACH_BASE), 0 } } } }
664  },
665/* not $fr */
666  {
667    IP2K_INSN_NOT_FR, "not_fr", "not", 16,
668    { 0, { { { (1<<MACH_BASE), 0 } } } }
669  },
670/* not W,$fr */
671  {
672    IP2K_INSN_NOTW_FR, "notw_fr", "not", 16,
673    { 0, { { { (1<<MACH_BASE), 0 } } } }
674  },
675/* test $fr */
676  {
677    IP2K_INSN_TEST_FR, "test_fr", "test", 16,
678    { 0, { { { (1<<MACH_BASE), 0 } } } }
679  },
680/* mov W,#$lit8 */
681  {
682    IP2K_INSN_MOVW_L, "movw_l", "mov", 16,
683    { 0, { { { (1<<MACH_BASE), 0 } } } }
684  },
685/* mov $fr,W */
686  {
687    IP2K_INSN_MOVFR_W, "movfr_w", "mov", 16,
688    { 0, { { { (1<<MACH_BASE), 0 } } } }
689  },
690/* mov W,$fr */
691  {
692    IP2K_INSN_MOVW_FR, "movw_fr", "mov", 16,
693    { 0, { { { (1<<MACH_BASE), 0 } } } }
694  },
695/* add $fr,W */
696  {
697    IP2K_INSN_ADDFR_W, "addfr_w", "add", 16,
698    { 0, { { { (1<<MACH_BASE), 0 } } } }
699  },
700/* add W,$fr */
701  {
702    IP2K_INSN_ADDW_FR, "addw_fr", "add", 16,
703    { 0, { { { (1<<MACH_BASE), 0 } } } }
704  },
705/* xor $fr,W */
706  {
707    IP2K_INSN_XORFR_W, "xorfr_w", "xor", 16,
708    { 0, { { { (1<<MACH_BASE), 0 } } } }
709  },
710/* xor W,$fr */
711  {
712    IP2K_INSN_XORW_FR, "xorw_fr", "xor", 16,
713    { 0, { { { (1<<MACH_BASE), 0 } } } }
714  },
715/* and $fr,W */
716  {
717    IP2K_INSN_ANDFR_W, "andfr_w", "and", 16,
718    { 0, { { { (1<<MACH_BASE), 0 } } } }
719  },
720/* and W,$fr */
721  {
722    IP2K_INSN_ANDW_FR, "andw_fr", "and", 16,
723    { 0, { { { (1<<MACH_BASE), 0 } } } }
724  },
725/* or $fr,W */
726  {
727    IP2K_INSN_ORFR_W, "orfr_w", "or", 16,
728    { 0, { { { (1<<MACH_BASE), 0 } } } }
729  },
730/* or W,$fr */
731  {
732    IP2K_INSN_ORW_FR, "orw_fr", "or", 16,
733    { 0, { { { (1<<MACH_BASE), 0 } } } }
734  },
735/* dec $fr */
736  {
737    IP2K_INSN_DEC_FR, "dec_fr", "dec", 16,
738    { 0, { { { (1<<MACH_BASE), 0 } } } }
739  },
740/* dec W,$fr */
741  {
742    IP2K_INSN_DECW_FR, "decw_fr", "dec", 16,
743    { 0, { { { (1<<MACH_BASE), 0 } } } }
744  },
745/* sub $fr,W */
746  {
747    IP2K_INSN_SUBFR_W, "subfr_w", "sub", 16,
748    { 0, { { { (1<<MACH_BASE), 0 } } } }
749  },
750/* sub W,$fr */
751  {
752    IP2K_INSN_SUBW_FR, "subw_fr", "sub", 16,
753    { 0, { { { (1<<MACH_BASE), 0 } } } }
754  },
755/* clr $fr */
756  {
757    IP2K_INSN_CLR_FR, "clr_fr", "clr", 16,
758    { 0, { { { (1<<MACH_BASE), 0 } } } }
759  },
760/* cmp W,$fr */
761  {
762    IP2K_INSN_CMPW_FR, "cmpw_fr", "cmp", 16,
763    { 0, { { { (1<<MACH_BASE), 0 } } } }
764  },
765/* speed #$lit8 */
766  {
767    IP2K_INSN_SPEED, "speed", "speed", 16,
768    { 0, { { { (1<<MACH_BASE), 0 } } } }
769  },
770/* ireadi */
771  {
772    IP2K_INSN_IREADI, "ireadi", "ireadi", 16,
773    { 0, { { { (1<<MACH_BASE), 0 } } } }
774  },
775/* iwritei */
776  {
777    IP2K_INSN_IWRITEI, "iwritei", "iwritei", 16,
778    { 0, { { { (1<<MACH_BASE), 0 } } } }
779  },
780/* fread */
781  {
782    IP2K_INSN_FREAD, "fread", "fread", 16,
783    { 0, { { { (1<<MACH_BASE), 0 } } } }
784  },
785/* fwrite */
786  {
787    IP2K_INSN_FWRITE, "fwrite", "fwrite", 16,
788    { 0, { { { (1<<MACH_BASE), 0 } } } }
789  },
790/* iread */
791  {
792    IP2K_INSN_IREAD, "iread", "iread", 16,
793    { 0, { { { (1<<MACH_BASE), 0 } } } }
794  },
795/* iwrite */
796  {
797    IP2K_INSN_IWRITE, "iwrite", "iwrite", 16,
798    { 0, { { { (1<<MACH_BASE), 0 } } } }
799  },
800/* page $addr16p */
801  {
802    IP2K_INSN_PAGE, "page", "page", 16,
803    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
804  },
805/* system */
806  {
807    IP2K_INSN_SYSTEM, "system", "system", 16,
808    { 0, { { { (1<<MACH_BASE), 0 } } } }
809  },
810/* reti #$reti3 */
811  {
812    IP2K_INSN_RETI, "reti", "reti", 16,
813    { 0, { { { (1<<MACH_BASE), 0 } } } }
814  },
815/* ret */
816  {
817    IP2K_INSN_RET, "ret", "ret", 16,
818    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
819  },
820/* int */
821  {
822    IP2K_INSN_INT, "int", "int", 16,
823    { 0, { { { (1<<MACH_BASE), 0 } } } }
824  },
825/* breakx */
826  {
827    IP2K_INSN_BREAKX, "breakx", "breakx", 16,
828    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
829  },
830/* cwdt */
831  {
832    IP2K_INSN_CWDT, "cwdt", "cwdt", 16,
833    { 0, { { { (1<<MACH_BASE), 0 } } } }
834  },
835/* ferase */
836  {
837    IP2K_INSN_FERASE, "ferase", "ferase", 16,
838    { 0, { { { (1<<MACH_BASE), 0 } } } }
839  },
840/* retnp */
841  {
842    IP2K_INSN_RETNP, "retnp", "retnp", 16,
843    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
844  },
845/* break */
846  {
847    IP2K_INSN_BREAK, "break", "break", 16,
848    { 0, { { { (1<<MACH_BASE), 0 } } } }
849  },
850/* nop */
851  {
852    IP2K_INSN_NOP, "nop", "nop", 16,
853    { 0, { { { (1<<MACH_BASE), 0 } } } }
854  },
855};
856
857#undef OP
858#undef A
859
860/* Initialize anything needed to be done once, before any cpu_open call.  */
861
862static void
863init_tables (void)
864{
865}
866
867static const CGEN_MACH * lookup_mach_via_bfd_name (const CGEN_MACH *, const char *);
868static void build_hw_table      (CGEN_CPU_TABLE *);
869static void build_ifield_table  (CGEN_CPU_TABLE *);
870static void build_operand_table (CGEN_CPU_TABLE *);
871static void build_insn_table    (CGEN_CPU_TABLE *);
872static void ip2k_cgen_rebuild_tables (CGEN_CPU_TABLE *);
873
874/* Subroutine of ip2k_cgen_cpu_open to look up a mach via its bfd name.  */
875
876static const CGEN_MACH *
877lookup_mach_via_bfd_name (const CGEN_MACH *table, const char *name)
878{
879  while (table->name)
880    {
881      if (strcmp (name, table->bfd_name) == 0)
882	return table;
883      ++table;
884    }
885  abort ();
886}
887
888/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.  */
889
890static void
891build_hw_table (CGEN_CPU_TABLE *cd)
892{
893  int i;
894  int machs = cd->machs;
895  const CGEN_HW_ENTRY *init = & ip2k_cgen_hw_table[0];
896  /* MAX_HW is only an upper bound on the number of selected entries.
897     However each entry is indexed by it's enum so there can be holes in
898     the table.  */
899  const CGEN_HW_ENTRY **selected =
900    (const CGEN_HW_ENTRY **) xmalloc (MAX_HW * sizeof (CGEN_HW_ENTRY *));
901
902  cd->hw_table.init_entries = init;
903  cd->hw_table.entry_size = sizeof (CGEN_HW_ENTRY);
904  memset (selected, 0, MAX_HW * sizeof (CGEN_HW_ENTRY *));
905  /* ??? For now we just use machs to determine which ones we want.  */
906  for (i = 0; init[i].name != NULL; ++i)
907    if (CGEN_HW_ATTR_VALUE (&init[i], CGEN_HW_MACH)
908	& machs)
909      selected[init[i].type] = &init[i];
910  cd->hw_table.entries = selected;
911  cd->hw_table.num_entries = MAX_HW;
912}
913
914/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.  */
915
916static void
917build_ifield_table (CGEN_CPU_TABLE *cd)
918{
919  cd->ifld_table = & ip2k_cgen_ifld_table[0];
920}
921
922/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.  */
923
924static void
925build_operand_table (CGEN_CPU_TABLE *cd)
926{
927  int i;
928  int machs = cd->machs;
929  const CGEN_OPERAND *init = & ip2k_cgen_operand_table[0];
930  /* MAX_OPERANDS is only an upper bound on the number of selected entries.
931     However each entry is indexed by it's enum so there can be holes in
932     the table.  */
933  const CGEN_OPERAND **selected = xmalloc (MAX_OPERANDS * sizeof (* selected));
934
935  cd->operand_table.init_entries = init;
936  cd->operand_table.entry_size = sizeof (CGEN_OPERAND);
937  memset (selected, 0, MAX_OPERANDS * sizeof (CGEN_OPERAND *));
938  /* ??? For now we just use mach to determine which ones we want.  */
939  for (i = 0; init[i].name != NULL; ++i)
940    if (CGEN_OPERAND_ATTR_VALUE (&init[i], CGEN_OPERAND_MACH)
941	& machs)
942      selected[init[i].type] = &init[i];
943  cd->operand_table.entries = selected;
944  cd->operand_table.num_entries = MAX_OPERANDS;
945}
946
947/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.
948   ??? This could leave out insns not supported by the specified mach/isa,
949   but that would cause errors like "foo only supported by bar" to become
950   "unknown insn", so for now we include all insns and require the app to
951   do the checking later.
952   ??? On the other hand, parsing of such insns may require their hardware or
953   operand elements to be in the table [which they mightn't be].  */
954
955static void
956build_insn_table (CGEN_CPU_TABLE *cd)
957{
958  int i;
959  const CGEN_IBASE *ib = & ip2k_cgen_insn_table[0];
960  CGEN_INSN *insns = xmalloc (MAX_INSNS * sizeof (CGEN_INSN));
961
962  memset (insns, 0, MAX_INSNS * sizeof (CGEN_INSN));
963  for (i = 0; i < MAX_INSNS; ++i)
964    insns[i].base = &ib[i];
965  cd->insn_table.init_entries = insns;
966  cd->insn_table.entry_size = sizeof (CGEN_IBASE);
967  cd->insn_table.num_init_entries = MAX_INSNS;
968}
969
970/* Subroutine of ip2k_cgen_cpu_open to rebuild the tables.  */
971
972static void
973ip2k_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
974{
975  int i;
976  CGEN_BITSET *isas = cd->isas;
977  unsigned int machs = cd->machs;
978
979  cd->int_insn_p = CGEN_INT_INSN_P;
980
981  /* Data derived from the isa spec.  */
982#define UNSET (CGEN_SIZE_UNKNOWN + 1)
983  cd->default_insn_bitsize = UNSET;
984  cd->base_insn_bitsize = UNSET;
985  cd->min_insn_bitsize = 65535; /* Some ridiculously big number.  */
986  cd->max_insn_bitsize = 0;
987  for (i = 0; i < MAX_ISAS; ++i)
988    if (cgen_bitset_contains (isas, i))
989      {
990	const CGEN_ISA *isa = & ip2k_cgen_isa_table[i];
991
992	/* Default insn sizes of all selected isas must be
993	   equal or we set the result to 0, meaning "unknown".  */
994	if (cd->default_insn_bitsize == UNSET)
995	  cd->default_insn_bitsize = isa->default_insn_bitsize;
996	else if (isa->default_insn_bitsize == cd->default_insn_bitsize)
997	  ; /* This is ok.  */
998	else
999	  cd->default_insn_bitsize = CGEN_SIZE_UNKNOWN;
1000
1001	/* Base insn sizes of all selected isas must be equal
1002	   or we set the result to 0, meaning "unknown".  */
1003	if (cd->base_insn_bitsize == UNSET)
1004	  cd->base_insn_bitsize = isa->base_insn_bitsize;
1005	else if (isa->base_insn_bitsize == cd->base_insn_bitsize)
1006	  ; /* This is ok.  */
1007	else
1008	  cd->base_insn_bitsize = CGEN_SIZE_UNKNOWN;
1009
1010	/* Set min,max insn sizes.  */
1011	if (isa->min_insn_bitsize < cd->min_insn_bitsize)
1012	  cd->min_insn_bitsize = isa->min_insn_bitsize;
1013	if (isa->max_insn_bitsize > cd->max_insn_bitsize)
1014	  cd->max_insn_bitsize = isa->max_insn_bitsize;
1015      }
1016
1017  /* Data derived from the mach spec.  */
1018  for (i = 0; i < MAX_MACHS; ++i)
1019    if (((1 << i) & machs) != 0)
1020      {
1021	const CGEN_MACH *mach = & ip2k_cgen_mach_table[i];
1022
1023	if (mach->insn_chunk_bitsize != 0)
1024	{
1025	  if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
1026	    {
1027	      fprintf (stderr, "ip2k_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n",
1028		       cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
1029	      abort ();
1030	    }
1031
1032 	  cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
1033	}
1034      }
1035
1036  /* Determine which hw elements are used by MACH.  */
1037  build_hw_table (cd);
1038
1039  /* Build the ifield table.  */
1040  build_ifield_table (cd);
1041
1042  /* Determine which operands are used by MACH/ISA.  */
1043  build_operand_table (cd);
1044
1045  /* Build the instruction table.  */
1046  build_insn_table (cd);
1047}
1048
1049/* Initialize a cpu table and return a descriptor.
1050   It's much like opening a file, and must be the first function called.
1051   The arguments are a set of (type/value) pairs, terminated with
1052   CGEN_CPU_OPEN_END.
1053
1054   Currently supported values:
1055   CGEN_CPU_OPEN_ISAS:    bitmap of values in enum isa_attr
1056   CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
1057   CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
1058   CGEN_CPU_OPEN_ENDIAN:  specify endian choice
1059   CGEN_CPU_OPEN_END:     terminates arguments
1060
1061   ??? Simultaneous multiple isas might not make sense, but it's not (yet)
1062   precluded.
1063
1064   ??? We only support ISO C stdargs here, not K&R.
1065   Laziness, plus experiment to see if anything requires K&R - eventually
1066   K&R will no longer be supported - e.g. GDB is currently trying this.  */
1067
1068CGEN_CPU_DESC
1069ip2k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
1070{
1071  CGEN_CPU_TABLE *cd = (CGEN_CPU_TABLE *) xmalloc (sizeof (CGEN_CPU_TABLE));
1072  static int init_p;
1073  CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
1074  unsigned int machs = 0; /* 0 = "unspecified" */
1075  enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
1076  va_list ap;
1077
1078  if (! init_p)
1079    {
1080      init_tables ();
1081      init_p = 1;
1082    }
1083
1084  memset (cd, 0, sizeof (*cd));
1085
1086  va_start (ap, arg_type);
1087  while (arg_type != CGEN_CPU_OPEN_END)
1088    {
1089      switch (arg_type)
1090	{
1091	case CGEN_CPU_OPEN_ISAS :
1092	  isas = va_arg (ap, CGEN_BITSET *);
1093	  break;
1094	case CGEN_CPU_OPEN_MACHS :
1095	  machs = va_arg (ap, unsigned int);
1096	  break;
1097	case CGEN_CPU_OPEN_BFDMACH :
1098	  {
1099	    const char *name = va_arg (ap, const char *);
1100	    const CGEN_MACH *mach =
1101	      lookup_mach_via_bfd_name (ip2k_cgen_mach_table, name);
1102
1103	    machs |= 1 << mach->num;
1104	    break;
1105	  }
1106	case CGEN_CPU_OPEN_ENDIAN :
1107	  endian = va_arg (ap, enum cgen_endian);
1108	  break;
1109	default :
1110	  fprintf (stderr, "ip2k_cgen_cpu_open: unsupported argument `%d'\n",
1111		   arg_type);
1112	  abort (); /* ??? return NULL? */
1113	}
1114      arg_type = va_arg (ap, enum cgen_cpu_open_arg);
1115    }
1116  va_end (ap);
1117
1118  /* Mach unspecified means "all".  */
1119  if (machs == 0)
1120    machs = (1 << MAX_MACHS) - 1;
1121  /* Base mach is always selected.  */
1122  machs |= 1;
1123  if (endian == CGEN_ENDIAN_UNKNOWN)
1124    {
1125      /* ??? If target has only one, could have a default.  */
1126      fprintf (stderr, "ip2k_cgen_cpu_open: no endianness specified\n");
1127      abort ();
1128    }
1129
1130  cd->isas = cgen_bitset_copy (isas);
1131  cd->machs = machs;
1132  cd->endian = endian;
1133  /* FIXME: for the sparc case we can determine insn-endianness statically.
1134     The worry here is where both data and insn endian can be independently
1135     chosen, in which case this function will need another argument.
1136     Actually, will want to allow for more arguments in the future anyway.  */
1137  cd->insn_endian = endian;
1138
1139  /* Table (re)builder.  */
1140  cd->rebuild_tables = ip2k_cgen_rebuild_tables;
1141  ip2k_cgen_rebuild_tables (cd);
1142
1143  /* Default to not allowing signed overflow.  */
1144  cd->signed_overflow_ok_p = 0;
1145
1146  return (CGEN_CPU_DESC) cd;
1147}
1148
1149/* Cover fn to ip2k_cgen_cpu_open to handle the simple case of 1 isa, 1 mach.
1150   MACH_NAME is the bfd name of the mach.  */
1151
1152CGEN_CPU_DESC
1153ip2k_cgen_cpu_open_1 (const char *mach_name, enum cgen_endian endian)
1154{
1155  return ip2k_cgen_cpu_open (CGEN_CPU_OPEN_BFDMACH, mach_name,
1156			       CGEN_CPU_OPEN_ENDIAN, endian,
1157			       CGEN_CPU_OPEN_END);
1158}
1159
1160/* Close a cpu table.
1161   ??? This can live in a machine independent file, but there's currently
1162   no place to put this file (there's no libcgen).  libopcodes is the wrong
1163   place as some simulator ports use this but they don't use libopcodes.  */
1164
1165void
1166ip2k_cgen_cpu_close (CGEN_CPU_DESC cd)
1167{
1168  unsigned int i;
1169  const CGEN_INSN *insns;
1170
1171  if (cd->macro_insn_table.init_entries)
1172    {
1173      insns = cd->macro_insn_table.init_entries;
1174      for (i = 0; i < cd->macro_insn_table.num_init_entries; ++i, ++insns)
1175	if (CGEN_INSN_RX ((insns)))
1176	  regfree (CGEN_INSN_RX (insns));
1177    }
1178
1179  if (cd->insn_table.init_entries)
1180    {
1181      insns = cd->insn_table.init_entries;
1182      for (i = 0; i < cd->insn_table.num_init_entries; ++i, ++insns)
1183	if (CGEN_INSN_RX (insns))
1184	  regfree (CGEN_INSN_RX (insns));
1185    }
1186
1187  if (cd->macro_insn_table.init_entries)
1188    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
1189
1190  if (cd->insn_table.init_entries)
1191    free ((CGEN_INSN *) cd->insn_table.init_entries);
1192
1193  if (cd->hw_table.entries)
1194    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
1195
1196  if (cd->operand_table.entries)
1197    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
1198
1199  free (cd);
1200}
1201
1202