1d2201f2fSdrahn /* Assembler interface for targets using CGEN. -*- C -*-
2d2201f2fSdrahn CGEN: Cpu tools GENerator
3d2201f2fSdrahn
4d2201f2fSdrahn THIS FILE IS MACHINE GENERATED WITH CGEN.
5d2201f2fSdrahn - the resultant file is machine generated, cgen-asm.in isn't
6d2201f2fSdrahn
7d2201f2fSdrahn Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8d2201f2fSdrahn
9d2201f2fSdrahn This file is part of the GNU Binutils and GDB, the GNU debugger.
10d2201f2fSdrahn
11d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
12d2201f2fSdrahn it under the terms of the GNU General Public License as published by
13d2201f2fSdrahn the Free Software Foundation; either version 2, or (at your option)
14d2201f2fSdrahn any later version.
15d2201f2fSdrahn
16d2201f2fSdrahn This program is distributed in the hope that it will be useful,
17d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
18d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19d2201f2fSdrahn GNU General Public License for more details.
20d2201f2fSdrahn
21d2201f2fSdrahn You should have received a copy of the GNU General Public License
22d2201f2fSdrahn along with this program; if not, write to the Free Software Foundation, Inc.,
23d2201f2fSdrahn 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24d2201f2fSdrahn
25d2201f2fSdrahn /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26d2201f2fSdrahn Keep that in mind. */
27d2201f2fSdrahn
28d2201f2fSdrahn #include "sysdep.h"
29d2201f2fSdrahn #include <stdio.h>
30d2201f2fSdrahn #include "ansidecl.h"
31d2201f2fSdrahn #include "bfd.h"
32d2201f2fSdrahn #include "symcat.h"
33d2201f2fSdrahn #include "iq2000-desc.h"
34d2201f2fSdrahn #include "iq2000-opc.h"
35d2201f2fSdrahn #include "opintl.h"
36d2201f2fSdrahn #include "xregex.h"
37d2201f2fSdrahn #include "libiberty.h"
38d2201f2fSdrahn #include "safe-ctype.h"
39d2201f2fSdrahn
40d2201f2fSdrahn #undef min
41d2201f2fSdrahn #define min(a,b) ((a) < (b) ? (a) : (b))
42d2201f2fSdrahn #undef max
43d2201f2fSdrahn #define max(a,b) ((a) > (b) ? (a) : (b))
44d2201f2fSdrahn
45d2201f2fSdrahn static const char * parse_insn_normal
46*cf2f2c56Smiod (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
47d2201f2fSdrahn
48d2201f2fSdrahn /* -- assembler routines inserted here. */
49d2201f2fSdrahn
50d2201f2fSdrahn /* -- asm.c */
51d2201f2fSdrahn static const char * parse_mimm PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
52d2201f2fSdrahn static const char * parse_imm PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
53d2201f2fSdrahn static const char * parse_hi16 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
54d2201f2fSdrahn static const char * parse_lo16 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
55d2201f2fSdrahn
56d2201f2fSdrahn /* Special check to ensure that instruction exists for given machine */
57d2201f2fSdrahn int
iq2000_cgen_insn_supported(cd,insn)58d2201f2fSdrahn iq2000_cgen_insn_supported (cd, insn)
59d2201f2fSdrahn CGEN_CPU_DESC cd;
60d2201f2fSdrahn CGEN_INSN *insn;
61d2201f2fSdrahn {
62d2201f2fSdrahn int machs = cd->machs;
63d2201f2fSdrahn
64d2201f2fSdrahn return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
65d2201f2fSdrahn }
66d2201f2fSdrahn
iq2000_cgen_isa_register(strp)67d2201f2fSdrahn static int iq2000_cgen_isa_register (strp)
68d2201f2fSdrahn const char **strp;
69d2201f2fSdrahn {
70d2201f2fSdrahn int len;
71d2201f2fSdrahn int ch1, ch2;
72d2201f2fSdrahn if (**strp == 'r' || **strp == 'R')
73d2201f2fSdrahn {
74d2201f2fSdrahn len = strlen (*strp);
75d2201f2fSdrahn if (len == 2)
76d2201f2fSdrahn {
77d2201f2fSdrahn ch1 = (*strp)[1];
78d2201f2fSdrahn if ('0' <= ch1 && ch1 <= '9')
79d2201f2fSdrahn return 1;
80d2201f2fSdrahn }
81d2201f2fSdrahn else if (len == 3)
82d2201f2fSdrahn {
83d2201f2fSdrahn ch1 = (*strp)[1];
84d2201f2fSdrahn ch2 = (*strp)[2];
85d2201f2fSdrahn if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
86d2201f2fSdrahn return 1;
87d2201f2fSdrahn if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
88d2201f2fSdrahn return 1;
89d2201f2fSdrahn }
90d2201f2fSdrahn }
91d2201f2fSdrahn if (**strp == '%' && tolower((*strp)[1]) != 'l' && tolower((*strp)[1]) != 'h')
92d2201f2fSdrahn return 1;
93d2201f2fSdrahn return 0;
94d2201f2fSdrahn }
95d2201f2fSdrahn
96d2201f2fSdrahn /* Handle negated literal. */
97d2201f2fSdrahn
98d2201f2fSdrahn static const char *
parse_mimm(cd,strp,opindex,valuep)99d2201f2fSdrahn parse_mimm (cd, strp, opindex, valuep)
100d2201f2fSdrahn CGEN_CPU_DESC cd;
101d2201f2fSdrahn const char **strp;
102d2201f2fSdrahn int opindex;
103d2201f2fSdrahn long *valuep;
104d2201f2fSdrahn {
105d2201f2fSdrahn const char *errmsg;
106d2201f2fSdrahn long value;
107d2201f2fSdrahn
108d2201f2fSdrahn /* Verify this isn't a register */
109d2201f2fSdrahn if (iq2000_cgen_isa_register (strp))
110d2201f2fSdrahn errmsg = _("immediate value cannot be register");
111d2201f2fSdrahn else
112d2201f2fSdrahn {
113d2201f2fSdrahn long value;
114d2201f2fSdrahn
115d2201f2fSdrahn errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
116d2201f2fSdrahn if (errmsg == NULL)
117d2201f2fSdrahn {
118d2201f2fSdrahn long x = (-value) & 0xFFFF0000;
119d2201f2fSdrahn if (x != 0 && x != 0xFFFF0000)
120d2201f2fSdrahn errmsg = _("immediate value out of range");
121d2201f2fSdrahn else
122d2201f2fSdrahn *valuep = (-value & 0xFFFF);
123d2201f2fSdrahn }
124d2201f2fSdrahn }
125d2201f2fSdrahn return errmsg;
126d2201f2fSdrahn }
127d2201f2fSdrahn
128d2201f2fSdrahn /* Handle signed/unsigned literal. */
129d2201f2fSdrahn
130d2201f2fSdrahn static const char *
parse_imm(cd,strp,opindex,valuep)131d2201f2fSdrahn parse_imm (cd, strp, opindex, valuep)
132d2201f2fSdrahn CGEN_CPU_DESC cd;
133d2201f2fSdrahn const char **strp;
134d2201f2fSdrahn int opindex;
135d2201f2fSdrahn unsigned long *valuep;
136d2201f2fSdrahn {
137d2201f2fSdrahn const char *errmsg;
138d2201f2fSdrahn long value;
139d2201f2fSdrahn
140d2201f2fSdrahn if (iq2000_cgen_isa_register (strp))
141d2201f2fSdrahn errmsg = _("immediate value cannot be register");
142d2201f2fSdrahn else
143d2201f2fSdrahn {
144d2201f2fSdrahn long value;
145d2201f2fSdrahn
146d2201f2fSdrahn errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
147d2201f2fSdrahn if (errmsg == NULL)
148d2201f2fSdrahn {
149d2201f2fSdrahn long x = value & 0xFFFF0000;
150d2201f2fSdrahn if (x != 0 && x != 0xFFFF0000)
151d2201f2fSdrahn errmsg = _("immediate value out of range");
152d2201f2fSdrahn else
153d2201f2fSdrahn *valuep = (value & 0xFFFF);
154d2201f2fSdrahn }
155d2201f2fSdrahn }
156d2201f2fSdrahn return errmsg;
157d2201f2fSdrahn }
158d2201f2fSdrahn
159d2201f2fSdrahn /* Handle iq10 21-bit jmp offset. */
160d2201f2fSdrahn
161d2201f2fSdrahn static const char *
parse_jtargq10(cd,strp,opindex,reloc,type_addr,valuep)162d2201f2fSdrahn parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
163d2201f2fSdrahn CGEN_CPU_DESC cd;
164d2201f2fSdrahn const char **strp;
165d2201f2fSdrahn int opindex;
166d2201f2fSdrahn int reloc;
167d2201f2fSdrahn enum cgen_parse_operand_result *type_addr;
168d2201f2fSdrahn unsigned long *valuep;
169d2201f2fSdrahn {
170d2201f2fSdrahn const char *errmsg;
171d2201f2fSdrahn bfd_vma value;
172d2201f2fSdrahn enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
173d2201f2fSdrahn
174d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
175d2201f2fSdrahn &result_type, &value);
176d2201f2fSdrahn if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
177d2201f2fSdrahn {
178d2201f2fSdrahn /* check value is within 23-bits (remembering that 2-bit shift right will occur) */
179d2201f2fSdrahn if (value > 0x7fffff)
180d2201f2fSdrahn return _("21-bit offset out of range");
181d2201f2fSdrahn }
182d2201f2fSdrahn *valuep = (value & 0x7FFFFF);
183d2201f2fSdrahn return errmsg;
184d2201f2fSdrahn }
185d2201f2fSdrahn
186d2201f2fSdrahn /* Handle high(). */
187d2201f2fSdrahn
188d2201f2fSdrahn static const char *
parse_hi16(cd,strp,opindex,valuep)189d2201f2fSdrahn parse_hi16 (cd, strp, opindex, valuep)
190d2201f2fSdrahn CGEN_CPU_DESC cd;
191d2201f2fSdrahn const char **strp;
192d2201f2fSdrahn int opindex;
193d2201f2fSdrahn unsigned long *valuep;
194d2201f2fSdrahn {
195d2201f2fSdrahn if (strncasecmp (*strp, "%hi(", 4) == 0)
196d2201f2fSdrahn {
197d2201f2fSdrahn enum cgen_parse_operand_result result_type;
198d2201f2fSdrahn bfd_vma value;
199d2201f2fSdrahn const char *errmsg;
200d2201f2fSdrahn
201d2201f2fSdrahn *strp += 4;
202d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
203d2201f2fSdrahn &result_type, &value);
204d2201f2fSdrahn if (**strp != ')')
205d2201f2fSdrahn return _("missing `)'");
206d2201f2fSdrahn
207d2201f2fSdrahn ++*strp;
208d2201f2fSdrahn if (errmsg == NULL
209d2201f2fSdrahn && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
210d2201f2fSdrahn {
211d2201f2fSdrahn /* if value has top-bit of %lo on, then it will
212d2201f2fSdrahn sign-propagate and so we compensate by adding
213d2201f2fSdrahn 1 to the resultant %hi value */
214d2201f2fSdrahn if (value & 0x8000)
215d2201f2fSdrahn value += 0x10000;
216d2201f2fSdrahn value >>= 16;
217d2201f2fSdrahn }
218d2201f2fSdrahn *valuep = value;
219d2201f2fSdrahn
220d2201f2fSdrahn return errmsg;
221d2201f2fSdrahn }
222d2201f2fSdrahn
223d2201f2fSdrahn /* we add %uhi in case a user just wants the high 16-bits or is using
224d2201f2fSdrahn an insn like ori for %lo which does not sign-propagate */
225d2201f2fSdrahn if (strncasecmp (*strp, "%uhi(", 5) == 0)
226d2201f2fSdrahn {
227d2201f2fSdrahn enum cgen_parse_operand_result result_type;
228d2201f2fSdrahn bfd_vma value;
229d2201f2fSdrahn const char *errmsg;
230d2201f2fSdrahn
231d2201f2fSdrahn *strp += 5;
232d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
233d2201f2fSdrahn &result_type, &value);
234d2201f2fSdrahn if (**strp != ')')
235d2201f2fSdrahn return _("missing `)'");
236d2201f2fSdrahn
237d2201f2fSdrahn ++*strp;
238d2201f2fSdrahn if (errmsg == NULL
239d2201f2fSdrahn && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
240d2201f2fSdrahn {
241d2201f2fSdrahn value >>= 16;
242d2201f2fSdrahn }
243d2201f2fSdrahn *valuep = value;
244d2201f2fSdrahn
245d2201f2fSdrahn return errmsg;
246d2201f2fSdrahn }
247d2201f2fSdrahn
248d2201f2fSdrahn return parse_imm (cd, strp, opindex, valuep);
249d2201f2fSdrahn }
250d2201f2fSdrahn
251d2201f2fSdrahn /* Handle %lo in a signed context.
252d2201f2fSdrahn The signedness of the value doesn't matter to %lo(), but this also
253d2201f2fSdrahn handles the case where %lo() isn't present. */
254d2201f2fSdrahn
255d2201f2fSdrahn static const char *
parse_lo16(cd,strp,opindex,valuep)256d2201f2fSdrahn parse_lo16 (cd, strp, opindex, valuep)
257d2201f2fSdrahn CGEN_CPU_DESC cd;
258d2201f2fSdrahn const char **strp;
259d2201f2fSdrahn int opindex;
260d2201f2fSdrahn long *valuep;
261d2201f2fSdrahn {
262d2201f2fSdrahn if (strncasecmp (*strp, "%lo(", 4) == 0)
263d2201f2fSdrahn {
264d2201f2fSdrahn const char *errmsg;
265d2201f2fSdrahn enum cgen_parse_operand_result result_type;
266d2201f2fSdrahn bfd_vma value;
267d2201f2fSdrahn
268d2201f2fSdrahn *strp += 4;
269d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
270d2201f2fSdrahn &result_type, &value);
271d2201f2fSdrahn if (**strp != ')')
272d2201f2fSdrahn return _("missing `)'");
273d2201f2fSdrahn ++*strp;
274d2201f2fSdrahn if (errmsg == NULL
275d2201f2fSdrahn && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
276d2201f2fSdrahn value &= 0xffff;
277d2201f2fSdrahn *valuep = value;
278d2201f2fSdrahn return errmsg;
279d2201f2fSdrahn }
280d2201f2fSdrahn
281d2201f2fSdrahn return parse_imm (cd, strp, opindex, valuep);
282d2201f2fSdrahn }
283d2201f2fSdrahn
284d2201f2fSdrahn /* Handle %lo in a negated signed context.
285d2201f2fSdrahn The signedness of the value doesn't matter to %lo(), but this also
286d2201f2fSdrahn handles the case where %lo() isn't present. */
287d2201f2fSdrahn
288d2201f2fSdrahn static const char *
parse_mlo16(cd,strp,opindex,valuep)289d2201f2fSdrahn parse_mlo16 (cd, strp, opindex, valuep)
290d2201f2fSdrahn CGEN_CPU_DESC cd;
291d2201f2fSdrahn const char **strp;
292d2201f2fSdrahn int opindex;
293d2201f2fSdrahn long *valuep;
294d2201f2fSdrahn {
295d2201f2fSdrahn if (strncasecmp (*strp, "%lo(", 4) == 0)
296d2201f2fSdrahn {
297d2201f2fSdrahn const char *errmsg;
298d2201f2fSdrahn enum cgen_parse_operand_result result_type;
299d2201f2fSdrahn bfd_vma value;
300d2201f2fSdrahn
301d2201f2fSdrahn *strp += 4;
302d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
303d2201f2fSdrahn &result_type, &value);
304d2201f2fSdrahn if (**strp != ')')
305d2201f2fSdrahn return _("missing `)'");
306d2201f2fSdrahn ++*strp;
307d2201f2fSdrahn if (errmsg == NULL
308d2201f2fSdrahn && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
309d2201f2fSdrahn value = (-value) & 0xffff;
310d2201f2fSdrahn *valuep = value;
311d2201f2fSdrahn return errmsg;
312d2201f2fSdrahn }
313d2201f2fSdrahn
314d2201f2fSdrahn return parse_mimm (cd, strp, opindex, valuep);
315d2201f2fSdrahn }
316d2201f2fSdrahn
317d2201f2fSdrahn /* -- */
318d2201f2fSdrahn
319d2201f2fSdrahn const char * iq2000_cgen_parse_operand
320d2201f2fSdrahn PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
321d2201f2fSdrahn
322d2201f2fSdrahn /* Main entry point for operand parsing.
323d2201f2fSdrahn
324d2201f2fSdrahn This function is basically just a big switch statement. Earlier versions
325d2201f2fSdrahn used tables to look up the function to use, but
326d2201f2fSdrahn - if the table contains both assembler and disassembler functions then
327d2201f2fSdrahn the disassembler contains much of the assembler and vice-versa,
328d2201f2fSdrahn - there's a lot of inlining possibilities as things grow,
329d2201f2fSdrahn - using a switch statement avoids the function call overhead.
330d2201f2fSdrahn
331d2201f2fSdrahn This function could be moved into `parse_insn_normal', but keeping it
332d2201f2fSdrahn separate makes clear the interface between `parse_insn_normal' and each of
333d2201f2fSdrahn the handlers. */
334d2201f2fSdrahn
335d2201f2fSdrahn const char *
iq2000_cgen_parse_operand(cd,opindex,strp,fields)336d2201f2fSdrahn iq2000_cgen_parse_operand (cd, opindex, strp, fields)
337d2201f2fSdrahn CGEN_CPU_DESC cd;
338d2201f2fSdrahn int opindex;
339d2201f2fSdrahn const char ** strp;
340d2201f2fSdrahn CGEN_FIELDS * fields;
341d2201f2fSdrahn {
342d2201f2fSdrahn const char * errmsg = NULL;
343d2201f2fSdrahn /* Used by scalar operands that still need to be parsed. */
344d2201f2fSdrahn long junk ATTRIBUTE_UNUSED;
345d2201f2fSdrahn
346d2201f2fSdrahn switch (opindex)
347d2201f2fSdrahn {
348d2201f2fSdrahn case IQ2000_OPERAND_BASE :
349d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rs);
350d2201f2fSdrahn break;
351d2201f2fSdrahn case IQ2000_OPERAND_BASEOFF :
352d2201f2fSdrahn {
353d2201f2fSdrahn bfd_vma value;
354d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_BASEOFF, 0, NULL, & value);
355d2201f2fSdrahn fields->f_imm = value;
356d2201f2fSdrahn }
357d2201f2fSdrahn break;
358d2201f2fSdrahn case IQ2000_OPERAND_BITNUM :
359d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_BITNUM, &fields->f_rt);
360d2201f2fSdrahn break;
361d2201f2fSdrahn case IQ2000_OPERAND_BYTECOUNT :
362d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_BYTECOUNT, &fields->f_bytecount);
363d2201f2fSdrahn break;
364d2201f2fSdrahn case IQ2000_OPERAND_CAM_Y :
365d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CAM_Y, &fields->f_cam_y);
366d2201f2fSdrahn break;
367d2201f2fSdrahn case IQ2000_OPERAND_CAM_Z :
368d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CAM_Z, &fields->f_cam_z);
369d2201f2fSdrahn break;
370d2201f2fSdrahn case IQ2000_OPERAND_CM_3FUNC :
371d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_3FUNC, &fields->f_cm_3func);
372d2201f2fSdrahn break;
373d2201f2fSdrahn case IQ2000_OPERAND_CM_3Z :
374d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_3Z, &fields->f_cm_3z);
375d2201f2fSdrahn break;
376d2201f2fSdrahn case IQ2000_OPERAND_CM_4FUNC :
377d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_4FUNC, &fields->f_cm_4func);
378d2201f2fSdrahn break;
379d2201f2fSdrahn case IQ2000_OPERAND_CM_4Z :
380d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_4Z, &fields->f_cm_4z);
381d2201f2fSdrahn break;
382d2201f2fSdrahn case IQ2000_OPERAND_COUNT :
383d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_COUNT, &fields->f_count);
384d2201f2fSdrahn break;
385d2201f2fSdrahn case IQ2000_OPERAND_EXECODE :
386d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_EXECODE, &fields->f_excode);
387d2201f2fSdrahn break;
388*cf2f2c56Smiod case IQ2000_OPERAND_F_INDEX :
389*cf2f2c56Smiod errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_F_INDEX, &fields->f_index);
390*cf2f2c56Smiod break;
391d2201f2fSdrahn case IQ2000_OPERAND_HI16 :
392d2201f2fSdrahn errmsg = parse_hi16 (cd, strp, IQ2000_OPERAND_HI16, &fields->f_imm);
393d2201f2fSdrahn break;
394d2201f2fSdrahn case IQ2000_OPERAND_IMM :
395d2201f2fSdrahn errmsg = parse_imm (cd, strp, IQ2000_OPERAND_IMM, &fields->f_imm);
396d2201f2fSdrahn break;
397d2201f2fSdrahn case IQ2000_OPERAND_JMPTARG :
398d2201f2fSdrahn {
399d2201f2fSdrahn bfd_vma value;
400d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_JMPTARG, 0, NULL, & value);
401d2201f2fSdrahn fields->f_jtarg = value;
402d2201f2fSdrahn }
403d2201f2fSdrahn break;
404d2201f2fSdrahn case IQ2000_OPERAND_JMPTARGQ10 :
405d2201f2fSdrahn {
406d2201f2fSdrahn bfd_vma value;
407d2201f2fSdrahn errmsg = parse_jtargq10 (cd, strp, IQ2000_OPERAND_JMPTARGQ10, 0, NULL, & value);
408d2201f2fSdrahn fields->f_jtargq10 = value;
409d2201f2fSdrahn }
410d2201f2fSdrahn break;
411d2201f2fSdrahn case IQ2000_OPERAND_LO16 :
412d2201f2fSdrahn errmsg = parse_lo16 (cd, strp, IQ2000_OPERAND_LO16, &fields->f_imm);
413d2201f2fSdrahn break;
414d2201f2fSdrahn case IQ2000_OPERAND_MASK :
415d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASK, &fields->f_mask);
416d2201f2fSdrahn break;
417d2201f2fSdrahn case IQ2000_OPERAND_MASKL :
418d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKL, &fields->f_maskl);
419d2201f2fSdrahn break;
420d2201f2fSdrahn case IQ2000_OPERAND_MASKQ10 :
421d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKQ10, &fields->f_maskq10);
422d2201f2fSdrahn break;
423d2201f2fSdrahn case IQ2000_OPERAND_MASKR :
424d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKR, &fields->f_rs);
425d2201f2fSdrahn break;
426d2201f2fSdrahn case IQ2000_OPERAND_MLO16 :
427d2201f2fSdrahn errmsg = parse_mlo16 (cd, strp, IQ2000_OPERAND_MLO16, &fields->f_imm);
428d2201f2fSdrahn break;
429d2201f2fSdrahn case IQ2000_OPERAND_OFFSET :
430d2201f2fSdrahn {
431d2201f2fSdrahn bfd_vma value;
432d2201f2fSdrahn errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_OFFSET, 0, NULL, & value);
433d2201f2fSdrahn fields->f_offset = value;
434d2201f2fSdrahn }
435d2201f2fSdrahn break;
436d2201f2fSdrahn case IQ2000_OPERAND_RD :
437d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd);
438d2201f2fSdrahn break;
439d2201f2fSdrahn case IQ2000_OPERAND_RD_RS :
440d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd_rs);
441d2201f2fSdrahn break;
442d2201f2fSdrahn case IQ2000_OPERAND_RD_RT :
443d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd_rt);
444d2201f2fSdrahn break;
445d2201f2fSdrahn case IQ2000_OPERAND_RS :
446d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rs);
447d2201f2fSdrahn break;
448d2201f2fSdrahn case IQ2000_OPERAND_RT :
449d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rt);
450d2201f2fSdrahn break;
451d2201f2fSdrahn case IQ2000_OPERAND_RT_RS :
452d2201f2fSdrahn errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rt_rs);
453d2201f2fSdrahn break;
454d2201f2fSdrahn case IQ2000_OPERAND_SHAMT :
455d2201f2fSdrahn errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_SHAMT, &fields->f_shamt);
456d2201f2fSdrahn break;
457d2201f2fSdrahn
458d2201f2fSdrahn default :
459d2201f2fSdrahn /* xgettext:c-format */
460d2201f2fSdrahn fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
461d2201f2fSdrahn abort ();
462d2201f2fSdrahn }
463d2201f2fSdrahn
464d2201f2fSdrahn return errmsg;
465d2201f2fSdrahn }
466d2201f2fSdrahn
467d2201f2fSdrahn cgen_parse_fn * const iq2000_cgen_parse_handlers[] =
468d2201f2fSdrahn {
469d2201f2fSdrahn parse_insn_normal,
470d2201f2fSdrahn };
471d2201f2fSdrahn
472d2201f2fSdrahn void
iq2000_cgen_init_asm(cd)473d2201f2fSdrahn iq2000_cgen_init_asm (cd)
474d2201f2fSdrahn CGEN_CPU_DESC cd;
475d2201f2fSdrahn {
476d2201f2fSdrahn iq2000_cgen_init_opcode_table (cd);
477d2201f2fSdrahn iq2000_cgen_init_ibld_table (cd);
478d2201f2fSdrahn cd->parse_handlers = & iq2000_cgen_parse_handlers[0];
479d2201f2fSdrahn cd->parse_operand = iq2000_cgen_parse_operand;
480d2201f2fSdrahn }
481d2201f2fSdrahn
482d2201f2fSdrahn
483d2201f2fSdrahn
484d2201f2fSdrahn /* Regex construction routine.
485d2201f2fSdrahn
486d2201f2fSdrahn This translates an opcode syntax string into a regex string,
487d2201f2fSdrahn by replacing any non-character syntax element (such as an
488d2201f2fSdrahn opcode) with the pattern '.*'
489d2201f2fSdrahn
490d2201f2fSdrahn It then compiles the regex and stores it in the opcode, for
491d2201f2fSdrahn later use by iq2000_cgen_assemble_insn
492d2201f2fSdrahn
493d2201f2fSdrahn Returns NULL for success, an error message for failure. */
494d2201f2fSdrahn
495d2201f2fSdrahn char *
iq2000_cgen_build_insn_regex(CGEN_INSN * insn)496*cf2f2c56Smiod iq2000_cgen_build_insn_regex (CGEN_INSN *insn)
497d2201f2fSdrahn {
498d2201f2fSdrahn CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
499d2201f2fSdrahn const char *mnem = CGEN_INSN_MNEMONIC (insn);
500d2201f2fSdrahn char rxbuf[CGEN_MAX_RX_ELEMENTS];
501d2201f2fSdrahn char *rx = rxbuf;
502d2201f2fSdrahn const CGEN_SYNTAX_CHAR_TYPE *syn;
503d2201f2fSdrahn int reg_err;
504d2201f2fSdrahn
505d2201f2fSdrahn syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
506d2201f2fSdrahn
507d2201f2fSdrahn /* Mnemonics come first in the syntax string. */
508d2201f2fSdrahn if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
509d2201f2fSdrahn return _("missing mnemonic in syntax string");
510d2201f2fSdrahn ++syn;
511d2201f2fSdrahn
512d2201f2fSdrahn /* Generate a case sensitive regular expression that emulates case
513d2201f2fSdrahn insensitive matching in the "C" locale. We cannot generate a case
514d2201f2fSdrahn insensitive regular expression because in Turkish locales, 'i' and 'I'
515d2201f2fSdrahn are not equal modulo case conversion. */
516d2201f2fSdrahn
517d2201f2fSdrahn /* Copy the literal mnemonic out of the insn. */
518d2201f2fSdrahn for (; *mnem; mnem++)
519d2201f2fSdrahn {
520d2201f2fSdrahn char c = *mnem;
521d2201f2fSdrahn
522d2201f2fSdrahn if (ISALPHA (c))
523d2201f2fSdrahn {
524d2201f2fSdrahn *rx++ = '[';
525d2201f2fSdrahn *rx++ = TOLOWER (c);
526d2201f2fSdrahn *rx++ = TOUPPER (c);
527d2201f2fSdrahn *rx++ = ']';
528d2201f2fSdrahn }
529d2201f2fSdrahn else
530d2201f2fSdrahn *rx++ = c;
531d2201f2fSdrahn }
532d2201f2fSdrahn
533d2201f2fSdrahn /* Copy any remaining literals from the syntax string into the rx. */
534d2201f2fSdrahn for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
535d2201f2fSdrahn {
536d2201f2fSdrahn if (CGEN_SYNTAX_CHAR_P (* syn))
537d2201f2fSdrahn {
538d2201f2fSdrahn char c = CGEN_SYNTAX_CHAR (* syn);
539d2201f2fSdrahn
540d2201f2fSdrahn switch (c)
541d2201f2fSdrahn {
542d2201f2fSdrahn /* Escape any regex metacharacters in the syntax. */
543d2201f2fSdrahn case '.': case '[': case '\\':
544d2201f2fSdrahn case '*': case '^': case '$':
545d2201f2fSdrahn
546d2201f2fSdrahn #ifdef CGEN_ESCAPE_EXTENDED_REGEX
547d2201f2fSdrahn case '?': case '{': case '}':
548d2201f2fSdrahn case '(': case ')': case '*':
549d2201f2fSdrahn case '|': case '+': case ']':
550d2201f2fSdrahn #endif
551d2201f2fSdrahn *rx++ = '\\';
552d2201f2fSdrahn *rx++ = c;
553d2201f2fSdrahn break;
554d2201f2fSdrahn
555d2201f2fSdrahn default:
556d2201f2fSdrahn if (ISALPHA (c))
557d2201f2fSdrahn {
558d2201f2fSdrahn *rx++ = '[';
559d2201f2fSdrahn *rx++ = TOLOWER (c);
560d2201f2fSdrahn *rx++ = TOUPPER (c);
561d2201f2fSdrahn *rx++ = ']';
562d2201f2fSdrahn }
563d2201f2fSdrahn else
564d2201f2fSdrahn *rx++ = c;
565d2201f2fSdrahn break;
566d2201f2fSdrahn }
567d2201f2fSdrahn }
568d2201f2fSdrahn else
569d2201f2fSdrahn {
570d2201f2fSdrahn /* Replace non-syntax fields with globs. */
571d2201f2fSdrahn *rx++ = '.';
572d2201f2fSdrahn *rx++ = '*';
573d2201f2fSdrahn }
574d2201f2fSdrahn }
575d2201f2fSdrahn
576d2201f2fSdrahn /* Trailing whitespace ok. */
577d2201f2fSdrahn * rx++ = '[';
578d2201f2fSdrahn * rx++ = ' ';
579d2201f2fSdrahn * rx++ = '\t';
580d2201f2fSdrahn * rx++ = ']';
581d2201f2fSdrahn * rx++ = '*';
582d2201f2fSdrahn
583d2201f2fSdrahn /* But anchor it after that. */
584d2201f2fSdrahn * rx++ = '$';
585d2201f2fSdrahn * rx = '\0';
586d2201f2fSdrahn
587d2201f2fSdrahn CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
588d2201f2fSdrahn reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
589d2201f2fSdrahn
590d2201f2fSdrahn if (reg_err == 0)
591d2201f2fSdrahn return NULL;
592d2201f2fSdrahn else
593d2201f2fSdrahn {
594d2201f2fSdrahn static char msg[80];
595d2201f2fSdrahn
596d2201f2fSdrahn regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
597d2201f2fSdrahn regfree ((regex_t *) CGEN_INSN_RX (insn));
598d2201f2fSdrahn free (CGEN_INSN_RX (insn));
599d2201f2fSdrahn (CGEN_INSN_RX (insn)) = NULL;
600d2201f2fSdrahn return msg;
601d2201f2fSdrahn }
602d2201f2fSdrahn }
603d2201f2fSdrahn
604d2201f2fSdrahn
605d2201f2fSdrahn /* Default insn parser.
606d2201f2fSdrahn
607d2201f2fSdrahn The syntax string is scanned and operands are parsed and stored in FIELDS.
608d2201f2fSdrahn Relocs are queued as we go via other callbacks.
609d2201f2fSdrahn
610d2201f2fSdrahn ??? Note that this is currently an all-or-nothing parser. If we fail to
611d2201f2fSdrahn parse the instruction, we return 0 and the caller will start over from
612d2201f2fSdrahn the beginning. Backtracking will be necessary in parsing subexpressions,
613d2201f2fSdrahn but that can be handled there. Not handling backtracking here may get
614d2201f2fSdrahn expensive in the case of the m68k. Deal with later.
615d2201f2fSdrahn
616d2201f2fSdrahn Returns NULL for success, an error message for failure. */
617d2201f2fSdrahn
618d2201f2fSdrahn static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)619*cf2f2c56Smiod parse_insn_normal (CGEN_CPU_DESC cd,
620*cf2f2c56Smiod const CGEN_INSN *insn,
621*cf2f2c56Smiod const char **strp,
622*cf2f2c56Smiod CGEN_FIELDS *fields)
623d2201f2fSdrahn {
624d2201f2fSdrahn /* ??? Runtime added insns not handled yet. */
625d2201f2fSdrahn const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
626d2201f2fSdrahn const char *str = *strp;
627d2201f2fSdrahn const char *errmsg;
628d2201f2fSdrahn const char *p;
629d2201f2fSdrahn const CGEN_SYNTAX_CHAR_TYPE * syn;
630d2201f2fSdrahn #ifdef CGEN_MNEMONIC_OPERANDS
631d2201f2fSdrahn /* FIXME: wip */
632d2201f2fSdrahn int past_opcode_p;
633d2201f2fSdrahn #endif
634d2201f2fSdrahn
635d2201f2fSdrahn /* For now we assume the mnemonic is first (there are no leading operands).
636d2201f2fSdrahn We can parse it without needing to set up operand parsing.
637d2201f2fSdrahn GAS's input scrubber will ensure mnemonics are lowercase, but we may
638d2201f2fSdrahn not be called from GAS. */
639d2201f2fSdrahn p = CGEN_INSN_MNEMONIC (insn);
640d2201f2fSdrahn while (*p && TOLOWER (*p) == TOLOWER (*str))
641d2201f2fSdrahn ++p, ++str;
642d2201f2fSdrahn
643d2201f2fSdrahn if (* p)
644d2201f2fSdrahn return _("unrecognized instruction");
645d2201f2fSdrahn
646d2201f2fSdrahn #ifndef CGEN_MNEMONIC_OPERANDS
647d2201f2fSdrahn if (* str && ! ISSPACE (* str))
648d2201f2fSdrahn return _("unrecognized instruction");
649d2201f2fSdrahn #endif
650d2201f2fSdrahn
651d2201f2fSdrahn CGEN_INIT_PARSE (cd);
652d2201f2fSdrahn cgen_init_parse_operand (cd);
653d2201f2fSdrahn #ifdef CGEN_MNEMONIC_OPERANDS
654d2201f2fSdrahn past_opcode_p = 0;
655d2201f2fSdrahn #endif
656d2201f2fSdrahn
657d2201f2fSdrahn /* We don't check for (*str != '\0') here because we want to parse
658d2201f2fSdrahn any trailing fake arguments in the syntax string. */
659d2201f2fSdrahn syn = CGEN_SYNTAX_STRING (syntax);
660d2201f2fSdrahn
661d2201f2fSdrahn /* Mnemonics come first for now, ensure valid string. */
662d2201f2fSdrahn if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
663d2201f2fSdrahn abort ();
664d2201f2fSdrahn
665d2201f2fSdrahn ++syn;
666d2201f2fSdrahn
667d2201f2fSdrahn while (* syn != 0)
668d2201f2fSdrahn {
669d2201f2fSdrahn /* Non operand chars must match exactly. */
670d2201f2fSdrahn if (CGEN_SYNTAX_CHAR_P (* syn))
671d2201f2fSdrahn {
672d2201f2fSdrahn /* FIXME: While we allow for non-GAS callers above, we assume the
673d2201f2fSdrahn first char after the mnemonic part is a space. */
674d2201f2fSdrahn /* FIXME: We also take inappropriate advantage of the fact that
675d2201f2fSdrahn GAS's input scrubber will remove extraneous blanks. */
676d2201f2fSdrahn if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
677d2201f2fSdrahn {
678d2201f2fSdrahn #ifdef CGEN_MNEMONIC_OPERANDS
679d2201f2fSdrahn if (CGEN_SYNTAX_CHAR(* syn) == ' ')
680d2201f2fSdrahn past_opcode_p = 1;
681d2201f2fSdrahn #endif
682d2201f2fSdrahn ++ syn;
683d2201f2fSdrahn ++ str;
684d2201f2fSdrahn }
685d2201f2fSdrahn else if (*str)
686d2201f2fSdrahn {
687d2201f2fSdrahn /* Syntax char didn't match. Can't be this insn. */
688d2201f2fSdrahn static char msg [80];
689d2201f2fSdrahn
690d2201f2fSdrahn /* xgettext:c-format */
691d2201f2fSdrahn sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
692d2201f2fSdrahn CGEN_SYNTAX_CHAR(*syn), *str);
693d2201f2fSdrahn return msg;
694d2201f2fSdrahn }
695d2201f2fSdrahn else
696d2201f2fSdrahn {
697d2201f2fSdrahn /* Ran out of input. */
698d2201f2fSdrahn static char msg [80];
699d2201f2fSdrahn
700d2201f2fSdrahn /* xgettext:c-format */
701d2201f2fSdrahn sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
702d2201f2fSdrahn CGEN_SYNTAX_CHAR(*syn));
703d2201f2fSdrahn return msg;
704d2201f2fSdrahn }
705d2201f2fSdrahn continue;
706d2201f2fSdrahn }
707d2201f2fSdrahn
708d2201f2fSdrahn /* We have an operand of some sort. */
709d2201f2fSdrahn errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
710d2201f2fSdrahn &str, fields);
711d2201f2fSdrahn if (errmsg)
712d2201f2fSdrahn return errmsg;
713d2201f2fSdrahn
714d2201f2fSdrahn /* Done with this operand, continue with next one. */
715d2201f2fSdrahn ++ syn;
716d2201f2fSdrahn }
717d2201f2fSdrahn
718d2201f2fSdrahn /* If we're at the end of the syntax string, we're done. */
719d2201f2fSdrahn if (* syn == 0)
720d2201f2fSdrahn {
721d2201f2fSdrahn /* FIXME: For the moment we assume a valid `str' can only contain
722d2201f2fSdrahn blanks now. IE: We needn't try again with a longer version of
723d2201f2fSdrahn the insn and it is assumed that longer versions of insns appear
724d2201f2fSdrahn before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
725d2201f2fSdrahn while (ISSPACE (* str))
726d2201f2fSdrahn ++ str;
727d2201f2fSdrahn
728d2201f2fSdrahn if (* str != '\0')
729d2201f2fSdrahn return _("junk at end of line"); /* FIXME: would like to include `str' */
730d2201f2fSdrahn
731d2201f2fSdrahn return NULL;
732d2201f2fSdrahn }
733d2201f2fSdrahn
734d2201f2fSdrahn /* We couldn't parse it. */
735d2201f2fSdrahn return _("unrecognized instruction");
736d2201f2fSdrahn }
737d2201f2fSdrahn
738d2201f2fSdrahn /* Main entry point.
739d2201f2fSdrahn This routine is called for each instruction to be assembled.
740d2201f2fSdrahn STR points to the insn to be assembled.
741d2201f2fSdrahn We assume all necessary tables have been initialized.
742d2201f2fSdrahn The assembled instruction, less any fixups, is stored in BUF.
743d2201f2fSdrahn Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
744d2201f2fSdrahn still needs to be converted to target byte order, otherwise BUF is an array
745d2201f2fSdrahn of bytes in target byte order.
746d2201f2fSdrahn The result is a pointer to the insn's entry in the opcode table,
747d2201f2fSdrahn or NULL if an error occured (an error message will have already been
748d2201f2fSdrahn printed).
749d2201f2fSdrahn
750d2201f2fSdrahn Note that when processing (non-alias) macro-insns,
751d2201f2fSdrahn this function recurses.
752d2201f2fSdrahn
753d2201f2fSdrahn ??? It's possible to make this cpu-independent.
754d2201f2fSdrahn One would have to deal with a few minor things.
755d2201f2fSdrahn At this point in time doing so would be more of a curiosity than useful
756d2201f2fSdrahn [for example this file isn't _that_ big], but keeping the possibility in
757d2201f2fSdrahn mind helps keep the design clean. */
758d2201f2fSdrahn
759d2201f2fSdrahn const CGEN_INSN *
iq2000_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)760*cf2f2c56Smiod iq2000_cgen_assemble_insn (CGEN_CPU_DESC cd,
761*cf2f2c56Smiod const char *str,
762*cf2f2c56Smiod CGEN_FIELDS *fields,
763*cf2f2c56Smiod CGEN_INSN_BYTES_PTR buf,
764*cf2f2c56Smiod char **errmsg)
765d2201f2fSdrahn {
766d2201f2fSdrahn const char *start;
767d2201f2fSdrahn CGEN_INSN_LIST *ilist;
768d2201f2fSdrahn const char *parse_errmsg = NULL;
769d2201f2fSdrahn const char *insert_errmsg = NULL;
770d2201f2fSdrahn int recognized_mnemonic = 0;
771d2201f2fSdrahn
772d2201f2fSdrahn /* Skip leading white space. */
773d2201f2fSdrahn while (ISSPACE (* str))
774d2201f2fSdrahn ++ str;
775d2201f2fSdrahn
776d2201f2fSdrahn /* The instructions are stored in hashed lists.
777d2201f2fSdrahn Get the first in the list. */
778d2201f2fSdrahn ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
779d2201f2fSdrahn
780d2201f2fSdrahn /* Keep looking until we find a match. */
781d2201f2fSdrahn start = str;
782d2201f2fSdrahn for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
783d2201f2fSdrahn {
784d2201f2fSdrahn const CGEN_INSN *insn = ilist->insn;
785d2201f2fSdrahn recognized_mnemonic = 1;
786d2201f2fSdrahn
787d2201f2fSdrahn #ifdef CGEN_VALIDATE_INSN_SUPPORTED
788d2201f2fSdrahn /* Not usually needed as unsupported opcodes
789d2201f2fSdrahn shouldn't be in the hash lists. */
790d2201f2fSdrahn /* Is this insn supported by the selected cpu? */
791d2201f2fSdrahn if (! iq2000_cgen_insn_supported (cd, insn))
792d2201f2fSdrahn continue;
793d2201f2fSdrahn #endif
794*cf2f2c56Smiod /* If the RELAXED attribute is set, this is an insn that shouldn't be
795d2201f2fSdrahn chosen immediately. Instead, it is used during assembler/linker
796d2201f2fSdrahn relaxation if possible. */
797*cf2f2c56Smiod if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
798d2201f2fSdrahn continue;
799d2201f2fSdrahn
800d2201f2fSdrahn str = start;
801d2201f2fSdrahn
802d2201f2fSdrahn /* Skip this insn if str doesn't look right lexically. */
803d2201f2fSdrahn if (CGEN_INSN_RX (insn) != NULL &&
804d2201f2fSdrahn regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
805d2201f2fSdrahn continue;
806d2201f2fSdrahn
807d2201f2fSdrahn /* Allow parse/insert handlers to obtain length of insn. */
808d2201f2fSdrahn CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
809d2201f2fSdrahn
810d2201f2fSdrahn parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
811d2201f2fSdrahn if (parse_errmsg != NULL)
812d2201f2fSdrahn continue;
813d2201f2fSdrahn
814d2201f2fSdrahn /* ??? 0 is passed for `pc'. */
815d2201f2fSdrahn insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
816d2201f2fSdrahn (bfd_vma) 0);
817d2201f2fSdrahn if (insert_errmsg != NULL)
818d2201f2fSdrahn continue;
819d2201f2fSdrahn
820d2201f2fSdrahn /* It is up to the caller to actually output the insn and any
821d2201f2fSdrahn queued relocs. */
822d2201f2fSdrahn return insn;
823d2201f2fSdrahn }
824d2201f2fSdrahn
825d2201f2fSdrahn {
826d2201f2fSdrahn static char errbuf[150];
827d2201f2fSdrahn #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
828d2201f2fSdrahn const char *tmp_errmsg;
829d2201f2fSdrahn
830d2201f2fSdrahn /* If requesting verbose error messages, use insert_errmsg.
831d2201f2fSdrahn Failing that, use parse_errmsg. */
832d2201f2fSdrahn tmp_errmsg = (insert_errmsg ? insert_errmsg :
833d2201f2fSdrahn parse_errmsg ? parse_errmsg :
834d2201f2fSdrahn recognized_mnemonic ?
835d2201f2fSdrahn _("unrecognized form of instruction") :
836d2201f2fSdrahn _("unrecognized instruction"));
837d2201f2fSdrahn
838d2201f2fSdrahn if (strlen (start) > 50)
839d2201f2fSdrahn /* xgettext:c-format */
840d2201f2fSdrahn sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
841d2201f2fSdrahn else
842d2201f2fSdrahn /* xgettext:c-format */
843d2201f2fSdrahn sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
844d2201f2fSdrahn #else
845d2201f2fSdrahn if (strlen (start) > 50)
846d2201f2fSdrahn /* xgettext:c-format */
847d2201f2fSdrahn sprintf (errbuf, _("bad instruction `%.50s...'"), start);
848d2201f2fSdrahn else
849d2201f2fSdrahn /* xgettext:c-format */
850d2201f2fSdrahn sprintf (errbuf, _("bad instruction `%.50s'"), start);
851d2201f2fSdrahn #endif
852d2201f2fSdrahn
853d2201f2fSdrahn *errmsg = errbuf;
854d2201f2fSdrahn return NULL;
855d2201f2fSdrahn }
856d2201f2fSdrahn }
857d2201f2fSdrahn
858d2201f2fSdrahn #if 0 /* This calls back to GAS which we can't do without care. */
859d2201f2fSdrahn
860d2201f2fSdrahn /* Record each member of OPVALS in the assembler's symbol table.
861d2201f2fSdrahn This lets GAS parse registers for us.
862d2201f2fSdrahn ??? Interesting idea but not currently used. */
863d2201f2fSdrahn
864d2201f2fSdrahn /* Record each member of OPVALS in the assembler's symbol table.
865d2201f2fSdrahn FIXME: Not currently used. */
866d2201f2fSdrahn
867d2201f2fSdrahn void
868*cf2f2c56Smiod iq2000_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
869d2201f2fSdrahn {
870d2201f2fSdrahn CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
871d2201f2fSdrahn const CGEN_KEYWORD_ENTRY * ke;
872d2201f2fSdrahn
873d2201f2fSdrahn while ((ke = cgen_keyword_search_next (& search)) != NULL)
874d2201f2fSdrahn {
875d2201f2fSdrahn #if 0 /* Unnecessary, should be done in the search routine. */
876d2201f2fSdrahn if (! iq2000_cgen_opval_supported (ke))
877d2201f2fSdrahn continue;
878d2201f2fSdrahn #endif
879d2201f2fSdrahn cgen_asm_record_register (cd, ke->name, ke->value);
880d2201f2fSdrahn }
881d2201f2fSdrahn }
882d2201f2fSdrahn
883d2201f2fSdrahn #endif /* 0 */
884