* arc-dis.c: Don't include <ctype.h>.
[binutils-gdb.git] / opcodes / openrisc-desc.c
1 /* CPU data for openrisc.
2
3 THIS FILE IS MACHINE GENERATED WITH CGEN.
4
5 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
6
7 This file is part of the GNU Binutils and/or GDB, the GNU debugger.
8
9 This program 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 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public 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 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "openrisc-desc.h"
32 #include "openrisc-opc.h"
33 #include "opintl.h"
34 #include "libiberty.h"
35
36 static void init_tables PARAMS ((void));
37 static const CGEN_MACH * lookup_mach_via_bfd_name PARAMS ((const CGEN_MACH *, const char *));
38 static void build_hw_table PARAMS ((CGEN_CPU_TABLE *));
39 static void build_ifield_table PARAMS ((CGEN_CPU_TABLE *));
40 static void build_operand_table PARAMS ((CGEN_CPU_TABLE *));
41 static void build_insn_table PARAMS ((CGEN_CPU_TABLE *));
42 static void openrisc_cgen_rebuild_tables PARAMS ((CGEN_CPU_TABLE *));
43 /* Attributes. */
44
45 static const CGEN_ATTR_ENTRY bool_attr[] =
46 {
47 { "#f", 0 },
48 { "#t", 1 },
49 { 0, 0 }
50 };
51
52 static const CGEN_ATTR_ENTRY MACH_attr[] =
53 {
54 { "base", MACH_BASE },
55 { "openrisc", MACH_OPENRISC },
56 { "or1300", MACH_OR1300 },
57 { "max", MACH_MAX },
58 { 0, 0 }
59 };
60
61 static const CGEN_ATTR_ENTRY ISA_attr[] =
62 {
63 { "or32", ISA_OR32 },
64 { "max", ISA_MAX },
65 { 0, 0 }
66 };
67
68 static const CGEN_ATTR_ENTRY HAS_CACHE_attr[] =
69 {
70 { "DATA_CACHE", HAS_CACHE_DATA_CACHE },
71 { "INSN_CACHE", HAS_CACHE_INSN_CACHE },
72 { 0, 0 }
73 };
74
75 const CGEN_ATTR_TABLE openrisc_cgen_ifield_attr_table[] =
76 {
77 { "MACH", & MACH_attr[0], & MACH_attr[0] },
78 { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
79 { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] },
80 { "ABS-ADDR", &bool_attr[0], &bool_attr[0] },
81 { "RESERVED", &bool_attr[0], &bool_attr[0] },
82 { "SIGN-OPT", &bool_attr[0], &bool_attr[0] },
83 { "SIGNED", &bool_attr[0], &bool_attr[0] },
84 { 0, 0, 0 }
85 };
86
87 const CGEN_ATTR_TABLE openrisc_cgen_hardware_attr_table[] =
88 {
89 { "MACH", & MACH_attr[0], & MACH_attr[0] },
90 { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
91 { "CACHE-ADDR", &bool_attr[0], &bool_attr[0] },
92 { "PC", &bool_attr[0], &bool_attr[0] },
93 { "PROFILE", &bool_attr[0], &bool_attr[0] },
94 { 0, 0, 0 }
95 };
96
97 const CGEN_ATTR_TABLE openrisc_cgen_operand_attr_table[] =
98 {
99 { "MACH", & MACH_attr[0], & MACH_attr[0] },
100 { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
101 { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] },
102 { "ABS-ADDR", &bool_attr[0], &bool_attr[0] },
103 { "SIGN-OPT", &bool_attr[0], &bool_attr[0] },
104 { "SIGNED", &bool_attr[0], &bool_attr[0] },
105 { "NEGATIVE", &bool_attr[0], &bool_attr[0] },
106 { "RELAX", &bool_attr[0], &bool_attr[0] },
107 { "SEM-ONLY", &bool_attr[0], &bool_attr[0] },
108 { 0, 0, 0 }
109 };
110
111 const CGEN_ATTR_TABLE openrisc_cgen_insn_attr_table[] =
112 {
113 { "MACH", & MACH_attr[0], & MACH_attr[0] },
114 { "ALIAS", &bool_attr[0], &bool_attr[0] },
115 { "VIRTUAL", &bool_attr[0], &bool_attr[0] },
116 { "UNCOND-CTI", &bool_attr[0], &bool_attr[0] },
117 { "COND-CTI", &bool_attr[0], &bool_attr[0] },
118 { "SKIP-CTI", &bool_attr[0], &bool_attr[0] },
119 { "DELAY-SLOT", &bool_attr[0], &bool_attr[0] },
120 { "RELAXABLE", &bool_attr[0], &bool_attr[0] },
121 { "RELAX", &bool_attr[0], &bool_attr[0] },
122 { "NO-DIS", &bool_attr[0], &bool_attr[0] },
123 { "PBB", &bool_attr[0], &bool_attr[0] },
124 { "NOT-IN-DELAY-SLOT", &bool_attr[0], &bool_attr[0] },
125 { 0, 0, 0 }
126 };
127
128 /* Instruction set variants. */
129
130 static const CGEN_ISA openrisc_cgen_isa_table[] = {
131 { "or32", 32, 32, 32, 32 },
132 { 0, 0, 0, 0, 0 }
133 };
134
135 /* Machine variants. */
136
137 static const CGEN_MACH openrisc_cgen_mach_table[] = {
138 { "openrisc", "openrisc", MACH_OPENRISC, 0 },
139 { "or1300", "openrisc:1300", MACH_OR1300, 0 },
140 { 0, 0, 0, 0 }
141 };
142
143 static CGEN_KEYWORD_ENTRY openrisc_cgen_opval_h_gr_entries[] =
144 {
145 { "r0", 0, {0, {0}}, 0, 0 },
146 { "r1", 1, {0, {0}}, 0, 0 },
147 { "r2", 2, {0, {0}}, 0, 0 },
148 { "r3", 3, {0, {0}}, 0, 0 },
149 { "r4", 4, {0, {0}}, 0, 0 },
150 { "r5", 5, {0, {0}}, 0, 0 },
151 { "r6", 6, {0, {0}}, 0, 0 },
152 { "r7", 7, {0, {0}}, 0, 0 },
153 { "r8", 8, {0, {0}}, 0, 0 },
154 { "r9", 9, {0, {0}}, 0, 0 },
155 { "r10", 10, {0, {0}}, 0, 0 },
156 { "r11", 11, {0, {0}}, 0, 0 },
157 { "r12", 12, {0, {0}}, 0, 0 },
158 { "r13", 13, {0, {0}}, 0, 0 },
159 { "r14", 14, {0, {0}}, 0, 0 },
160 { "r15", 15, {0, {0}}, 0, 0 },
161 { "r16", 16, {0, {0}}, 0, 0 },
162 { "r17", 17, {0, {0}}, 0, 0 },
163 { "r18", 18, {0, {0}}, 0, 0 },
164 { "r19", 19, {0, {0}}, 0, 0 },
165 { "r20", 20, {0, {0}}, 0, 0 },
166 { "r21", 21, {0, {0}}, 0, 0 },
167 { "r22", 22, {0, {0}}, 0, 0 },
168 { "r23", 23, {0, {0}}, 0, 0 },
169 { "r24", 24, {0, {0}}, 0, 0 },
170 { "r25", 25, {0, {0}}, 0, 0 },
171 { "r26", 26, {0, {0}}, 0, 0 },
172 { "r27", 27, {0, {0}}, 0, 0 },
173 { "r28", 28, {0, {0}}, 0, 0 },
174 { "r29", 29, {0, {0}}, 0, 0 },
175 { "r30", 30, {0, {0}}, 0, 0 },
176 { "r31", 31, {0, {0}}, 0, 0 },
177 { "lr", 11, {0, {0}}, 0, 0 },
178 { "sp", 1, {0, {0}}, 0, 0 },
179 { "fp", 2, {0, {0}}, 0, 0 }
180 };
181
182 CGEN_KEYWORD openrisc_cgen_opval_h_gr =
183 {
184 & openrisc_cgen_opval_h_gr_entries[0],
185 35,
186 0, 0, 0, 0, ""
187 };
188
189
190 /* The hardware table. */
191
192 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
193 #define A(a) (1 << CGEN_HW_##a)
194 #else
195 #define A(a) (1 << CGEN_HW_/**/a)
196 #endif
197
198 const CGEN_HW_ENTRY openrisc_cgen_hw_table[] =
199 {
200 { "h-memory", HW_H_MEMORY, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
201 { "h-sint", HW_H_SINT, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
202 { "h-uint", HW_H_UINT, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
203 { "h-addr", HW_H_ADDR, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
204 { "h-iaddr", HW_H_IADDR, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
205 { "h-pc", HW_H_PC, CGEN_ASM_NONE, 0, { 0|A(PROFILE)|A(PC), { (1<<MACH_BASE) } } },
206 { "h-gr", HW_H_GR, CGEN_ASM_KEYWORD, (PTR) & openrisc_cgen_opval_h_gr, { 0|A(PROFILE), { (1<<MACH_BASE) } } },
207 { "h-sr", HW_H_SR, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
208 { "h-hi16", HW_H_HI16, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
209 { "h-lo16", HW_H_LO16, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
210 { "h-cbit", HW_H_CBIT, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
211 { "h-delay-insn", HW_H_DELAY_INSN, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
212 { 0, 0, CGEN_ASM_NONE, 0, {0, {0}} }
213 };
214
215 #undef A
216
217
218 /* The instruction field table. */
219
220 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
221 #define A(a) (1 << CGEN_IFLD_##a)
222 #else
223 #define A(a) (1 << CGEN_IFLD_/**/a)
224 #endif
225
226 const CGEN_IFLD openrisc_cgen_ifld_table[] =
227 {
228 { OPENRISC_F_NIL, "f-nil", 0, 0, 0, 0, { 0, { (1<<MACH_BASE) } } },
229 { OPENRISC_F_ANYOF, "f-anyof", 0, 0, 0, 0, { 0, { (1<<MACH_BASE) } } },
230 { OPENRISC_F_CLASS, "f-class", 0, 32, 31, 2, { 0, { (1<<MACH_BASE) } } },
231 { OPENRISC_F_SUB, "f-sub", 0, 32, 29, 4, { 0, { (1<<MACH_BASE) } } },
232 { OPENRISC_F_R1, "f-r1", 0, 32, 25, 5, { 0, { (1<<MACH_BASE) } } },
233 { OPENRISC_F_R2, "f-r2", 0, 32, 20, 5, { 0, { (1<<MACH_BASE) } } },
234 { OPENRISC_F_R3, "f-r3", 0, 32, 15, 5, { 0, { (1<<MACH_BASE) } } },
235 { OPENRISC_F_SIMM16, "f-simm16", 0, 32, 15, 16, { 0, { (1<<MACH_BASE) } } },
236 { OPENRISC_F_UIMM16, "f-uimm16", 0, 32, 15, 16, { 0, { (1<<MACH_BASE) } } },
237 { OPENRISC_F_UIMM5, "f-uimm5", 0, 32, 4, 5, { 0, { (1<<MACH_BASE) } } },
238 { OPENRISC_F_HI16, "f-hi16", 0, 32, 15, 16, { 0, { (1<<MACH_BASE) } } },
239 { OPENRISC_F_LO16, "f-lo16", 0, 32, 15, 16, { 0, { (1<<MACH_BASE) } } },
240 { OPENRISC_F_OP1, "f-op1", 0, 32, 31, 2, { 0, { (1<<MACH_BASE) } } },
241 { OPENRISC_F_OP2, "f-op2", 0, 32, 29, 4, { 0, { (1<<MACH_BASE) } } },
242 { OPENRISC_F_OP3, "f-op3", 0, 32, 25, 2, { 0, { (1<<MACH_BASE) } } },
243 { OPENRISC_F_OP4, "f-op4", 0, 32, 23, 3, { 0, { (1<<MACH_BASE) } } },
244 { OPENRISC_F_OP5, "f-op5", 0, 32, 25, 5, { 0, { (1<<MACH_BASE) } } },
245 { OPENRISC_F_OP6, "f-op6", 0, 32, 7, 3, { 0, { (1<<MACH_BASE) } } },
246 { OPENRISC_F_OP7, "f-op7", 0, 32, 3, 4, { 0, { (1<<MACH_BASE) } } },
247 { OPENRISC_F_I16_1, "f-i16-1", 0, 32, 10, 11, { 0, { (1<<MACH_BASE) } } },
248 { OPENRISC_F_I16_2, "f-i16-2", 0, 32, 25, 5, { 0, { (1<<MACH_BASE) } } },
249 { OPENRISC_F_DISP26, "f-disp26", 0, 32, 25, 26, { 0|A(PCREL_ADDR), { (1<<MACH_BASE) } } },
250 { OPENRISC_F_ABS26, "f-abs26", 0, 32, 25, 26, { 0|A(ABS_ADDR), { (1<<MACH_BASE) } } },
251 { OPENRISC_F_F_15_8, "f-f-15-8", 0, 32, 15, 8, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
252 { OPENRISC_F_F_10_3, "f-f-10-3", 0, 32, 10, 3, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
253 { OPENRISC_F_F_4_1, "f-f-4-1", 0, 32, 4, 1, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
254 { OPENRISC_F_F_7_3, "f-f-7-3", 0, 32, 7, 3, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
255 { OPENRISC_F_F_10_7, "f-f-10-7", 0, 32, 10, 7, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
256 { OPENRISC_F_F_10_11, "f-f-10-11", 0, 32, 10, 11, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
257 { 0, 0, 0, 0, 0, 0, {0, {0}} }
258 };
259
260 #undef A
261
262
263 /* The operand table. */
264
265 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
266 #define A(a) (1 << CGEN_OPERAND_##a)
267 #else
268 #define A(a) (1 << CGEN_OPERAND_/**/a)
269 #endif
270 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
271 #define OPERAND(op) OPENRISC_OPERAND_##op
272 #else
273 #define OPERAND(op) OPENRISC_OPERAND_/**/op
274 #endif
275
276 const CGEN_OPERAND openrisc_cgen_operand_table[] =
277 {
278 /* pc: program counter */
279 { "pc", OPENRISC_OPERAND_PC, HW_H_PC, 0, 0,
280 { 0|A(SEM_ONLY), { (1<<MACH_BASE) } } },
281 /* sr: special register */
282 { "sr", OPENRISC_OPERAND_SR, HW_H_SR, 0, 0,
283 { 0|A(SEM_ONLY), { (1<<MACH_BASE) } } },
284 /* cbit: condition bit */
285 { "cbit", OPENRISC_OPERAND_CBIT, HW_H_CBIT, 0, 0,
286 { 0|A(SEM_ONLY), { (1<<MACH_BASE) } } },
287 /* simm-16: 16 bit signed immediate */
288 { "simm-16", OPENRISC_OPERAND_SIMM_16, HW_H_SINT, 15, 16,
289 { 0, { (1<<MACH_BASE) } } },
290 /* uimm-16: 16 bit unsigned immediate */
291 { "uimm-16", OPENRISC_OPERAND_UIMM_16, HW_H_UINT, 15, 16,
292 { 0, { (1<<MACH_BASE) } } },
293 /* disp-26: pc-rel 26 bit */
294 { "disp-26", OPENRISC_OPERAND_DISP_26, HW_H_IADDR, 25, 26,
295 { 0|A(PCREL_ADDR), { (1<<MACH_BASE) } } },
296 /* abs-26: abs 26 bit */
297 { "abs-26", OPENRISC_OPERAND_ABS_26, HW_H_IADDR, 25, 26,
298 { 0|A(ABS_ADDR), { (1<<MACH_BASE) } } },
299 /* uimm-5: imm5 */
300 { "uimm-5", OPENRISC_OPERAND_UIMM_5, HW_H_UINT, 4, 5,
301 { 0, { (1<<MACH_BASE) } } },
302 /* rD: destination register */
303 { "rD", OPENRISC_OPERAND_RD, HW_H_GR, 25, 5,
304 { 0, { (1<<MACH_BASE) } } },
305 /* rA: source register A */
306 { "rA", OPENRISC_OPERAND_RA, HW_H_GR, 20, 5,
307 { 0, { (1<<MACH_BASE) } } },
308 /* rB: source register B */
309 { "rB", OPENRISC_OPERAND_RB, HW_H_GR, 15, 5,
310 { 0, { (1<<MACH_BASE) } } },
311 /* op-f-23: f-op23 */
312 { "op-f-23", OPENRISC_OPERAND_OP_F_23, HW_H_UINT, 23, 3,
313 { 0, { (1<<MACH_BASE) } } },
314 /* op-f-3: f-op3 */
315 { "op-f-3", OPENRISC_OPERAND_OP_F_3, HW_H_UINT, 25, 5,
316 { 0, { (1<<MACH_BASE) } } },
317 /* hi16: high 16 bit immediate, sign optional */
318 { "hi16", OPENRISC_OPERAND_HI16, HW_H_HI16, 15, 16,
319 { 0|A(SIGN_OPT), { (1<<MACH_BASE) } } },
320 /* lo16: low 16 bit immediate, sign optional */
321 { "lo16", OPENRISC_OPERAND_LO16, HW_H_LO16, 15, 16,
322 { 0|A(SIGN_OPT), { (1<<MACH_BASE) } } },
323 /* ui16nc: 16 bit immediate, sign optional */
324 { "ui16nc", OPENRISC_OPERAND_UI16NC, HW_H_LO16, 10, 16,
325 { 0|A(SIGN_OPT)|A(VIRTUAL), { (1<<MACH_BASE) } } },
326 { 0, 0, 0, 0, 0, {0, {0}} }
327 };
328
329 #undef A
330
331
332 /* The instruction table. */
333
334 #define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
335 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
336 #define A(a) (1 << CGEN_INSN_##a)
337 #else
338 #define A(a) (1 << CGEN_INSN_/**/a)
339 #endif
340
341 static const CGEN_IBASE openrisc_cgen_insn_table[MAX_INSNS] =
342 {
343 /* Special null first entry.
344 A `num' value of zero is thus invalid.
345 Also, the special `invalid' insn resides here. */
346 { 0, 0, 0, 0, {0, {0}} },
347 /* l.j ${abs-26} */
348 {
349 OPENRISC_INSN_L_J, "l-j", "l.j", 32,
350 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
351 },
352 /* l.jal ${abs-26} */
353 {
354 OPENRISC_INSN_L_JAL, "l-jal", "l.jal", 32,
355 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
356 },
357 /* l.jr $rA */
358 {
359 OPENRISC_INSN_L_JR, "l-jr", "l.jr", 32,
360 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
361 },
362 /* l.jalr $rA */
363 {
364 OPENRISC_INSN_L_JALR, "l-jalr", "l.jalr", 32,
365 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
366 },
367 /* l.bal ${disp-26} */
368 {
369 OPENRISC_INSN_L_BAL, "l-bal", "l.bal", 32,
370 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
371 },
372 /* l.bnf ${disp-26} */
373 {
374 OPENRISC_INSN_L_BNF, "l-bnf", "l.bnf", 32,
375 { 0|A(NOT_IN_DELAY_SLOT)|A(COND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
376 },
377 /* l.bf ${disp-26} */
378 {
379 OPENRISC_INSN_L_BF, "l-bf", "l.bf", 32,
380 { 0|A(NOT_IN_DELAY_SLOT)|A(COND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
381 },
382 /* l.brk ${uimm-16} */
383 {
384 OPENRISC_INSN_L_BRK, "l-brk", "l.brk", 32,
385 { 0|A(NOT_IN_DELAY_SLOT), { (1<<MACH_BASE) } }
386 },
387 /* l.rfe $rA */
388 {
389 OPENRISC_INSN_L_RFE, "l-rfe", "l.rfe", 32,
390 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
391 },
392 /* l.sys ${uimm-16} */
393 {
394 OPENRISC_INSN_L_SYS, "l-sys", "l.sys", 32,
395 { 0|A(NOT_IN_DELAY_SLOT)|A(UNCOND_CTI)|A(DELAY_SLOT), { (1<<MACH_BASE) } }
396 },
397 /* l.nop */
398 {
399 OPENRISC_INSN_L_NOP, "l-nop", "l.nop", 32,
400 { 0, { (1<<MACH_BASE) } }
401 },
402 /* l.movhi $rD,$hi16 */
403 {
404 OPENRISC_INSN_L_MOVHI, "l-movhi", "l.movhi", 32,
405 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
406 },
407 /* l.mfsr $rD,$rA */
408 {
409 OPENRISC_INSN_L_MFSR, "l-mfsr", "l.mfsr", 32,
410 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
411 },
412 /* l.mtsr $rA,$rB */
413 {
414 OPENRISC_INSN_L_MTSR, "l-mtsr", "l.mtsr", 32,
415 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
416 },
417 /* l.lw $rD,${simm-16}($rA) */
418 {
419 OPENRISC_INSN_L_LW, "l-lw", "l.lw", 32,
420 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
421 },
422 /* l.lbz $rD,${simm-16}($rA) */
423 {
424 OPENRISC_INSN_L_LBZ, "l-lbz", "l.lbz", 32,
425 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
426 },
427 /* l.lbs $rD,${simm-16}($rA) */
428 {
429 OPENRISC_INSN_L_LBS, "l-lbs", "l.lbs", 32,
430 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
431 },
432 /* l.lhz $rD,${simm-16}($rA) */
433 {
434 OPENRISC_INSN_L_LHZ, "l-lhz", "l.lhz", 32,
435 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
436 },
437 /* l.lhs $rD,${simm-16}($rA) */
438 {
439 OPENRISC_INSN_L_LHS, "l-lhs", "l.lhs", 32,
440 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
441 },
442 /* l.sw ${ui16nc}($rA),$rB */
443 {
444 OPENRISC_INSN_L_SW, "l-sw", "l.sw", 32,
445 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
446 },
447 /* l.sb ${ui16nc}($rA),$rB */
448 {
449 OPENRISC_INSN_L_SB, "l-sb", "l.sb", 32,
450 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
451 },
452 /* l.sh ${ui16nc}($rA),$rB */
453 {
454 OPENRISC_INSN_L_SH, "l-sh", "l.sh", 32,
455 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
456 },
457 /* l.sll $rD,$rA,$rB */
458 {
459 OPENRISC_INSN_L_SLL, "l-sll", "l.sll", 32,
460 { 0, { (1<<MACH_BASE) } }
461 },
462 /* l.slli $rD,$rA,${uimm-5} */
463 {
464 OPENRISC_INSN_L_SLLI, "l-slli", "l.slli", 32,
465 { 0, { (1<<MACH_BASE) } }
466 },
467 /* l.srl $rD,$rA,$rB */
468 {
469 OPENRISC_INSN_L_SRL, "l-srl", "l.srl", 32,
470 { 0, { (1<<MACH_BASE) } }
471 },
472 /* l.srli $rD,$rA,${uimm-5} */
473 {
474 OPENRISC_INSN_L_SRLI, "l-srli", "l.srli", 32,
475 { 0, { (1<<MACH_BASE) } }
476 },
477 /* l.sra $rD,$rA,$rB */
478 {
479 OPENRISC_INSN_L_SRA, "l-sra", "l.sra", 32,
480 { 0, { (1<<MACH_BASE) } }
481 },
482 /* l.srai $rD,$rA,${uimm-5} */
483 {
484 OPENRISC_INSN_L_SRAI, "l-srai", "l.srai", 32,
485 { 0, { (1<<MACH_BASE) } }
486 },
487 /* l.ror $rD,$rA,$rB */
488 {
489 OPENRISC_INSN_L_ROR, "l-ror", "l.ror", 32,
490 { 0, { (1<<MACH_BASE) } }
491 },
492 /* l.rori $rD,$rA,${uimm-5} */
493 {
494 OPENRISC_INSN_L_RORI, "l-rori", "l.rori", 32,
495 { 0, { (1<<MACH_BASE) } }
496 },
497 /* l.add $rD,$rA,$rB */
498 {
499 OPENRISC_INSN_L_ADD, "l-add", "l.add", 32,
500 { 0, { (1<<MACH_BASE) } }
501 },
502 /* l.addi $rD,$rA,$lo16 */
503 {
504 OPENRISC_INSN_L_ADDI, "l-addi", "l.addi", 32,
505 { 0, { (1<<MACH_BASE) } }
506 },
507 /* l.sub $rD,$rA,$rB */
508 {
509 OPENRISC_INSN_L_SUB, "l-sub", "l.sub", 32,
510 { 0, { (1<<MACH_BASE) } }
511 },
512 /* l.subi $rD,$rA,$lo16 */
513 {
514 OPENRISC_INSN_L_SUBI, "l-subi", "l.subi", 32,
515 { 0, { (1<<MACH_BASE) } }
516 },
517 /* l.and $rD,$rA,$rB */
518 {
519 OPENRISC_INSN_L_AND, "l-and", "l.and", 32,
520 { 0, { (1<<MACH_BASE) } }
521 },
522 /* l.andi $rD,$rA,$lo16 */
523 {
524 OPENRISC_INSN_L_ANDI, "l-andi", "l.andi", 32,
525 { 0, { (1<<MACH_BASE) } }
526 },
527 /* l.or $rD,$rA,$rB */
528 {
529 OPENRISC_INSN_L_OR, "l-or", "l.or", 32,
530 { 0, { (1<<MACH_BASE) } }
531 },
532 /* l.ori $rD,$rA,$lo16 */
533 {
534 OPENRISC_INSN_L_ORI, "l-ori", "l.ori", 32,
535 { 0, { (1<<MACH_BASE) } }
536 },
537 /* l.xor $rD,$rA,$rB */
538 {
539 OPENRISC_INSN_L_XOR, "l-xor", "l.xor", 32,
540 { 0, { (1<<MACH_BASE) } }
541 },
542 /* l.xori $rD,$rA,$lo16 */
543 {
544 OPENRISC_INSN_L_XORI, "l-xori", "l.xori", 32,
545 { 0, { (1<<MACH_BASE) } }
546 },
547 /* l.mul $rD,$rA,$rB */
548 {
549 OPENRISC_INSN_L_MUL, "l-mul", "l.mul", 32,
550 { 0, { (1<<MACH_BASE) } }
551 },
552 /* l.muli $rD,$rA,$lo16 */
553 {
554 OPENRISC_INSN_L_MULI, "l-muli", "l.muli", 32,
555 { 0, { (1<<MACH_BASE) } }
556 },
557 /* l.div $rD,$rA,$rB */
558 {
559 OPENRISC_INSN_L_DIV, "l-div", "l.div", 32,
560 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
561 },
562 /* l.divu $rD,$rA,$rB */
563 {
564 OPENRISC_INSN_L_DIVU, "l-divu", "l.divu", 32,
565 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
566 },
567 /* l.sfgts $rA,$rB */
568 {
569 OPENRISC_INSN_L_SFGTS, "l-sfgts", "l.sfgts", 32,
570 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
571 },
572 /* l.sfgtu $rA,$rB */
573 {
574 OPENRISC_INSN_L_SFGTU, "l-sfgtu", "l.sfgtu", 32,
575 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
576 },
577 /* l.sfges $rA,$rB */
578 {
579 OPENRISC_INSN_L_SFGES, "l-sfges", "l.sfges", 32,
580 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
581 },
582 /* l.sfgeu $rA,$rB */
583 {
584 OPENRISC_INSN_L_SFGEU, "l-sfgeu", "l.sfgeu", 32,
585 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
586 },
587 /* l.sflts $rA,$rB */
588 {
589 OPENRISC_INSN_L_SFLTS, "l-sflts", "l.sflts", 32,
590 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
591 },
592 /* l.sfltu $rA,$rB */
593 {
594 OPENRISC_INSN_L_SFLTU, "l-sfltu", "l.sfltu", 32,
595 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
596 },
597 /* l.sfles $rA,$rB */
598 {
599 OPENRISC_INSN_L_SFLES, "l-sfles", "l.sfles", 32,
600 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
601 },
602 /* l.sfleu $rA,$rB */
603 {
604 OPENRISC_INSN_L_SFLEU, "l-sfleu", "l.sfleu", 32,
605 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
606 },
607 /* l.sfgtsi $rA,${simm-16} */
608 {
609 OPENRISC_INSN_L_SFGTSI, "l-sfgtsi", "l.sfgtsi", 32,
610 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
611 },
612 /* l.sfgtui $rA,${uimm-16} */
613 {
614 OPENRISC_INSN_L_SFGTUI, "l-sfgtui", "l.sfgtui", 32,
615 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
616 },
617 /* l.sfgesi $rA,${simm-16} */
618 {
619 OPENRISC_INSN_L_SFGESI, "l-sfgesi", "l.sfgesi", 32,
620 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
621 },
622 /* l.sfgeui $rA,${uimm-16} */
623 {
624 OPENRISC_INSN_L_SFGEUI, "l-sfgeui", "l.sfgeui", 32,
625 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
626 },
627 /* l.sfltsi $rA,${simm-16} */
628 {
629 OPENRISC_INSN_L_SFLTSI, "l-sfltsi", "l.sfltsi", 32,
630 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
631 },
632 /* l.sfltui $rA,${uimm-16} */
633 {
634 OPENRISC_INSN_L_SFLTUI, "l-sfltui", "l.sfltui", 32,
635 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
636 },
637 /* l.sflesi $rA,${simm-16} */
638 {
639 OPENRISC_INSN_L_SFLESI, "l-sflesi", "l.sflesi", 32,
640 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
641 },
642 /* l.sfleui $rA,${uimm-16} */
643 {
644 OPENRISC_INSN_L_SFLEUI, "l-sfleui", "l.sfleui", 32,
645 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
646 },
647 /* l.sfeq $rA,$rB */
648 {
649 OPENRISC_INSN_L_SFEQ, "l-sfeq", "l.sfeq", 32,
650 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
651 },
652 /* l.sfeqi $rA,${simm-16} */
653 {
654 OPENRISC_INSN_L_SFEQI, "l-sfeqi", "l.sfeqi", 32,
655 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
656 },
657 /* l.sfne $rA,$rB */
658 {
659 OPENRISC_INSN_L_SFNE, "l-sfne", "l.sfne", 32,
660 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
661 },
662 /* l.sfnei $rA,${simm-16} */
663 {
664 OPENRISC_INSN_L_SFNEI, "l-sfnei", "l.sfnei", 32,
665 { 0|A(DELAY_SLOT), { (1<<MACH_BASE) } }
666 },
667 };
668
669 #undef OP
670 #undef A
671
672 /* Initialize anything needed to be done once, before any cpu_open call. */
673
674 static void
675 init_tables ()
676 {
677 }
678
679 /* Subroutine of openrisc_cgen_cpu_open to look up a mach via its bfd name. */
680
681 static const CGEN_MACH *
682 lookup_mach_via_bfd_name (table, name)
683 const CGEN_MACH *table;
684 const char *name;
685 {
686 while (table->name)
687 {
688 if (strcmp (name, table->bfd_name) == 0)
689 return table;
690 ++table;
691 }
692 abort ();
693 }
694
695 /* Subroutine of openrisc_cgen_cpu_open to build the hardware table. */
696
697 static void
698 build_hw_table (cd)
699 CGEN_CPU_TABLE *cd;
700 {
701 int i;
702 int machs = cd->machs;
703 const CGEN_HW_ENTRY *init = & openrisc_cgen_hw_table[0];
704 /* MAX_HW is only an upper bound on the number of selected entries.
705 However each entry is indexed by it's enum so there can be holes in
706 the table. */
707 const CGEN_HW_ENTRY **selected =
708 (const CGEN_HW_ENTRY **) xmalloc (MAX_HW * sizeof (CGEN_HW_ENTRY *));
709
710 cd->hw_table.init_entries = init;
711 cd->hw_table.entry_size = sizeof (CGEN_HW_ENTRY);
712 memset (selected, 0, MAX_HW * sizeof (CGEN_HW_ENTRY *));
713 /* ??? For now we just use machs to determine which ones we want. */
714 for (i = 0; init[i].name != NULL; ++i)
715 if (CGEN_HW_ATTR_VALUE (&init[i], CGEN_HW_MACH)
716 & machs)
717 selected[init[i].type] = &init[i];
718 cd->hw_table.entries = selected;
719 cd->hw_table.num_entries = MAX_HW;
720 }
721
722 /* Subroutine of openrisc_cgen_cpu_open to build the hardware table. */
723
724 static void
725 build_ifield_table (cd)
726 CGEN_CPU_TABLE *cd;
727 {
728 cd->ifld_table = & openrisc_cgen_ifld_table[0];
729 }
730
731 /* Subroutine of openrisc_cgen_cpu_open to build the hardware table. */
732
733 static void
734 build_operand_table (cd)
735 CGEN_CPU_TABLE *cd;
736 {
737 int i;
738 int machs = cd->machs;
739 const CGEN_OPERAND *init = & openrisc_cgen_operand_table[0];
740 /* MAX_OPERANDS is only an upper bound on the number of selected entries.
741 However each entry is indexed by it's enum so there can be holes in
742 the table. */
743 const CGEN_OPERAND **selected =
744 (const CGEN_OPERAND **) xmalloc (MAX_OPERANDS * sizeof (CGEN_OPERAND *));
745
746 cd->operand_table.init_entries = init;
747 cd->operand_table.entry_size = sizeof (CGEN_OPERAND);
748 memset (selected, 0, MAX_OPERANDS * sizeof (CGEN_OPERAND *));
749 /* ??? For now we just use mach to determine which ones we want. */
750 for (i = 0; init[i].name != NULL; ++i)
751 if (CGEN_OPERAND_ATTR_VALUE (&init[i], CGEN_OPERAND_MACH)
752 & machs)
753 selected[init[i].type] = &init[i];
754 cd->operand_table.entries = selected;
755 cd->operand_table.num_entries = MAX_OPERANDS;
756 }
757
758 /* Subroutine of openrisc_cgen_cpu_open to build the hardware table.
759 ??? This could leave out insns not supported by the specified mach/isa,
760 but that would cause errors like "foo only supported by bar" to become
761 "unknown insn", so for now we include all insns and require the app to
762 do the checking later.
763 ??? On the other hand, parsing of such insns may require their hardware or
764 operand elements to be in the table [which they mightn't be]. */
765
766 static void
767 build_insn_table (cd)
768 CGEN_CPU_TABLE *cd;
769 {
770 int i;
771 const CGEN_IBASE *ib = & openrisc_cgen_insn_table[0];
772 CGEN_INSN *insns = (CGEN_INSN *) xmalloc (MAX_INSNS * sizeof (CGEN_INSN));
773
774 memset (insns, 0, MAX_INSNS * sizeof (CGEN_INSN));
775 for (i = 0; i < MAX_INSNS; ++i)
776 insns[i].base = &ib[i];
777 cd->insn_table.init_entries = insns;
778 cd->insn_table.entry_size = sizeof (CGEN_IBASE);
779 cd->insn_table.num_init_entries = MAX_INSNS;
780 }
781
782 /* Subroutine of openrisc_cgen_cpu_open to rebuild the tables. */
783
784 static void
785 openrisc_cgen_rebuild_tables (cd)
786 CGEN_CPU_TABLE *cd;
787 {
788 int i;
789 unsigned int isas = cd->isas;
790 unsigned int machs = cd->machs;
791
792 cd->int_insn_p = CGEN_INT_INSN_P;
793
794 /* Data derived from the isa spec. */
795 #define UNSET (CGEN_SIZE_UNKNOWN + 1)
796 cd->default_insn_bitsize = UNSET;
797 cd->base_insn_bitsize = UNSET;
798 cd->min_insn_bitsize = 65535; /* some ridiculously big number */
799 cd->max_insn_bitsize = 0;
800 for (i = 0; i < MAX_ISAS; ++i)
801 if (((1 << i) & isas) != 0)
802 {
803 const CGEN_ISA *isa = & openrisc_cgen_isa_table[i];
804
805 /* Default insn sizes of all selected isas must be equal or we set
806 the result to 0, meaning "unknown". */
807 if (cd->default_insn_bitsize == UNSET)
808 cd->default_insn_bitsize = isa->default_insn_bitsize;
809 else if (isa->default_insn_bitsize == cd->default_insn_bitsize)
810 ; /* this is ok */
811 else
812 cd->default_insn_bitsize = CGEN_SIZE_UNKNOWN;
813
814 /* Base insn sizes of all selected isas must be equal or we set
815 the result to 0, meaning "unknown". */
816 if (cd->base_insn_bitsize == UNSET)
817 cd->base_insn_bitsize = isa->base_insn_bitsize;
818 else if (isa->base_insn_bitsize == cd->base_insn_bitsize)
819 ; /* this is ok */
820 else
821 cd->base_insn_bitsize = CGEN_SIZE_UNKNOWN;
822
823 /* Set min,max insn sizes. */
824 if (isa->min_insn_bitsize < cd->min_insn_bitsize)
825 cd->min_insn_bitsize = isa->min_insn_bitsize;
826 if (isa->max_insn_bitsize > cd->max_insn_bitsize)
827 cd->max_insn_bitsize = isa->max_insn_bitsize;
828 }
829
830 /* Data derived from the mach spec. */
831 for (i = 0; i < MAX_MACHS; ++i)
832 if (((1 << i) & machs) != 0)
833 {
834 const CGEN_MACH *mach = & openrisc_cgen_mach_table[i];
835
836 if (mach->insn_chunk_bitsize != 0)
837 {
838 if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
839 {
840 fprintf (stderr, "openrisc_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n",
841 cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
842 abort ();
843 }
844
845 cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
846 }
847 }
848
849 /* Determine which hw elements are used by MACH. */
850 build_hw_table (cd);
851
852 /* Build the ifield table. */
853 build_ifield_table (cd);
854
855 /* Determine which operands are used by MACH/ISA. */
856 build_operand_table (cd);
857
858 /* Build the instruction table. */
859 build_insn_table (cd);
860 }
861
862 /* Initialize a cpu table and return a descriptor.
863 It's much like opening a file, and must be the first function called.
864 The arguments are a set of (type/value) pairs, terminated with
865 CGEN_CPU_OPEN_END.
866
867 Currently supported values:
868 CGEN_CPU_OPEN_ISAS: bitmap of values in enum isa_attr
869 CGEN_CPU_OPEN_MACHS: bitmap of values in enum mach_attr
870 CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
871 CGEN_CPU_OPEN_ENDIAN: specify endian choice
872 CGEN_CPU_OPEN_END: terminates arguments
873
874 ??? Simultaneous multiple isas might not make sense, but it's not (yet)
875 precluded.
876
877 ??? We only support ISO C stdargs here, not K&R.
878 Laziness, plus experiment to see if anything requires K&R - eventually
879 K&R will no longer be supported - e.g. GDB is currently trying this. */
880
881 CGEN_CPU_DESC
882 openrisc_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
883 {
884 CGEN_CPU_TABLE *cd = (CGEN_CPU_TABLE *) xmalloc (sizeof (CGEN_CPU_TABLE));
885 static int init_p;
886 unsigned int isas = 0; /* 0 = "unspecified" */
887 unsigned int machs = 0; /* 0 = "unspecified" */
888 enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
889 va_list ap;
890
891 if (! init_p)
892 {
893 init_tables ();
894 init_p = 1;
895 }
896
897 memset (cd, 0, sizeof (*cd));
898
899 va_start (ap, arg_type);
900 while (arg_type != CGEN_CPU_OPEN_END)
901 {
902 switch (arg_type)
903 {
904 case CGEN_CPU_OPEN_ISAS :
905 isas = va_arg (ap, unsigned int);
906 break;
907 case CGEN_CPU_OPEN_MACHS :
908 machs = va_arg (ap, unsigned int);
909 break;
910 case CGEN_CPU_OPEN_BFDMACH :
911 {
912 const char *name = va_arg (ap, const char *);
913 const CGEN_MACH *mach =
914 lookup_mach_via_bfd_name (openrisc_cgen_mach_table, name);
915
916 machs |= 1 << mach->num;
917 break;
918 }
919 case CGEN_CPU_OPEN_ENDIAN :
920 endian = va_arg (ap, enum cgen_endian);
921 break;
922 default :
923 fprintf (stderr, "openrisc_cgen_cpu_open: unsupported argument `%d'\n",
924 arg_type);
925 abort (); /* ??? return NULL? */
926 }
927 arg_type = va_arg (ap, enum cgen_cpu_open_arg);
928 }
929 va_end (ap);
930
931 /* mach unspecified means "all" */
932 if (machs == 0)
933 machs = (1 << MAX_MACHS) - 1;
934 /* base mach is always selected */
935 machs |= 1;
936 /* isa unspecified means "all" */
937 if (isas == 0)
938 isas = (1 << MAX_ISAS) - 1;
939 if (endian == CGEN_ENDIAN_UNKNOWN)
940 {
941 /* ??? If target has only one, could have a default. */
942 fprintf (stderr, "openrisc_cgen_cpu_open: no endianness specified\n");
943 abort ();
944 }
945
946 cd->isas = isas;
947 cd->machs = machs;
948 cd->endian = endian;
949 /* FIXME: for the sparc case we can determine insn-endianness statically.
950 The worry here is where both data and insn endian can be independently
951 chosen, in which case this function will need another argument.
952 Actually, will want to allow for more arguments in the future anyway. */
953 cd->insn_endian = endian;
954
955 /* Table (re)builder. */
956 cd->rebuild_tables = openrisc_cgen_rebuild_tables;
957 openrisc_cgen_rebuild_tables (cd);
958
959 /* Default to not allowing signed overflow. */
960 cd->signed_overflow_ok_p = 0;
961
962 return (CGEN_CPU_DESC) cd;
963 }
964
965 /* Cover fn to openrisc_cgen_cpu_open to handle the simple case of 1 isa, 1 mach.
966 MACH_NAME is the bfd name of the mach. */
967
968 CGEN_CPU_DESC
969 openrisc_cgen_cpu_open_1 (mach_name, endian)
970 const char *mach_name;
971 enum cgen_endian endian;
972 {
973 return openrisc_cgen_cpu_open (CGEN_CPU_OPEN_BFDMACH, mach_name,
974 CGEN_CPU_OPEN_ENDIAN, endian,
975 CGEN_CPU_OPEN_END);
976 }
977
978 /* Close a cpu table.
979 ??? This can live in a machine independent file, but there's currently
980 no place to put this file (there's no libcgen). libopcodes is the wrong
981 place as some simulator ports use this but they don't use libopcodes. */
982
983 void
984 openrisc_cgen_cpu_close (cd)
985 CGEN_CPU_DESC cd;
986 {
987 if (cd->insn_table.init_entries)
988 free ((CGEN_INSN *) cd->insn_table.init_entries);
989 if (cd->hw_table.entries)
990 free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
991 free (cd);
992 }
993