[ARM] Add ARMv8.2 FP16 vmul/vmla/vmls (by scalar)
[external/binutils.git] / opcodes / ip2k-desc.c
1 /* CPU data for ip2k.
2
3 THIS FILE IS MACHINE GENERATED WITH CGEN.
4
5 Copyright (C) 1996-2016 Free Software Foundation, Inc.
6
7 This 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
39 static const CGEN_ATTR_ENTRY bool_attr[] =
40 {
41   { "#f", 0 },
42   { "#t", 1 },
43   { 0, 0 }
44 };
45
46 static 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
55 static const CGEN_ATTR_ENTRY ISA_attr[] ATTRIBUTE_UNUSED =
56 {
57   { "ip2k", ISA_IP2K },
58   { "max", ISA_MAX },
59   { 0, 0 }
60 };
61
62 const 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
74 const 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
84 const 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
98 const 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
118 static 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
125 static 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
131 static 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
256 CGEN_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
268 const 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
293 const 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
331 const 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
399 static 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
842 static void
843 init_tables (void)
844 {
845 }
846
847 static const CGEN_MACH * lookup_mach_via_bfd_name (const CGEN_MACH *, const char *);
848 static void build_hw_table      (CGEN_CPU_TABLE *);
849 static void build_ifield_table  (CGEN_CPU_TABLE *);
850 static void build_operand_table (CGEN_CPU_TABLE *);
851 static void build_insn_table    (CGEN_CPU_TABLE *);
852 static 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
856 static const CGEN_MACH *
857 lookup_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
870 static void
871 build_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
896 static void
897 build_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
904 static void
905 build_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
935 static void
936 build_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
952 static void
953 ip2k_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
1044 CGEN_CPU_DESC
1045 ip2k_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
1128 CGEN_CPU_DESC
1129 ip2k_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
1141 void
1142 ip2k_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