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
init_tables(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 *
lookup_mach_via_bfd_name(const CGEN_MACH * table,const char * name)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
build_hw_table(CGEN_CPU_TABLE * cd)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
build_ifield_table(CGEN_CPU_TABLE * cd)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
build_operand_table(CGEN_CPU_TABLE * cd)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
build_insn_table(CGEN_CPU_TABLE * cd)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
ip2k_cgen_rebuild_tables(CGEN_CPU_TABLE * cd)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
ip2k_cgen_cpu_open(enum cgen_cpu_open_arg arg_type,...)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
ip2k_cgen_cpu_open_1(const char * mach_name,enum cgen_endian endian)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
ip2k_cgen_cpu_close(CGEN_CPU_DESC cd)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 
1178