1/* CPU data for ip2k.
2
3THIS FILE IS MACHINE GENERATED WITH CGEN.
4
5Copyright (C) 1996-2017 Free Software Foundation, Inc.
6
7This file is part of the GNU Binutils and/or GDB, the GNU debugger.
8
9   This file is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 3, or (at your option)
12   any later version.
13
14   It is distributed in the hope that it will be useful, but WITHOUT
15   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17   License for more details.
18
19   You should have received a copy of the GNU General Public License along
20   with this program; if not, write to the Free Software Foundation, Inc.,
21   51 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#define A(a) (1 << CGEN_HW_##a)
267
268const CGEN_HW_ENTRY ip2k_cgen_hw_table[] =
269{
270  { "h-memory", HW_H_MEMORY, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
271  { "h-sint", HW_H_SINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
272  { "h-uint", HW_H_UINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
273  { "h-addr", HW_H_ADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
274  { "h-iaddr", HW_H_IADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
275  { "h-spr", HW_H_SPR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
276  { "h-registers", HW_H_REGISTERS, CGEN_ASM_NONE, 0, { 0|A(VIRTUAL), { { { (1<<MACH_BASE), 0 } } } } },
277  { "h-stack", HW_H_STACK, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
278  { "h-pabits", HW_H_PABITS, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
279  { "h-zbit", HW_H_ZBIT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
280  { "h-cbit", HW_H_CBIT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
281  { "h-dcbit", HW_H_DCBIT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
282  { "h-pc", HW_H_PC, CGEN_ASM_NONE, 0, { 0|A(PROFILE)|A(PC), { { { (1<<MACH_BASE), 0 } } } } },
283  { 0, 0, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } }
284};
285
286#undef A
287
288
289/* The instruction field table.  */
290
291#define A(a) (1 << CGEN_IFLD_##a)
292
293const CGEN_IFLD ip2k_cgen_ifld_table[] =
294{
295  { IP2K_F_NIL, "f-nil", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
296  { IP2K_F_ANYOF, "f-anyof", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
297  { IP2K_F_IMM8, "f-imm8", 0, 16, 7, 8, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
298  { IP2K_F_REG, "f-reg", 0, 16, 8, 9, { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
299  { IP2K_F_ADDR16CJP, "f-addr16cjp", 0, 16, 12, 13, { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
300  { IP2K_F_DIR, "f-dir", 0, 16, 9, 1, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
301  { IP2K_F_BITNO, "f-bitno", 0, 16, 11, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
302  { IP2K_F_OP3, "f-op3", 0, 16, 15, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
303  { IP2K_F_OP4, "f-op4", 0, 16, 15, 4, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
304  { IP2K_F_OP4MID, "f-op4mid", 0, 16, 11, 4, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
305  { IP2K_F_OP6, "f-op6", 0, 16, 15, 6, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
306  { IP2K_F_OP8, "f-op8", 0, 16, 15, 8, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
307  { IP2K_F_OP6_10LOW, "f-op6-10low", 0, 16, 9, 10, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
308  { IP2K_F_OP6_7LOW, "f-op6-7low", 0, 16, 9, 7, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
309  { IP2K_F_RETI3, "f-reti3", 0, 16, 2, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
310  { IP2K_F_SKIPB, "f-skipb", 0, 16, 12, 1, { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
311  { IP2K_F_PAGE3, "f-page3", 0, 16, 2, 3, { 0, { { { (1<<MACH_BASE), 0 } } } }  },
312  { 0, 0, 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } }
313};
314
315#undef A
316
317
318
319/* multi ifield declarations */
320
321
322
323/* multi ifield definitions */
324
325
326/* The operand table.  */
327
328#define A(a) (1 << CGEN_OPERAND_##a)
329#define OPERAND(op) IP2K_OPERAND_##op
330
331const CGEN_OPERAND ip2k_cgen_operand_table[] =
332{
333/* pc: program counter */
334  { "pc", IP2K_OPERAND_PC, HW_H_PC, 0, 0,
335    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_NIL] } },
336    { 0|A(SEM_ONLY), { { { (1<<MACH_BASE), 0 } } } }  },
337/* addr16cjp: 13-bit address */
338  { "addr16cjp", IP2K_OPERAND_ADDR16CJP, HW_H_UINT, 12, 13,
339    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_ADDR16CJP] } },
340    { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
341/* fr: register */
342  { "fr", IP2K_OPERAND_FR, HW_H_REGISTERS, 8, 9,
343    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_REG] } },
344    { 0|A(ABS_ADDR), { { { (1<<MACH_BASE), 0 } } } }  },
345/* lit8: 8-bit signed literal */
346  { "lit8", IP2K_OPERAND_LIT8, HW_H_SINT, 7, 8,
347    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_IMM8] } },
348    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
349/* bitno: bit number */
350  { "bitno", IP2K_OPERAND_BITNO, HW_H_UINT, 11, 3,
351    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_BITNO] } },
352    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
353/* addr16p: page number */
354  { "addr16p", IP2K_OPERAND_ADDR16P, HW_H_UINT, 2, 3,
355    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_PAGE3] } },
356    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
357/* addr16h: high 8 bits of address */
358  { "addr16h", IP2K_OPERAND_ADDR16H, HW_H_UINT, 7, 8,
359    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_IMM8] } },
360    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
361/* addr16l: low 8 bits of address */
362  { "addr16l", IP2K_OPERAND_ADDR16L, HW_H_UINT, 7, 8,
363    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_IMM8] } },
364    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
365/* reti3: reti flags */
366  { "reti3", IP2K_OPERAND_RETI3, HW_H_UINT, 2, 3,
367    { 0, { (const PTR) &ip2k_cgen_ifld_table[IP2K_F_RETI3] } },
368    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
369/* pabits: page bits */
370  { "pabits", IP2K_OPERAND_PABITS, HW_H_PABITS, 0, 0,
371    { 0, { (const PTR) 0 } },
372    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
373/* zbit: zero bit */
374  { "zbit", IP2K_OPERAND_ZBIT, HW_H_ZBIT, 0, 0,
375    { 0, { (const PTR) 0 } },
376    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
377/* cbit: carry bit */
378  { "cbit", IP2K_OPERAND_CBIT, HW_H_CBIT, 0, 0,
379    { 0, { (const PTR) 0 } },
380    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
381/* dcbit: digit carry bit */
382  { "dcbit", IP2K_OPERAND_DCBIT, HW_H_DCBIT, 0, 0,
383    { 0, { (const PTR) 0 } },
384    { 0, { { { (1<<MACH_BASE), 0 } } } }  },
385/* sentinel */
386  { 0, 0, 0, 0, 0,
387    { 0, { (const PTR) 0 } },
388    { 0, { { { (1<<MACH_BASE), 0 } } } } }
389};
390
391#undef A
392
393
394/* The instruction table.  */
395
396#define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
397#define A(a) (1 << CGEN_INSN_##a)
398
399static const CGEN_IBASE ip2k_cgen_insn_table[MAX_INSNS] =
400{
401  /* Special null first entry.
402     A `num' value of zero is thus invalid.
403     Also, the special `invalid' insn resides here.  */
404  { 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } } } } },
405/* jmp $addr16cjp */
406  {
407    IP2K_INSN_JMP, "jmp", "jmp", 16,
408    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
409  },
410/* call $addr16cjp */
411  {
412    IP2K_INSN_CALL, "call", "call", 16,
413    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
414  },
415/* sb $fr,$bitno */
416  {
417    IP2K_INSN_SB, "sb", "sb", 16,
418    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
419  },
420/* snb $fr,$bitno */
421  {
422    IP2K_INSN_SNB, "snb", "snb", 16,
423    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
424  },
425/* setb $fr,$bitno */
426  {
427    IP2K_INSN_SETB, "setb", "setb", 16,
428    { 0, { { { (1<<MACH_BASE), 0 } } } }
429  },
430/* clrb $fr,$bitno */
431  {
432    IP2K_INSN_CLRB, "clrb", "clrb", 16,
433    { 0, { { { (1<<MACH_BASE), 0 } } } }
434  },
435/* xor W,#$lit8 */
436  {
437    IP2K_INSN_XORW_L, "xorw_l", "xor", 16,
438    { 0, { { { (1<<MACH_BASE), 0 } } } }
439  },
440/* and W,#$lit8 */
441  {
442    IP2K_INSN_ANDW_L, "andw_l", "and", 16,
443    { 0, { { { (1<<MACH_BASE), 0 } } } }
444  },
445/* or W,#$lit8 */
446  {
447    IP2K_INSN_ORW_L, "orw_l", "or", 16,
448    { 0, { { { (1<<MACH_BASE), 0 } } } }
449  },
450/* add W,#$lit8 */
451  {
452    IP2K_INSN_ADDW_L, "addw_l", "add", 16,
453    { 0, { { { (1<<MACH_BASE), 0 } } } }
454  },
455/* sub W,#$lit8 */
456  {
457    IP2K_INSN_SUBW_L, "subw_l", "sub", 16,
458    { 0, { { { (1<<MACH_BASE), 0 } } } }
459  },
460/* cmp W,#$lit8 */
461  {
462    IP2K_INSN_CMPW_L, "cmpw_l", "cmp", 16,
463    { 0, { { { (1<<MACH_BASE), 0 } } } }
464  },
465/* retw #$lit8 */
466  {
467    IP2K_INSN_RETW_L, "retw_l", "retw", 16,
468    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
469  },
470/* cse W,#$lit8 */
471  {
472    IP2K_INSN_CSEW_L, "csew_l", "cse", 16,
473    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
474  },
475/* csne W,#$lit8 */
476  {
477    IP2K_INSN_CSNEW_L, "csnew_l", "csne", 16,
478    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
479  },
480/* push #$lit8 */
481  {
482    IP2K_INSN_PUSH_L, "push_l", "push", 16,
483    { 0, { { { (1<<MACH_BASE), 0 } } } }
484  },
485/* muls W,#$lit8 */
486  {
487    IP2K_INSN_MULSW_L, "mulsw_l", "muls", 16,
488    { 0, { { { (1<<MACH_BASE), 0 } } } }
489  },
490/* mulu W,#$lit8 */
491  {
492    IP2K_INSN_MULUW_L, "muluw_l", "mulu", 16,
493    { 0, { { { (1<<MACH_BASE), 0 } } } }
494  },
495/* loadl #$lit8 */
496  {
497    IP2K_INSN_LOADL_L, "loadl_l", "loadl", 16,
498    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
499  },
500/* loadh #$lit8 */
501  {
502    IP2K_INSN_LOADH_L, "loadh_l", "loadh", 16,
503    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
504  },
505/* loadl $addr16l */
506  {
507    IP2K_INSN_LOADL_A, "loadl_a", "loadl", 16,
508    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
509  },
510/* loadh $addr16h */
511  {
512    IP2K_INSN_LOADH_A, "loadh_a", "loadh", 16,
513    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
514  },
515/* addc $fr,W */
516  {
517    IP2K_INSN_ADDCFR_W, "addcfr_w", "addc", 16,
518    { 0, { { { (1<<MACH_BASE), 0 } } } }
519  },
520/* addc W,$fr */
521  {
522    IP2K_INSN_ADDCW_FR, "addcw_fr", "addc", 16,
523    { 0, { { { (1<<MACH_BASE), 0 } } } }
524  },
525/* incsnz $fr */
526  {
527    IP2K_INSN_INCSNZ_FR, "incsnz_fr", "incsnz", 16,
528    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
529  },
530/* incsnz W,$fr */
531  {
532    IP2K_INSN_INCSNZW_FR, "incsnzw_fr", "incsnz", 16,
533    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
534  },
535/* muls W,$fr */
536  {
537    IP2K_INSN_MULSW_FR, "mulsw_fr", "muls", 16,
538    { 0, { { { (1<<MACH_BASE), 0 } } } }
539  },
540/* mulu W,$fr */
541  {
542    IP2K_INSN_MULUW_FR, "muluw_fr", "mulu", 16,
543    { 0, { { { (1<<MACH_BASE), 0 } } } }
544  },
545/* decsnz $fr */
546  {
547    IP2K_INSN_DECSNZ_FR, "decsnz_fr", "decsnz", 16,
548    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
549  },
550/* decsnz W,$fr */
551  {
552    IP2K_INSN_DECSNZW_FR, "decsnzw_fr", "decsnz", 16,
553    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
554  },
555/* subc W,$fr */
556  {
557    IP2K_INSN_SUBCW_FR, "subcw_fr", "subc", 16,
558    { 0, { { { (1<<MACH_BASE), 0 } } } }
559  },
560/* subc $fr,W */
561  {
562    IP2K_INSN_SUBCFR_W, "subcfr_w", "subc", 16,
563    { 0, { { { (1<<MACH_BASE), 0 } } } }
564  },
565/* pop $fr */
566  {
567    IP2K_INSN_POP_FR, "pop_fr", "pop", 16,
568    { 0, { { { (1<<MACH_BASE), 0 } } } }
569  },
570/* push $fr */
571  {
572    IP2K_INSN_PUSH_FR, "push_fr", "push", 16,
573    { 0, { { { (1<<MACH_BASE), 0 } } } }
574  },
575/* cse W,$fr */
576  {
577    IP2K_INSN_CSEW_FR, "csew_fr", "cse", 16,
578    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
579  },
580/* csne W,$fr */
581  {
582    IP2K_INSN_CSNEW_FR, "csnew_fr", "csne", 16,
583    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
584  },
585/* incsz $fr */
586  {
587    IP2K_INSN_INCSZ_FR, "incsz_fr", "incsz", 16,
588    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
589  },
590/* incsz W,$fr */
591  {
592    IP2K_INSN_INCSZW_FR, "incszw_fr", "incsz", 16,
593    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
594  },
595/* swap $fr */
596  {
597    IP2K_INSN_SWAP_FR, "swap_fr", "swap", 16,
598    { 0, { { { (1<<MACH_BASE), 0 } } } }
599  },
600/* swap W,$fr */
601  {
602    IP2K_INSN_SWAPW_FR, "swapw_fr", "swap", 16,
603    { 0, { { { (1<<MACH_BASE), 0 } } } }
604  },
605/* rl $fr */
606  {
607    IP2K_INSN_RL_FR, "rl_fr", "rl", 16,
608    { 0, { { { (1<<MACH_BASE), 0 } } } }
609  },
610/* rl W,$fr */
611  {
612    IP2K_INSN_RLW_FR, "rlw_fr", "rl", 16,
613    { 0, { { { (1<<MACH_BASE), 0 } } } }
614  },
615/* rr $fr */
616  {
617    IP2K_INSN_RR_FR, "rr_fr", "rr", 16,
618    { 0, { { { (1<<MACH_BASE), 0 } } } }
619  },
620/* rr W,$fr */
621  {
622    IP2K_INSN_RRW_FR, "rrw_fr", "rr", 16,
623    { 0, { { { (1<<MACH_BASE), 0 } } } }
624  },
625/* decsz $fr */
626  {
627    IP2K_INSN_DECSZ_FR, "decsz_fr", "decsz", 16,
628    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
629  },
630/* decsz W,$fr */
631  {
632    IP2K_INSN_DECSZW_FR, "decszw_fr", "decsz", 16,
633    { 0|A(SKIP_CTI), { { { (1<<MACH_BASE), 0 } } } }
634  },
635/* inc $fr */
636  {
637    IP2K_INSN_INC_FR, "inc_fr", "inc", 16,
638    { 0, { { { (1<<MACH_BASE), 0 } } } }
639  },
640/* inc W,$fr */
641  {
642    IP2K_INSN_INCW_FR, "incw_fr", "inc", 16,
643    { 0, { { { (1<<MACH_BASE), 0 } } } }
644  },
645/* not $fr */
646  {
647    IP2K_INSN_NOT_FR, "not_fr", "not", 16,
648    { 0, { { { (1<<MACH_BASE), 0 } } } }
649  },
650/* not W,$fr */
651  {
652    IP2K_INSN_NOTW_FR, "notw_fr", "not", 16,
653    { 0, { { { (1<<MACH_BASE), 0 } } } }
654  },
655/* test $fr */
656  {
657    IP2K_INSN_TEST_FR, "test_fr", "test", 16,
658    { 0, { { { (1<<MACH_BASE), 0 } } } }
659  },
660/* mov W,#$lit8 */
661  {
662    IP2K_INSN_MOVW_L, "movw_l", "mov", 16,
663    { 0, { { { (1<<MACH_BASE), 0 } } } }
664  },
665/* mov $fr,W */
666  {
667    IP2K_INSN_MOVFR_W, "movfr_w", "mov", 16,
668    { 0, { { { (1<<MACH_BASE), 0 } } } }
669  },
670/* mov W,$fr */
671  {
672    IP2K_INSN_MOVW_FR, "movw_fr", "mov", 16,
673    { 0, { { { (1<<MACH_BASE), 0 } } } }
674  },
675/* add $fr,W */
676  {
677    IP2K_INSN_ADDFR_W, "addfr_w", "add", 16,
678    { 0, { { { (1<<MACH_BASE), 0 } } } }
679  },
680/* add W,$fr */
681  {
682    IP2K_INSN_ADDW_FR, "addw_fr", "add", 16,
683    { 0, { { { (1<<MACH_BASE), 0 } } } }
684  },
685/* xor $fr,W */
686  {
687    IP2K_INSN_XORFR_W, "xorfr_w", "xor", 16,
688    { 0, { { { (1<<MACH_BASE), 0 } } } }
689  },
690/* xor W,$fr */
691  {
692    IP2K_INSN_XORW_FR, "xorw_fr", "xor", 16,
693    { 0, { { { (1<<MACH_BASE), 0 } } } }
694  },
695/* and $fr,W */
696  {
697    IP2K_INSN_ANDFR_W, "andfr_w", "and", 16,
698    { 0, { { { (1<<MACH_BASE), 0 } } } }
699  },
700/* and W,$fr */
701  {
702    IP2K_INSN_ANDW_FR, "andw_fr", "and", 16,
703    { 0, { { { (1<<MACH_BASE), 0 } } } }
704  },
705/* or $fr,W */
706  {
707    IP2K_INSN_ORFR_W, "orfr_w", "or", 16,
708    { 0, { { { (1<<MACH_BASE), 0 } } } }
709  },
710/* or W,$fr */
711  {
712    IP2K_INSN_ORW_FR, "orw_fr", "or", 16,
713    { 0, { { { (1<<MACH_BASE), 0 } } } }
714  },
715/* dec $fr */
716  {
717    IP2K_INSN_DEC_FR, "dec_fr", "dec", 16,
718    { 0, { { { (1<<MACH_BASE), 0 } } } }
719  },
720/* dec W,$fr */
721  {
722    IP2K_INSN_DECW_FR, "decw_fr", "dec", 16,
723    { 0, { { { (1<<MACH_BASE), 0 } } } }
724  },
725/* sub $fr,W */
726  {
727    IP2K_INSN_SUBFR_W, "subfr_w", "sub", 16,
728    { 0, { { { (1<<MACH_BASE), 0 } } } }
729  },
730/* sub W,$fr */
731  {
732    IP2K_INSN_SUBW_FR, "subw_fr", "sub", 16,
733    { 0, { { { (1<<MACH_BASE), 0 } } } }
734  },
735/* clr $fr */
736  {
737    IP2K_INSN_CLR_FR, "clr_fr", "clr", 16,
738    { 0, { { { (1<<MACH_BASE), 0 } } } }
739  },
740/* cmp W,$fr */
741  {
742    IP2K_INSN_CMPW_FR, "cmpw_fr", "cmp", 16,
743    { 0, { { { (1<<MACH_BASE), 0 } } } }
744  },
745/* speed #$lit8 */
746  {
747    IP2K_INSN_SPEED, "speed", "speed", 16,
748    { 0, { { { (1<<MACH_BASE), 0 } } } }
749  },
750/* ireadi */
751  {
752    IP2K_INSN_IREADI, "ireadi", "ireadi", 16,
753    { 0, { { { (1<<MACH_BASE), 0 } } } }
754  },
755/* iwritei */
756  {
757    IP2K_INSN_IWRITEI, "iwritei", "iwritei", 16,
758    { 0, { { { (1<<MACH_BASE), 0 } } } }
759  },
760/* fread */
761  {
762    IP2K_INSN_FREAD, "fread", "fread", 16,
763    { 0, { { { (1<<MACH_BASE), 0 } } } }
764  },
765/* fwrite */
766  {
767    IP2K_INSN_FWRITE, "fwrite", "fwrite", 16,
768    { 0, { { { (1<<MACH_BASE), 0 } } } }
769  },
770/* iread */
771  {
772    IP2K_INSN_IREAD, "iread", "iread", 16,
773    { 0, { { { (1<<MACH_BASE), 0 } } } }
774  },
775/* iwrite */
776  {
777    IP2K_INSN_IWRITE, "iwrite", "iwrite", 16,
778    { 0, { { { (1<<MACH_BASE), 0 } } } }
779  },
780/* page $addr16p */
781  {
782    IP2K_INSN_PAGE, "page", "page", 16,
783    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
784  },
785/* system */
786  {
787    IP2K_INSN_SYSTEM, "system", "system", 16,
788    { 0, { { { (1<<MACH_BASE), 0 } } } }
789  },
790/* reti #$reti3 */
791  {
792    IP2K_INSN_RETI, "reti", "reti", 16,
793    { 0, { { { (1<<MACH_BASE), 0 } } } }
794  },
795/* ret */
796  {
797    IP2K_INSN_RET, "ret", "ret", 16,
798    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
799  },
800/* int */
801  {
802    IP2K_INSN_INT, "int", "int", 16,
803    { 0, { { { (1<<MACH_BASE), 0 } } } }
804  },
805/* breakx */
806  {
807    IP2K_INSN_BREAKX, "breakx", "breakx", 16,
808    { 0|A(EXT_SKIP_INSN), { { { (1<<MACH_BASE), 0 } } } }
809  },
810/* cwdt */
811  {
812    IP2K_INSN_CWDT, "cwdt", "cwdt", 16,
813    { 0, { { { (1<<MACH_BASE), 0 } } } }
814  },
815/* ferase */
816  {
817    IP2K_INSN_FERASE, "ferase", "ferase", 16,
818    { 0, { { { (1<<MACH_BASE), 0 } } } }
819  },
820/* retnp */
821  {
822    IP2K_INSN_RETNP, "retnp", "retnp", 16,
823    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } } } }
824  },
825/* break */
826  {
827    IP2K_INSN_BREAK, "break", "break", 16,
828    { 0, { { { (1<<MACH_BASE), 0 } } } }
829  },
830/* nop */
831  {
832    IP2K_INSN_NOP, "nop", "nop", 16,
833    { 0, { { { (1<<MACH_BASE), 0 } } } }
834  },
835};
836
837#undef OP
838#undef A
839
840/* Initialize anything needed to be done once, before any cpu_open call.  */
841
842static void
843init_tables (void)
844{
845}
846
847static const CGEN_MACH * lookup_mach_via_bfd_name (const CGEN_MACH *, const char *);
848static void build_hw_table      (CGEN_CPU_TABLE *);
849static void build_ifield_table  (CGEN_CPU_TABLE *);
850static void build_operand_table (CGEN_CPU_TABLE *);
851static void build_insn_table    (CGEN_CPU_TABLE *);
852static void ip2k_cgen_rebuild_tables (CGEN_CPU_TABLE *);
853
854/* Subroutine of ip2k_cgen_cpu_open to look up a mach via its bfd name.  */
855
856static const CGEN_MACH *
857lookup_mach_via_bfd_name (const CGEN_MACH *table, const char *name)
858{
859  while (table->name)
860    {
861      if (strcmp (name, table->bfd_name) == 0)
862	return table;
863      ++table;
864    }
865  abort ();
866}
867
868/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.  */
869
870static void
871build_hw_table (CGEN_CPU_TABLE *cd)
872{
873  int i;
874  int machs = cd->machs;
875  const CGEN_HW_ENTRY *init = & ip2k_cgen_hw_table[0];
876  /* MAX_HW is only an upper bound on the number of selected entries.
877     However each entry is indexed by it's enum so there can be holes in
878     the table.  */
879  const CGEN_HW_ENTRY **selected =
880    (const CGEN_HW_ENTRY **) xmalloc (MAX_HW * sizeof (CGEN_HW_ENTRY *));
881
882  cd->hw_table.init_entries = init;
883  cd->hw_table.entry_size = sizeof (CGEN_HW_ENTRY);
884  memset (selected, 0, MAX_HW * sizeof (CGEN_HW_ENTRY *));
885  /* ??? For now we just use machs to determine which ones we want.  */
886  for (i = 0; init[i].name != NULL; ++i)
887    if (CGEN_HW_ATTR_VALUE (&init[i], CGEN_HW_MACH)
888	& machs)
889      selected[init[i].type] = &init[i];
890  cd->hw_table.entries = selected;
891  cd->hw_table.num_entries = MAX_HW;
892}
893
894/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.  */
895
896static void
897build_ifield_table (CGEN_CPU_TABLE *cd)
898{
899  cd->ifld_table = & ip2k_cgen_ifld_table[0];
900}
901
902/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.  */
903
904static void
905build_operand_table (CGEN_CPU_TABLE *cd)
906{
907  int i;
908  int machs = cd->machs;
909  const CGEN_OPERAND *init = & ip2k_cgen_operand_table[0];
910  /* MAX_OPERANDS is only an upper bound on the number of selected entries.
911     However each entry is indexed by it's enum so there can be holes in
912     the table.  */
913  const CGEN_OPERAND **selected = xmalloc (MAX_OPERANDS * sizeof (* selected));
914
915  cd->operand_table.init_entries = init;
916  cd->operand_table.entry_size = sizeof (CGEN_OPERAND);
917  memset (selected, 0, MAX_OPERANDS * sizeof (CGEN_OPERAND *));
918  /* ??? For now we just use mach to determine which ones we want.  */
919  for (i = 0; init[i].name != NULL; ++i)
920    if (CGEN_OPERAND_ATTR_VALUE (&init[i], CGEN_OPERAND_MACH)
921	& machs)
922      selected[init[i].type] = &init[i];
923  cd->operand_table.entries = selected;
924  cd->operand_table.num_entries = MAX_OPERANDS;
925}
926
927/* Subroutine of ip2k_cgen_cpu_open to build the hardware table.
928   ??? This could leave out insns not supported by the specified mach/isa,
929   but that would cause errors like "foo only supported by bar" to become
930   "unknown insn", so for now we include all insns and require the app to
931   do the checking later.
932   ??? On the other hand, parsing of such insns may require their hardware or
933   operand elements to be in the table [which they mightn't be].  */
934
935static void
936build_insn_table (CGEN_CPU_TABLE *cd)
937{
938  int i;
939  const CGEN_IBASE *ib = & ip2k_cgen_insn_table[0];
940  CGEN_INSN *insns = xmalloc (MAX_INSNS * sizeof (CGEN_INSN));
941
942  memset (insns, 0, MAX_INSNS * sizeof (CGEN_INSN));
943  for (i = 0; i < MAX_INSNS; ++i)
944    insns[i].base = &ib[i];
945  cd->insn_table.init_entries = insns;
946  cd->insn_table.entry_size = sizeof (CGEN_IBASE);
947  cd->insn_table.num_init_entries = MAX_INSNS;
948}
949
950/* Subroutine of ip2k_cgen_cpu_open to rebuild the tables.  */
951
952static void
953ip2k_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
954{
955  int i;
956  CGEN_BITSET *isas = cd->isas;
957  unsigned int machs = cd->machs;
958
959  cd->int_insn_p = CGEN_INT_INSN_P;
960
961  /* Data derived from the isa spec.  */
962#define UNSET (CGEN_SIZE_UNKNOWN + 1)
963  cd->default_insn_bitsize = UNSET;
964  cd->base_insn_bitsize = UNSET;
965  cd->min_insn_bitsize = 65535; /* Some ridiculously big number.  */
966  cd->max_insn_bitsize = 0;
967  for (i = 0; i < MAX_ISAS; ++i)
968    if (cgen_bitset_contains (isas, i))
969      {
970	const CGEN_ISA *isa = & ip2k_cgen_isa_table[i];
971
972	/* Default insn sizes of all selected isas must be
973	   equal or we set the result to 0, meaning "unknown".  */
974	if (cd->default_insn_bitsize == UNSET)
975	  cd->default_insn_bitsize = isa->default_insn_bitsize;
976	else if (isa->default_insn_bitsize == cd->default_insn_bitsize)
977	  ; /* This is ok.  */
978	else
979	  cd->default_insn_bitsize = CGEN_SIZE_UNKNOWN;
980
981	/* Base insn sizes of all selected isas must be equal
982	   or we set the result to 0, meaning "unknown".  */
983	if (cd->base_insn_bitsize == UNSET)
984	  cd->base_insn_bitsize = isa->base_insn_bitsize;
985	else if (isa->base_insn_bitsize == cd->base_insn_bitsize)
986	  ; /* This is ok.  */
987	else
988	  cd->base_insn_bitsize = CGEN_SIZE_UNKNOWN;
989
990	/* Set min,max insn sizes.  */
991	if (isa->min_insn_bitsize < cd->min_insn_bitsize)
992	  cd->min_insn_bitsize = isa->min_insn_bitsize;
993	if (isa->max_insn_bitsize > cd->max_insn_bitsize)
994	  cd->max_insn_bitsize = isa->max_insn_bitsize;
995      }
996
997  /* Data derived from the mach spec.  */
998  for (i = 0; i < MAX_MACHS; ++i)
999    if (((1 << i) & machs) != 0)
1000      {
1001	const CGEN_MACH *mach = & ip2k_cgen_mach_table[i];
1002
1003	if (mach->insn_chunk_bitsize != 0)
1004	{
1005	  if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
1006	    {
1007	      fprintf (stderr, "ip2k_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n",
1008		       cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
1009	      abort ();
1010	    }
1011
1012 	  cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
1013	}
1014      }
1015
1016  /* Determine which hw elements are used by MACH.  */
1017  build_hw_table (cd);
1018
1019  /* Build the ifield table.  */
1020  build_ifield_table (cd);
1021
1022  /* Determine which operands are used by MACH/ISA.  */
1023  build_operand_table (cd);
1024
1025  /* Build the instruction table.  */
1026  build_insn_table (cd);
1027}
1028
1029/* Initialize a cpu table and return a descriptor.
1030   It's much like opening a file, and must be the first function called.
1031   The arguments are a set of (type/value) pairs, terminated with
1032   CGEN_CPU_OPEN_END.
1033
1034   Currently supported values:
1035   CGEN_CPU_OPEN_ISAS:    bitmap of values in enum isa_attr
1036   CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
1037   CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
1038   CGEN_CPU_OPEN_ENDIAN:  specify endian choice
1039   CGEN_CPU_OPEN_END:     terminates arguments
1040
1041   ??? Simultaneous multiple isas might not make sense, but it's not (yet)
1042   precluded.  */
1043
1044CGEN_CPU_DESC
1045ip2k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
1046{
1047  CGEN_CPU_TABLE *cd = (CGEN_CPU_TABLE *) xmalloc (sizeof (CGEN_CPU_TABLE));
1048  static int init_p;
1049  CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
1050  unsigned int machs = 0; /* 0 = "unspecified" */
1051  enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
1052  va_list ap;
1053
1054  if (! init_p)
1055    {
1056      init_tables ();
1057      init_p = 1;
1058    }
1059
1060  memset (cd, 0, sizeof (*cd));
1061
1062  va_start (ap, arg_type);
1063  while (arg_type != CGEN_CPU_OPEN_END)
1064    {
1065      switch (arg_type)
1066	{
1067	case CGEN_CPU_OPEN_ISAS :
1068	  isas = va_arg (ap, CGEN_BITSET *);
1069	  break;
1070	case CGEN_CPU_OPEN_MACHS :
1071	  machs = va_arg (ap, unsigned int);
1072	  break;
1073	case CGEN_CPU_OPEN_BFDMACH :
1074	  {
1075	    const char *name = va_arg (ap, const char *);
1076	    const CGEN_MACH *mach =
1077	      lookup_mach_via_bfd_name (ip2k_cgen_mach_table, name);
1078
1079	    machs |= 1 << mach->num;
1080	    break;
1081	  }
1082	case CGEN_CPU_OPEN_ENDIAN :
1083	  endian = va_arg (ap, enum cgen_endian);
1084	  break;
1085	default :
1086	  fprintf (stderr, "ip2k_cgen_cpu_open: unsupported argument `%d'\n",
1087		   arg_type);
1088	  abort (); /* ??? return NULL? */
1089	}
1090      arg_type = va_arg (ap, enum cgen_cpu_open_arg);
1091    }
1092  va_end (ap);
1093
1094  /* Mach unspecified means "all".  */
1095  if (machs == 0)
1096    machs = (1 << MAX_MACHS) - 1;
1097  /* Base mach is always selected.  */
1098  machs |= 1;
1099  if (endian == CGEN_ENDIAN_UNKNOWN)
1100    {
1101      /* ??? If target has only one, could have a default.  */
1102      fprintf (stderr, "ip2k_cgen_cpu_open: no endianness specified\n");
1103      abort ();
1104    }
1105
1106  cd->isas = cgen_bitset_copy (isas);
1107  cd->machs = machs;
1108  cd->endian = endian;
1109  /* FIXME: for the sparc case we can determine insn-endianness statically.
1110     The worry here is where both data and insn endian can be independently
1111     chosen, in which case this function will need another argument.
1112     Actually, will want to allow for more arguments in the future anyway.  */
1113  cd->insn_endian = endian;
1114
1115  /* Table (re)builder.  */
1116  cd->rebuild_tables = ip2k_cgen_rebuild_tables;
1117  ip2k_cgen_rebuild_tables (cd);
1118
1119  /* Default to not allowing signed overflow.  */
1120  cd->signed_overflow_ok_p = 0;
1121
1122  return (CGEN_CPU_DESC) cd;
1123}
1124
1125/* Cover fn to ip2k_cgen_cpu_open to handle the simple case of 1 isa, 1 mach.
1126   MACH_NAME is the bfd name of the mach.  */
1127
1128CGEN_CPU_DESC
1129ip2k_cgen_cpu_open_1 (const char *mach_name, enum cgen_endian endian)
1130{
1131  return ip2k_cgen_cpu_open (CGEN_CPU_OPEN_BFDMACH, mach_name,
1132			       CGEN_CPU_OPEN_ENDIAN, endian,
1133			       CGEN_CPU_OPEN_END);
1134}
1135
1136/* Close a cpu table.
1137   ??? This can live in a machine independent file, but there's currently
1138   no place to put this file (there's no libcgen).  libopcodes is the wrong
1139   place as some simulator ports use this but they don't use libopcodes.  */
1140
1141void
1142ip2k_cgen_cpu_close (CGEN_CPU_DESC cd)
1143{
1144  unsigned int i;
1145  const CGEN_INSN *insns;
1146
1147  if (cd->macro_insn_table.init_entries)
1148    {
1149      insns = cd->macro_insn_table.init_entries;
1150      for (i = 0; i < cd->macro_insn_table.num_init_entries; ++i, ++insns)
1151	if (CGEN_INSN_RX ((insns)))
1152	  regfree (CGEN_INSN_RX (insns));
1153    }
1154
1155  if (cd->insn_table.init_entries)
1156    {
1157      insns = cd->insn_table.init_entries;
1158      for (i = 0; i < cd->insn_table.num_init_entries; ++i, ++insns)
1159	if (CGEN_INSN_RX (insns))
1160	  regfree (CGEN_INSN_RX (insns));
1161    }
1162
1163  if (cd->macro_insn_table.init_entries)
1164    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
1165
1166  if (cd->insn_table.init_entries)
1167    free ((CGEN_INSN *) cd->insn_table.init_entries);
1168
1169  if (cd->hw_table.entries)
1170    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
1171
1172  if (cd->operand_table.entries)
1173    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
1174
1175  free (cd);
1176}
1177
1178