1ede78133Schristos /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
275fd0b74Schristos /* Assembler interface for targets using CGEN. -*- C -*-
375fd0b74Schristos CGEN: Cpu tools GENerator
475fd0b74Schristos
575fd0b74Schristos THIS FILE IS MACHINE GENERATED WITH CGEN.
675fd0b74Schristos - the resultant file is machine generated, cgen-asm.in isn't
775fd0b74Schristos
8*e992f068Schristos Copyright (C) 1996-2022 Free Software Foundation, Inc.
975fd0b74Schristos
1075fd0b74Schristos This file is part of libopcodes.
1175fd0b74Schristos
1275fd0b74Schristos This library is free software; you can redistribute it and/or modify
1375fd0b74Schristos it under the terms of the GNU General Public License as published by
1475fd0b74Schristos the Free Software Foundation; either version 3, or (at your option)
1575fd0b74Schristos any later version.
1675fd0b74Schristos
1775fd0b74Schristos It is distributed in the hope that it will be useful, but WITHOUT
1875fd0b74Schristos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1975fd0b74Schristos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
2075fd0b74Schristos License for more details.
2175fd0b74Schristos
2275fd0b74Schristos You should have received a copy of the GNU General Public License
2375fd0b74Schristos along with this program; if not, write to the Free Software Foundation, Inc.,
2475fd0b74Schristos 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
2575fd0b74Schristos
2675fd0b74Schristos
2775fd0b74Schristos /* ??? Eventually more and more of this stuff can go to cpu-independent files.
2875fd0b74Schristos Keep that in mind. */
2975fd0b74Schristos
3075fd0b74Schristos #include "sysdep.h"
3175fd0b74Schristos #include <stdio.h>
3275fd0b74Schristos #include "ansidecl.h"
3375fd0b74Schristos #include "bfd.h"
3475fd0b74Schristos #include "symcat.h"
3575fd0b74Schristos #include "or1k-desc.h"
3675fd0b74Schristos #include "or1k-opc.h"
3775fd0b74Schristos #include "opintl.h"
3875fd0b74Schristos #include "xregex.h"
3975fd0b74Schristos #include "libiberty.h"
4075fd0b74Schristos #include "safe-ctype.h"
4175fd0b74Schristos
4275fd0b74Schristos #undef min
4375fd0b74Schristos #define min(a,b) ((a) < (b) ? (a) : (b))
4475fd0b74Schristos #undef max
4575fd0b74Schristos #define max(a,b) ((a) > (b) ? (a) : (b))
4675fd0b74Schristos
4775fd0b74Schristos static const char * parse_insn_normal
4875fd0b74Schristos (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
4975fd0b74Schristos
5075fd0b74Schristos /* -- assembler routines inserted here. */
5175fd0b74Schristos
5275fd0b74Schristos /* -- asm.c */
5375fd0b74Schristos
5475fd0b74Schristos static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
55012573ebSchristos static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
56012573ebSchristos static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
5775fd0b74Schristos
5875fd0b74Schristos #define CGEN_VERBOSE_ASSEMBLER_ERRORS
5975fd0b74Schristos
6075fd0b74Schristos static const char *
parse_disp26(CGEN_CPU_DESC cd,const char ** strp,int opindex,int opinfo ATTRIBUTE_UNUSED,enum cgen_parse_operand_result * resultp,bfd_vma * valuep)6175fd0b74Schristos parse_disp26 (CGEN_CPU_DESC cd,
6275fd0b74Schristos const char ** strp,
6375fd0b74Schristos int opindex,
64012573ebSchristos int opinfo ATTRIBUTE_UNUSED,
6575fd0b74Schristos enum cgen_parse_operand_result * resultp,
6675fd0b74Schristos bfd_vma * valuep)
6775fd0b74Schristos {
68012573ebSchristos const char *str = *strp;
6975fd0b74Schristos const char *errmsg = NULL;
70012573ebSchristos bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
7175fd0b74Schristos
72012573ebSchristos if (strncasecmp (str, "plta(", 5) == 0)
7375fd0b74Schristos {
74012573ebSchristos *strp = str + 5;
75012573ebSchristos reloc = BFD_RELOC_OR1K_PLTA26;
7675fd0b74Schristos }
77012573ebSchristos else if (strncasecmp (str, "plt(", 4) == 0)
78012573ebSchristos {
79012573ebSchristos *strp = str + 4;
80012573ebSchristos reloc = BFD_RELOC_OR1K_PLT26;
81012573ebSchristos }
82012573ebSchristos
83012573ebSchristos errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
84012573ebSchristos
85012573ebSchristos if (reloc != BFD_RELOC_OR1K_REL_26)
86012573ebSchristos {
87012573ebSchristos if (**strp != ')')
88012573ebSchristos errmsg = MISSING_CLOSING_PARENTHESIS;
89012573ebSchristos else
90012573ebSchristos ++*strp;
91012573ebSchristos }
92012573ebSchristos
93012573ebSchristos return errmsg;
9475fd0b74Schristos }
9575fd0b74Schristos
9675fd0b74Schristos static const char *
parse_disp21(CGEN_CPU_DESC cd,const char ** strp,int opindex,int opinfo ATTRIBUTE_UNUSED,enum cgen_parse_operand_result * resultp,bfd_vma * valuep)97012573ebSchristos parse_disp21 (CGEN_CPU_DESC cd,
98012573ebSchristos const char ** strp,
99012573ebSchristos int opindex,
100012573ebSchristos int opinfo ATTRIBUTE_UNUSED,
101012573ebSchristos enum cgen_parse_operand_result * resultp,
102012573ebSchristos bfd_vma * valuep)
103012573ebSchristos {
104012573ebSchristos const char *str = *strp;
105012573ebSchristos const char *errmsg = NULL;
106012573ebSchristos bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
107012573ebSchristos
108012573ebSchristos if (strncasecmp (str, "got(", 4) == 0)
109012573ebSchristos {
110012573ebSchristos *strp = str + 4;
111012573ebSchristos reloc = BFD_RELOC_OR1K_GOT_PG21;
112012573ebSchristos }
113012573ebSchristos else if (strncasecmp (str, "tlsgd(", 6) == 0)
114012573ebSchristos {
115012573ebSchristos *strp = str + 6;
116012573ebSchristos reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
117012573ebSchristos }
118012573ebSchristos else if (strncasecmp (str, "tlsldm(", 7) == 0)
119012573ebSchristos {
120012573ebSchristos *strp = str + 7;
121012573ebSchristos reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
122012573ebSchristos }
123012573ebSchristos else if (strncasecmp (str, "gottp(", 6) == 0)
124012573ebSchristos {
125012573ebSchristos *strp = str + 6;
126012573ebSchristos reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
127012573ebSchristos }
128012573ebSchristos
129012573ebSchristos errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
130012573ebSchristos
131012573ebSchristos if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
132012573ebSchristos {
133012573ebSchristos if (**strp != ')')
134012573ebSchristos errmsg = MISSING_CLOSING_PARENTHESIS;
135012573ebSchristos else
136012573ebSchristos ++*strp;
137012573ebSchristos }
138012573ebSchristos
139012573ebSchristos return errmsg;
140012573ebSchristos }
141012573ebSchristos
142012573ebSchristos enum or1k_rclass
143012573ebSchristos {
144012573ebSchristos RCLASS_DIRECT = 0,
145012573ebSchristos RCLASS_GOT = 1,
146012573ebSchristos RCLASS_GOTPC = 2,
147012573ebSchristos RCLASS_GOTOFF = 3,
148012573ebSchristos RCLASS_TLSGD = 4,
149012573ebSchristos RCLASS_TLSLDM = 5,
150012573ebSchristos RCLASS_DTPOFF = 6,
151012573ebSchristos RCLASS_GOTTPOFF = 7,
152012573ebSchristos RCLASS_TPOFF = 8,
153012573ebSchristos };
154012573ebSchristos
155012573ebSchristos enum or1k_rtype
156012573ebSchristos {
157012573ebSchristos RTYPE_LO = 0,
158012573ebSchristos RTYPE_SLO = 1,
159012573ebSchristos RTYPE_PO = 2,
160012573ebSchristos RTYPE_SPO = 3,
161012573ebSchristos RTYPE_HI = 4,
162012573ebSchristos RTYPE_AHI = 5,
163012573ebSchristos };
164012573ebSchristos
165012573ebSchristos #define RCLASS_SHIFT 3
166012573ebSchristos #define RTYPE_MASK 7
167012573ebSchristos
168012573ebSchristos static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
169012573ebSchristos { BFD_RELOC_LO16,
170012573ebSchristos BFD_RELOC_OR1K_SLO16,
171012573ebSchristos BFD_RELOC_OR1K_LO13,
172012573ebSchristos BFD_RELOC_OR1K_SLO13,
173012573ebSchristos BFD_RELOC_HI16,
174012573ebSchristos BFD_RELOC_HI16_S, },
175012573ebSchristos { BFD_RELOC_OR1K_GOT16,
176012573ebSchristos BFD_RELOC_UNUSED,
177012573ebSchristos BFD_RELOC_OR1K_GOT_LO13,
178012573ebSchristos BFD_RELOC_UNUSED,
179012573ebSchristos BFD_RELOC_UNUSED,
180*e992f068Schristos BFD_RELOC_OR1K_GOT_AHI16 },
181012573ebSchristos { BFD_RELOC_OR1K_GOTPC_LO16,
182012573ebSchristos BFD_RELOC_UNUSED,
183012573ebSchristos BFD_RELOC_UNUSED,
184012573ebSchristos BFD_RELOC_UNUSED,
185012573ebSchristos BFD_RELOC_OR1K_GOTPC_HI16,
186012573ebSchristos BFD_RELOC_UNUSED },
187012573ebSchristos { BFD_RELOC_LO16_GOTOFF,
188012573ebSchristos BFD_RELOC_OR1K_GOTOFF_SLO16,
189012573ebSchristos BFD_RELOC_UNUSED,
190012573ebSchristos BFD_RELOC_UNUSED,
191012573ebSchristos BFD_RELOC_HI16_GOTOFF,
192012573ebSchristos BFD_RELOC_HI16_S_GOTOFF },
193012573ebSchristos { BFD_RELOC_OR1K_TLS_GD_LO16,
194012573ebSchristos BFD_RELOC_UNUSED,
195012573ebSchristos BFD_RELOC_OR1K_TLS_GD_LO13,
196012573ebSchristos BFD_RELOC_UNUSED,
197012573ebSchristos BFD_RELOC_OR1K_TLS_GD_HI16,
198012573ebSchristos BFD_RELOC_UNUSED },
199012573ebSchristos { BFD_RELOC_OR1K_TLS_LDM_LO16,
200012573ebSchristos BFD_RELOC_UNUSED,
201012573ebSchristos BFD_RELOC_OR1K_TLS_LDM_LO13,
202012573ebSchristos BFD_RELOC_UNUSED,
203012573ebSchristos BFD_RELOC_OR1K_TLS_LDM_HI16,
204012573ebSchristos BFD_RELOC_UNUSED },
205012573ebSchristos { BFD_RELOC_OR1K_TLS_LDO_LO16,
206012573ebSchristos BFD_RELOC_UNUSED,
207012573ebSchristos BFD_RELOC_UNUSED,
208012573ebSchristos BFD_RELOC_UNUSED,
209012573ebSchristos BFD_RELOC_OR1K_TLS_LDO_HI16,
210012573ebSchristos BFD_RELOC_UNUSED },
211012573ebSchristos { BFD_RELOC_OR1K_TLS_IE_LO16,
212012573ebSchristos BFD_RELOC_UNUSED,
213012573ebSchristos BFD_RELOC_OR1K_TLS_IE_LO13,
214012573ebSchristos BFD_RELOC_UNUSED,
215012573ebSchristos BFD_RELOC_OR1K_TLS_IE_HI16,
216012573ebSchristos BFD_RELOC_OR1K_TLS_IE_AHI16 },
217012573ebSchristos { BFD_RELOC_OR1K_TLS_LE_LO16,
218012573ebSchristos BFD_RELOC_OR1K_TLS_LE_SLO16,
219012573ebSchristos BFD_RELOC_UNUSED,
220012573ebSchristos BFD_RELOC_UNUSED,
221012573ebSchristos BFD_RELOC_OR1K_TLS_LE_HI16,
222012573ebSchristos BFD_RELOC_OR1K_TLS_LE_AHI16 },
223012573ebSchristos };
224012573ebSchristos
225012573ebSchristos static int
parse_reloc(const char ** strp)226012573ebSchristos parse_reloc (const char **strp)
227012573ebSchristos {
228012573ebSchristos const char *str = *strp;
229012573ebSchristos enum or1k_rclass cls = RCLASS_DIRECT;
230012573ebSchristos enum or1k_rtype typ;
231012573ebSchristos
232012573ebSchristos if (strncasecmp (str, "got(", 4) == 0)
233012573ebSchristos {
234012573ebSchristos *strp = str + 4;
235012573ebSchristos return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
236012573ebSchristos }
237012573ebSchristos if (strncasecmp (str, "gotpo(", 6) == 0)
238012573ebSchristos {
239012573ebSchristos *strp = str + 6;
240012573ebSchristos return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
241012573ebSchristos }
242012573ebSchristos if (strncasecmp (str, "gottppo(", 8) == 0)
243012573ebSchristos {
244012573ebSchristos *strp = str + 8;
245012573ebSchristos return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
246012573ebSchristos }
247012573ebSchristos
248012573ebSchristos if (strncasecmp (str, "gotpc", 5) == 0)
249012573ebSchristos {
250012573ebSchristos str += 5;
251012573ebSchristos cls = RCLASS_GOTPC;
252012573ebSchristos }
253012573ebSchristos else if (strncasecmp (str, "gotoff", 6) == 0)
254012573ebSchristos {
255012573ebSchristos str += 6;
256012573ebSchristos cls = RCLASS_GOTOFF;
257012573ebSchristos }
258012573ebSchristos else if (strncasecmp (str, "tlsgd", 5) == 0)
259012573ebSchristos {
260012573ebSchristos str += 5;
261012573ebSchristos cls = RCLASS_TLSGD;
262012573ebSchristos }
263012573ebSchristos else if (strncasecmp (str, "tlsldm", 6) == 0)
264012573ebSchristos {
265012573ebSchristos str += 6;
266012573ebSchristos cls = RCLASS_TLSLDM;
267012573ebSchristos }
268012573ebSchristos else if (strncasecmp (str, "dtpoff", 6) == 0)
269012573ebSchristos {
270012573ebSchristos str += 6;
271012573ebSchristos cls = RCLASS_DTPOFF;
272012573ebSchristos }
273012573ebSchristos else if (strncasecmp (str, "gottpoff", 8) == 0)
274012573ebSchristos {
275012573ebSchristos str += 8;
276012573ebSchristos cls = RCLASS_GOTTPOFF;
277012573ebSchristos }
278012573ebSchristos else if (strncasecmp (str, "tpoff", 5) == 0)
279012573ebSchristos {
280012573ebSchristos str += 5;
281012573ebSchristos cls = RCLASS_TPOFF;
282012573ebSchristos }
283*e992f068Schristos else if (strncasecmp (str, "got", 3) == 0)
284*e992f068Schristos {
285*e992f068Schristos str += 3;
286*e992f068Schristos cls = RCLASS_GOT;
287*e992f068Schristos }
288012573ebSchristos
289012573ebSchristos if (strncasecmp (str, "hi(", 3) == 0)
290012573ebSchristos {
291012573ebSchristos str += 3;
292012573ebSchristos typ = RTYPE_HI;
293012573ebSchristos }
294012573ebSchristos else if (strncasecmp (str, "lo(", 3) == 0)
295012573ebSchristos {
296012573ebSchristos str += 3;
297012573ebSchristos typ = RTYPE_LO;
298012573ebSchristos }
299012573ebSchristos else if (strncasecmp (str, "ha(", 3) == 0)
300012573ebSchristos {
301012573ebSchristos str += 3;
302012573ebSchristos typ = RTYPE_AHI;
303012573ebSchristos }
304012573ebSchristos else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
305012573ebSchristos {
306012573ebSchristos str += 3;
307012573ebSchristos typ = RTYPE_PO;
308012573ebSchristos }
309012573ebSchristos else
310012573ebSchristos return -1;
311012573ebSchristos
312012573ebSchristos *strp = str;
313012573ebSchristos return (cls << RCLASS_SHIFT) | typ;
314012573ebSchristos }
315012573ebSchristos
316012573ebSchristos static const char *
parse_imm16(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep,int splitp)317012573ebSchristos parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
318012573ebSchristos long *valuep, int splitp)
31975fd0b74Schristos {
32075fd0b74Schristos const char *errmsg;
32175fd0b74Schristos enum cgen_parse_operand_result result_type;
322012573ebSchristos bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
323012573ebSchristos enum or1k_rtype reloc_type;
324012573ebSchristos int reloc_code;
325012573ebSchristos bfd_vma ret;
32675fd0b74Schristos
32775fd0b74Schristos if (**strp == '#')
32875fd0b74Schristos ++*strp;
32975fd0b74Schristos
330012573ebSchristos reloc_code = parse_reloc (strp);
331012573ebSchristos reloc_type = reloc_code & RTYPE_MASK;
332012573ebSchristos if (reloc_code >= 0)
333012573ebSchristos {
334012573ebSchristos enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
335012573ebSchristos if (splitp)
336012573ebSchristos {
337012573ebSchristos if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
338012573ebSchristos && reloc_class != RCLASS_GOT)
339012573ebSchristos /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
340012573ebSchristos reloc_type |= 1;
341012573ebSchristos else
342012573ebSchristos return INVALID_STORE_RELOC;
343012573ebSchristos }
344012573ebSchristos reloc = or1k_imm16_relocs[reloc_class][reloc_type];
345012573ebSchristos }
346012573ebSchristos
347012573ebSchristos if (reloc != BFD_RELOC_UNUSED)
34875fd0b74Schristos {
34975fd0b74Schristos bfd_vma value;
35075fd0b74Schristos
351012573ebSchristos errmsg = cgen_parse_address (cd, strp, opindex, reloc,
35275fd0b74Schristos &result_type, &value);
35375fd0b74Schristos if (**strp != ')')
35475fd0b74Schristos errmsg = MISSING_CLOSING_PARENTHESIS;
35575fd0b74Schristos ++*strp;
35675fd0b74Schristos
35775fd0b74Schristos ret = value;
35875fd0b74Schristos
359012573ebSchristos if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
360012573ebSchristos switch (reloc_type)
36175fd0b74Schristos {
362012573ebSchristos case RTYPE_AHI:
363012573ebSchristos ret += 0x8000;
364012573ebSchristos /* FALLTHRU */
365012573ebSchristos case RTYPE_HI:
36675fd0b74Schristos ret >>= 16;
367012573ebSchristos /* FALLTHRU */
368012573ebSchristos case RTYPE_LO:
369012573ebSchristos case RTYPE_SLO:
37075fd0b74Schristos ret &= 0xffff;
37175fd0b74Schristos ret = (ret ^ 0x8000) - 0x8000;
372012573ebSchristos break;
373012573ebSchristos case RTYPE_PO:
374012573ebSchristos case RTYPE_SPO:
375012573ebSchristos ret &= 0x1fff;
376012573ebSchristos break;
377012573ebSchristos default:
378012573ebSchristos errmsg = INVALID_RELOC_TYPE;
37975fd0b74Schristos }
38075fd0b74Schristos }
38175fd0b74Schristos else
38275fd0b74Schristos {
38375fd0b74Schristos long value;
38475fd0b74Schristos errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
38575fd0b74Schristos ret = value;
38675fd0b74Schristos }
38775fd0b74Schristos
38875fd0b74Schristos if (errmsg == NULL)
38975fd0b74Schristos *valuep = ret;
39075fd0b74Schristos
39175fd0b74Schristos return errmsg;
39275fd0b74Schristos }
39375fd0b74Schristos
39475fd0b74Schristos static const char *
parse_simm16(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)395012573ebSchristos parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
39675fd0b74Schristos {
397012573ebSchristos return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
398012573ebSchristos }
39975fd0b74Schristos
400012573ebSchristos static const char *
parse_simm16_split(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)401012573ebSchristos parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
402012573ebSchristos long *valuep)
403012573ebSchristos {
404012573ebSchristos return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
405012573ebSchristos }
406012573ebSchristos
407012573ebSchristos static const char *
parse_uimm16(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)408012573ebSchristos parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
409012573ebSchristos unsigned long *valuep)
410012573ebSchristos {
411012573ebSchristos const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
41275fd0b74Schristos if (errmsg == NULL)
41375fd0b74Schristos *valuep &= 0xffff;
41475fd0b74Schristos return errmsg;
41575fd0b74Schristos }
41675fd0b74Schristos
417012573ebSchristos static const char *
parse_uimm16_split(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)418012573ebSchristos parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
419012573ebSchristos unsigned long *valuep)
420012573ebSchristos {
421012573ebSchristos const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
422012573ebSchristos if (errmsg == NULL)
423012573ebSchristos *valuep &= 0xffff;
424012573ebSchristos return errmsg;
425012573ebSchristos }
426012573ebSchristos
427012573ebSchristos /* Parse register pairs with syntax rA,rB to a flag + rA value. */
428012573ebSchristos
429012573ebSchristos static const char *
parse_regpair(CGEN_CPU_DESC cd,const char ** strp,int opindex ATTRIBUTE_UNUSED,unsigned long * valuep)430012573ebSchristos parse_regpair (CGEN_CPU_DESC cd, const char **strp,
431012573ebSchristos int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
432012573ebSchristos {
433012573ebSchristos long reg1_index;
434012573ebSchristos long reg2_index;
435012573ebSchristos const char *errmsg;
436012573ebSchristos
437012573ebSchristos /* The first part should just be a register. */
438012573ebSchristos errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
439012573ebSchristos ®1_index);
440012573ebSchristos
441012573ebSchristos /* If that worked skip the comma separator. */
442012573ebSchristos if (errmsg == NULL)
443012573ebSchristos {
444012573ebSchristos if (**strp == ',')
445012573ebSchristos ++*strp;
446012573ebSchristos else
447012573ebSchristos errmsg = "Unexpected character, expected ','";
448012573ebSchristos }
449012573ebSchristos
450012573ebSchristos /* If that worked the next part is just another register. */
451012573ebSchristos if (errmsg == NULL)
452012573ebSchristos errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
453012573ebSchristos ®2_index);
454012573ebSchristos
455012573ebSchristos /* Validate the register pair is valid and create the output value. */
456012573ebSchristos if (errmsg == NULL)
457012573ebSchristos {
458012573ebSchristos int regoffset = reg2_index - reg1_index;
459012573ebSchristos
460012573ebSchristos if (regoffset == 1 || regoffset == 2)
461012573ebSchristos {
462012573ebSchristos unsigned short offsetmask;
463012573ebSchristos unsigned short value;
464012573ebSchristos
465012573ebSchristos offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
466012573ebSchristos value = offsetmask | reg1_index;
467012573ebSchristos
468012573ebSchristos *valuep = value;
469012573ebSchristos }
470012573ebSchristos else
471012573ebSchristos errmsg = "Invalid register pair, offset not 1 or 2.";
472012573ebSchristos }
473012573ebSchristos
474012573ebSchristos return errmsg;
475012573ebSchristos }
476012573ebSchristos
47775fd0b74Schristos /* -- */
47875fd0b74Schristos
47975fd0b74Schristos const char * or1k_cgen_parse_operand
48075fd0b74Schristos (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
48175fd0b74Schristos
48275fd0b74Schristos /* Main entry point for operand parsing.
48375fd0b74Schristos
48475fd0b74Schristos This function is basically just a big switch statement. Earlier versions
48575fd0b74Schristos used tables to look up the function to use, but
48675fd0b74Schristos - if the table contains both assembler and disassembler functions then
48775fd0b74Schristos the disassembler contains much of the assembler and vice-versa,
48875fd0b74Schristos - there's a lot of inlining possibilities as things grow,
48975fd0b74Schristos - using a switch statement avoids the function call overhead.
49075fd0b74Schristos
49175fd0b74Schristos This function could be moved into `parse_insn_normal', but keeping it
49275fd0b74Schristos separate makes clear the interface between `parse_insn_normal' and each of
49375fd0b74Schristos the handlers. */
49475fd0b74Schristos
49575fd0b74Schristos const char *
or1k_cgen_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp,CGEN_FIELDS * fields)49675fd0b74Schristos or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
49775fd0b74Schristos int opindex,
49875fd0b74Schristos const char ** strp,
49975fd0b74Schristos CGEN_FIELDS * fields)
50075fd0b74Schristos {
50175fd0b74Schristos const char * errmsg = NULL;
50275fd0b74Schristos /* Used by scalar operands that still need to be parsed. */
50375fd0b74Schristos long junk ATTRIBUTE_UNUSED;
50475fd0b74Schristos
50575fd0b74Schristos switch (opindex)
50675fd0b74Schristos {
507012573ebSchristos case OR1K_OPERAND_DISP21 :
508012573ebSchristos {
509012573ebSchristos bfd_vma value = 0;
510012573ebSchristos errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL, & value);
511012573ebSchristos fields->f_disp21 = value;
512012573ebSchristos }
513012573ebSchristos break;
51475fd0b74Schristos case OR1K_OPERAND_DISP26 :
51575fd0b74Schristos {
51675fd0b74Schristos bfd_vma value = 0;
51775fd0b74Schristos errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL, & value);
51875fd0b74Schristos fields->f_disp26 = value;
51975fd0b74Schristos }
52075fd0b74Schristos break;
52175fd0b74Schristos case OR1K_OPERAND_RA :
52275fd0b74Schristos errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
52375fd0b74Schristos break;
524012573ebSchristos case OR1K_OPERAND_RAD32F :
525012573ebSchristos errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
526012573ebSchristos break;
527012573ebSchristos case OR1K_OPERAND_RADI :
528012573ebSchristos errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
52975fd0b74Schristos break;
53075fd0b74Schristos case OR1K_OPERAND_RASF :
53175fd0b74Schristos errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
53275fd0b74Schristos break;
53375fd0b74Schristos case OR1K_OPERAND_RB :
53475fd0b74Schristos errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
53575fd0b74Schristos break;
536012573ebSchristos case OR1K_OPERAND_RBD32F :
537012573ebSchristos errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
538012573ebSchristos break;
539012573ebSchristos case OR1K_OPERAND_RBDI :
540012573ebSchristos errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
54175fd0b74Schristos break;
54275fd0b74Schristos case OR1K_OPERAND_RBSF :
54375fd0b74Schristos errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
54475fd0b74Schristos break;
54575fd0b74Schristos case OR1K_OPERAND_RD :
54675fd0b74Schristos errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
54775fd0b74Schristos break;
548012573ebSchristos case OR1K_OPERAND_RDD32F :
549012573ebSchristos errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
550012573ebSchristos break;
551012573ebSchristos case OR1K_OPERAND_RDDI :
552012573ebSchristos errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
553012573ebSchristos break;
55475fd0b74Schristos case OR1K_OPERAND_RDSF :
55575fd0b74Schristos errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
55675fd0b74Schristos break;
55775fd0b74Schristos case OR1K_OPERAND_SIMM16 :
55875fd0b74Schristos errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
55975fd0b74Schristos break;
56075fd0b74Schristos case OR1K_OPERAND_SIMM16_SPLIT :
561012573ebSchristos errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
56275fd0b74Schristos break;
56375fd0b74Schristos case OR1K_OPERAND_UIMM16 :
56475fd0b74Schristos errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
56575fd0b74Schristos break;
56675fd0b74Schristos case OR1K_OPERAND_UIMM16_SPLIT :
567012573ebSchristos errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
56875fd0b74Schristos break;
56975fd0b74Schristos case OR1K_OPERAND_UIMM6 :
57075fd0b74Schristos errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
57175fd0b74Schristos break;
57275fd0b74Schristos
57375fd0b74Schristos default :
57475fd0b74Schristos /* xgettext:c-format */
575ede78133Schristos opcodes_error_handler
576ede78133Schristos (_("internal error: unrecognized field %d while parsing"),
577ede78133Schristos opindex);
57875fd0b74Schristos abort ();
57975fd0b74Schristos }
58075fd0b74Schristos
58175fd0b74Schristos return errmsg;
58275fd0b74Schristos }
58375fd0b74Schristos
58475fd0b74Schristos cgen_parse_fn * const or1k_cgen_parse_handlers[] =
58575fd0b74Schristos {
58675fd0b74Schristos parse_insn_normal,
58775fd0b74Schristos };
58875fd0b74Schristos
58975fd0b74Schristos void
or1k_cgen_init_asm(CGEN_CPU_DESC cd)59075fd0b74Schristos or1k_cgen_init_asm (CGEN_CPU_DESC cd)
59175fd0b74Schristos {
59275fd0b74Schristos or1k_cgen_init_opcode_table (cd);
59375fd0b74Schristos or1k_cgen_init_ibld_table (cd);
59475fd0b74Schristos cd->parse_handlers = & or1k_cgen_parse_handlers[0];
59575fd0b74Schristos cd->parse_operand = or1k_cgen_parse_operand;
59675fd0b74Schristos #ifdef CGEN_ASM_INIT_HOOK
59775fd0b74Schristos CGEN_ASM_INIT_HOOK
59875fd0b74Schristos #endif
59975fd0b74Schristos }
60075fd0b74Schristos
60175fd0b74Schristos
60275fd0b74Schristos
60375fd0b74Schristos /* Regex construction routine.
60475fd0b74Schristos
60575fd0b74Schristos This translates an opcode syntax string into a regex string,
60675fd0b74Schristos by replacing any non-character syntax element (such as an
60775fd0b74Schristos opcode) with the pattern '.*'
60875fd0b74Schristos
60975fd0b74Schristos It then compiles the regex and stores it in the opcode, for
61075fd0b74Schristos later use by or1k_cgen_assemble_insn
61175fd0b74Schristos
61275fd0b74Schristos Returns NULL for success, an error message for failure. */
61375fd0b74Schristos
61475fd0b74Schristos char *
or1k_cgen_build_insn_regex(CGEN_INSN * insn)61575fd0b74Schristos or1k_cgen_build_insn_regex (CGEN_INSN *insn)
61675fd0b74Schristos {
61775fd0b74Schristos CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
61875fd0b74Schristos const char *mnem = CGEN_INSN_MNEMONIC (insn);
61975fd0b74Schristos char rxbuf[CGEN_MAX_RX_ELEMENTS];
62075fd0b74Schristos char *rx = rxbuf;
62175fd0b74Schristos const CGEN_SYNTAX_CHAR_TYPE *syn;
62275fd0b74Schristos int reg_err;
62375fd0b74Schristos
62475fd0b74Schristos syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
62575fd0b74Schristos
62675fd0b74Schristos /* Mnemonics come first in the syntax string. */
62775fd0b74Schristos if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
62875fd0b74Schristos return _("missing mnemonic in syntax string");
62975fd0b74Schristos ++syn;
63075fd0b74Schristos
63175fd0b74Schristos /* Generate a case sensitive regular expression that emulates case
63275fd0b74Schristos insensitive matching in the "C" locale. We cannot generate a case
63375fd0b74Schristos insensitive regular expression because in Turkish locales, 'i' and 'I'
63475fd0b74Schristos are not equal modulo case conversion. */
63575fd0b74Schristos
63675fd0b74Schristos /* Copy the literal mnemonic out of the insn. */
63775fd0b74Schristos for (; *mnem; mnem++)
63875fd0b74Schristos {
63975fd0b74Schristos char c = *mnem;
64075fd0b74Schristos
64175fd0b74Schristos if (ISALPHA (c))
64275fd0b74Schristos {
64375fd0b74Schristos *rx++ = '[';
64475fd0b74Schristos *rx++ = TOLOWER (c);
64575fd0b74Schristos *rx++ = TOUPPER (c);
64675fd0b74Schristos *rx++ = ']';
64775fd0b74Schristos }
64875fd0b74Schristos else
64975fd0b74Schristos *rx++ = c;
65075fd0b74Schristos }
65175fd0b74Schristos
65275fd0b74Schristos /* Copy any remaining literals from the syntax string into the rx. */
65375fd0b74Schristos for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
65475fd0b74Schristos {
65575fd0b74Schristos if (CGEN_SYNTAX_CHAR_P (* syn))
65675fd0b74Schristos {
65775fd0b74Schristos char c = CGEN_SYNTAX_CHAR (* syn);
65875fd0b74Schristos
65975fd0b74Schristos switch (c)
66075fd0b74Schristos {
66175fd0b74Schristos /* Escape any regex metacharacters in the syntax. */
66275fd0b74Schristos case '.': case '[': case '\\':
66375fd0b74Schristos case '*': case '^': case '$':
66475fd0b74Schristos
66575fd0b74Schristos #ifdef CGEN_ESCAPE_EXTENDED_REGEX
66675fd0b74Schristos case '?': case '{': case '}':
66775fd0b74Schristos case '(': case ')': case '*':
66875fd0b74Schristos case '|': case '+': case ']':
66975fd0b74Schristos #endif
67075fd0b74Schristos *rx++ = '\\';
67175fd0b74Schristos *rx++ = c;
67275fd0b74Schristos break;
67375fd0b74Schristos
67475fd0b74Schristos default:
67575fd0b74Schristos if (ISALPHA (c))
67675fd0b74Schristos {
67775fd0b74Schristos *rx++ = '[';
67875fd0b74Schristos *rx++ = TOLOWER (c);
67975fd0b74Schristos *rx++ = TOUPPER (c);
68075fd0b74Schristos *rx++ = ']';
68175fd0b74Schristos }
68275fd0b74Schristos else
68375fd0b74Schristos *rx++ = c;
68475fd0b74Schristos break;
68575fd0b74Schristos }
68675fd0b74Schristos }
68775fd0b74Schristos else
68875fd0b74Schristos {
68975fd0b74Schristos /* Replace non-syntax fields with globs. */
69075fd0b74Schristos *rx++ = '.';
69175fd0b74Schristos *rx++ = '*';
69275fd0b74Schristos }
69375fd0b74Schristos }
69475fd0b74Schristos
69575fd0b74Schristos /* Trailing whitespace ok. */
69675fd0b74Schristos * rx++ = '[';
69775fd0b74Schristos * rx++ = ' ';
69875fd0b74Schristos * rx++ = '\t';
69975fd0b74Schristos * rx++ = ']';
70075fd0b74Schristos * rx++ = '*';
70175fd0b74Schristos
70275fd0b74Schristos /* But anchor it after that. */
70375fd0b74Schristos * rx++ = '$';
70475fd0b74Schristos * rx = '\0';
70575fd0b74Schristos
70675fd0b74Schristos CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
70775fd0b74Schristos reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
70875fd0b74Schristos
70975fd0b74Schristos if (reg_err == 0)
71075fd0b74Schristos return NULL;
71175fd0b74Schristos else
71275fd0b74Schristos {
71375fd0b74Schristos static char msg[80];
71475fd0b74Schristos
71575fd0b74Schristos regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
71675fd0b74Schristos regfree ((regex_t *) CGEN_INSN_RX (insn));
71775fd0b74Schristos free (CGEN_INSN_RX (insn));
71875fd0b74Schristos (CGEN_INSN_RX (insn)) = NULL;
71975fd0b74Schristos return msg;
72075fd0b74Schristos }
72175fd0b74Schristos }
72275fd0b74Schristos
72375fd0b74Schristos
72475fd0b74Schristos /* Default insn parser.
72575fd0b74Schristos
72675fd0b74Schristos The syntax string is scanned and operands are parsed and stored in FIELDS.
72775fd0b74Schristos Relocs are queued as we go via other callbacks.
72875fd0b74Schristos
72975fd0b74Schristos ??? Note that this is currently an all-or-nothing parser. If we fail to
73075fd0b74Schristos parse the instruction, we return 0 and the caller will start over from
73175fd0b74Schristos the beginning. Backtracking will be necessary in parsing subexpressions,
73275fd0b74Schristos but that can be handled there. Not handling backtracking here may get
73375fd0b74Schristos expensive in the case of the m68k. Deal with later.
73475fd0b74Schristos
73575fd0b74Schristos Returns NULL for success, an error message for failure. */
73675fd0b74Schristos
73775fd0b74Schristos static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)73875fd0b74Schristos parse_insn_normal (CGEN_CPU_DESC cd,
73975fd0b74Schristos const CGEN_INSN *insn,
74075fd0b74Schristos const char **strp,
74175fd0b74Schristos CGEN_FIELDS *fields)
74275fd0b74Schristos {
74375fd0b74Schristos /* ??? Runtime added insns not handled yet. */
74475fd0b74Schristos const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
74575fd0b74Schristos const char *str = *strp;
74675fd0b74Schristos const char *errmsg;
74775fd0b74Schristos const char *p;
74875fd0b74Schristos const CGEN_SYNTAX_CHAR_TYPE * syn;
74975fd0b74Schristos #ifdef CGEN_MNEMONIC_OPERANDS
75075fd0b74Schristos /* FIXME: wip */
75175fd0b74Schristos int past_opcode_p;
75275fd0b74Schristos #endif
75375fd0b74Schristos
75475fd0b74Schristos /* For now we assume the mnemonic is first (there are no leading operands).
75575fd0b74Schristos We can parse it without needing to set up operand parsing.
75675fd0b74Schristos GAS's input scrubber will ensure mnemonics are lowercase, but we may
75775fd0b74Schristos not be called from GAS. */
75875fd0b74Schristos p = CGEN_INSN_MNEMONIC (insn);
75975fd0b74Schristos while (*p && TOLOWER (*p) == TOLOWER (*str))
76075fd0b74Schristos ++p, ++str;
76175fd0b74Schristos
76275fd0b74Schristos if (* p)
76375fd0b74Schristos return _("unrecognized instruction");
76475fd0b74Schristos
76575fd0b74Schristos #ifndef CGEN_MNEMONIC_OPERANDS
76675fd0b74Schristos if (* str && ! ISSPACE (* str))
76775fd0b74Schristos return _("unrecognized instruction");
76875fd0b74Schristos #endif
76975fd0b74Schristos
77075fd0b74Schristos CGEN_INIT_PARSE (cd);
77175fd0b74Schristos cgen_init_parse_operand (cd);
77275fd0b74Schristos #ifdef CGEN_MNEMONIC_OPERANDS
77375fd0b74Schristos past_opcode_p = 0;
77475fd0b74Schristos #endif
77575fd0b74Schristos
77675fd0b74Schristos /* We don't check for (*str != '\0') here because we want to parse
77775fd0b74Schristos any trailing fake arguments in the syntax string. */
77875fd0b74Schristos syn = CGEN_SYNTAX_STRING (syntax);
77975fd0b74Schristos
78075fd0b74Schristos /* Mnemonics come first for now, ensure valid string. */
78175fd0b74Schristos if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
78275fd0b74Schristos abort ();
78375fd0b74Schristos
78475fd0b74Schristos ++syn;
78575fd0b74Schristos
78675fd0b74Schristos while (* syn != 0)
78775fd0b74Schristos {
78875fd0b74Schristos /* Non operand chars must match exactly. */
78975fd0b74Schristos if (CGEN_SYNTAX_CHAR_P (* syn))
79075fd0b74Schristos {
79175fd0b74Schristos /* FIXME: While we allow for non-GAS callers above, we assume the
79275fd0b74Schristos first char after the mnemonic part is a space. */
79375fd0b74Schristos /* FIXME: We also take inappropriate advantage of the fact that
79475fd0b74Schristos GAS's input scrubber will remove extraneous blanks. */
79575fd0b74Schristos if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
79675fd0b74Schristos {
79775fd0b74Schristos #ifdef CGEN_MNEMONIC_OPERANDS
79875fd0b74Schristos if (CGEN_SYNTAX_CHAR(* syn) == ' ')
79975fd0b74Schristos past_opcode_p = 1;
80075fd0b74Schristos #endif
80175fd0b74Schristos ++ syn;
80275fd0b74Schristos ++ str;
80375fd0b74Schristos }
80475fd0b74Schristos else if (*str)
80575fd0b74Schristos {
80675fd0b74Schristos /* Syntax char didn't match. Can't be this insn. */
80775fd0b74Schristos static char msg [80];
80875fd0b74Schristos
80975fd0b74Schristos /* xgettext:c-format */
81075fd0b74Schristos sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
81175fd0b74Schristos CGEN_SYNTAX_CHAR(*syn), *str);
81275fd0b74Schristos return msg;
81375fd0b74Schristos }
81475fd0b74Schristos else
81575fd0b74Schristos {
81675fd0b74Schristos /* Ran out of input. */
81775fd0b74Schristos static char msg [80];
81875fd0b74Schristos
81975fd0b74Schristos /* xgettext:c-format */
82075fd0b74Schristos sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
82175fd0b74Schristos CGEN_SYNTAX_CHAR(*syn));
82275fd0b74Schristos return msg;
82375fd0b74Schristos }
82475fd0b74Schristos continue;
82575fd0b74Schristos }
82675fd0b74Schristos
82775fd0b74Schristos #ifdef CGEN_MNEMONIC_OPERANDS
82875fd0b74Schristos (void) past_opcode_p;
82975fd0b74Schristos #endif
83075fd0b74Schristos /* We have an operand of some sort. */
83175fd0b74Schristos errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
83275fd0b74Schristos if (errmsg)
83375fd0b74Schristos return errmsg;
83475fd0b74Schristos
83575fd0b74Schristos /* Done with this operand, continue with next one. */
83675fd0b74Schristos ++ syn;
83775fd0b74Schristos }
83875fd0b74Schristos
83975fd0b74Schristos /* If we're at the end of the syntax string, we're done. */
84075fd0b74Schristos if (* syn == 0)
84175fd0b74Schristos {
84275fd0b74Schristos /* FIXME: For the moment we assume a valid `str' can only contain
84375fd0b74Schristos blanks now. IE: We needn't try again with a longer version of
84475fd0b74Schristos the insn and it is assumed that longer versions of insns appear
84575fd0b74Schristos before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
84675fd0b74Schristos while (ISSPACE (* str))
84775fd0b74Schristos ++ str;
84875fd0b74Schristos
84975fd0b74Schristos if (* str != '\0')
85075fd0b74Schristos return _("junk at end of line"); /* FIXME: would like to include `str' */
85175fd0b74Schristos
85275fd0b74Schristos return NULL;
85375fd0b74Schristos }
85475fd0b74Schristos
85575fd0b74Schristos /* We couldn't parse it. */
85675fd0b74Schristos return _("unrecognized instruction");
85775fd0b74Schristos }
85875fd0b74Schristos
85975fd0b74Schristos /* Main entry point.
86075fd0b74Schristos This routine is called for each instruction to be assembled.
86175fd0b74Schristos STR points to the insn to be assembled.
86275fd0b74Schristos We assume all necessary tables have been initialized.
86375fd0b74Schristos The assembled instruction, less any fixups, is stored in BUF.
86475fd0b74Schristos Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
86575fd0b74Schristos still needs to be converted to target byte order, otherwise BUF is an array
86675fd0b74Schristos of bytes in target byte order.
86775fd0b74Schristos The result is a pointer to the insn's entry in the opcode table,
86875fd0b74Schristos or NULL if an error occured (an error message will have already been
86975fd0b74Schristos printed).
87075fd0b74Schristos
87175fd0b74Schristos Note that when processing (non-alias) macro-insns,
87275fd0b74Schristos this function recurses.
87375fd0b74Schristos
87475fd0b74Schristos ??? It's possible to make this cpu-independent.
87575fd0b74Schristos One would have to deal with a few minor things.
87675fd0b74Schristos At this point in time doing so would be more of a curiosity than useful
87775fd0b74Schristos [for example this file isn't _that_ big], but keeping the possibility in
87875fd0b74Schristos mind helps keep the design clean. */
87975fd0b74Schristos
88075fd0b74Schristos const CGEN_INSN *
or1k_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)88175fd0b74Schristos or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
88275fd0b74Schristos const char *str,
88375fd0b74Schristos CGEN_FIELDS *fields,
88475fd0b74Schristos CGEN_INSN_BYTES_PTR buf,
88575fd0b74Schristos char **errmsg)
88675fd0b74Schristos {
88775fd0b74Schristos const char *start;
88875fd0b74Schristos CGEN_INSN_LIST *ilist;
88975fd0b74Schristos const char *parse_errmsg = NULL;
89075fd0b74Schristos const char *insert_errmsg = NULL;
89175fd0b74Schristos int recognized_mnemonic = 0;
89275fd0b74Schristos
89375fd0b74Schristos /* Skip leading white space. */
89475fd0b74Schristos while (ISSPACE (* str))
89575fd0b74Schristos ++ str;
89675fd0b74Schristos
89775fd0b74Schristos /* The instructions are stored in hashed lists.
89875fd0b74Schristos Get the first in the list. */
89975fd0b74Schristos ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
90075fd0b74Schristos
90175fd0b74Schristos /* Keep looking until we find a match. */
90275fd0b74Schristos start = str;
90375fd0b74Schristos for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
90475fd0b74Schristos {
90575fd0b74Schristos const CGEN_INSN *insn = ilist->insn;
90675fd0b74Schristos recognized_mnemonic = 1;
90775fd0b74Schristos
90875fd0b74Schristos #ifdef CGEN_VALIDATE_INSN_SUPPORTED
90975fd0b74Schristos /* Not usually needed as unsupported opcodes
91075fd0b74Schristos shouldn't be in the hash lists. */
91175fd0b74Schristos /* Is this insn supported by the selected cpu? */
91275fd0b74Schristos if (! or1k_cgen_insn_supported (cd, insn))
91375fd0b74Schristos continue;
91475fd0b74Schristos #endif
91575fd0b74Schristos /* If the RELAXED attribute is set, this is an insn that shouldn't be
91675fd0b74Schristos chosen immediately. Instead, it is used during assembler/linker
91775fd0b74Schristos relaxation if possible. */
91875fd0b74Schristos if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
91975fd0b74Schristos continue;
92075fd0b74Schristos
92175fd0b74Schristos str = start;
92275fd0b74Schristos
92375fd0b74Schristos /* Skip this insn if str doesn't look right lexically. */
92475fd0b74Schristos if (CGEN_INSN_RX (insn) != NULL &&
92575fd0b74Schristos regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
92675fd0b74Schristos continue;
92775fd0b74Schristos
92875fd0b74Schristos /* Allow parse/insert handlers to obtain length of insn. */
92975fd0b74Schristos CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
93075fd0b74Schristos
93175fd0b74Schristos parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
93275fd0b74Schristos if (parse_errmsg != NULL)
93375fd0b74Schristos continue;
93475fd0b74Schristos
93575fd0b74Schristos /* ??? 0 is passed for `pc'. */
93675fd0b74Schristos insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
93775fd0b74Schristos (bfd_vma) 0);
93875fd0b74Schristos if (insert_errmsg != NULL)
93975fd0b74Schristos continue;
94075fd0b74Schristos
94175fd0b74Schristos /* It is up to the caller to actually output the insn and any
94275fd0b74Schristos queued relocs. */
94375fd0b74Schristos return insn;
94475fd0b74Schristos }
94575fd0b74Schristos
94675fd0b74Schristos {
94775fd0b74Schristos static char errbuf[150];
94875fd0b74Schristos const char *tmp_errmsg;
94975fd0b74Schristos #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
95075fd0b74Schristos #define be_verbose 1
95175fd0b74Schristos #else
95275fd0b74Schristos #define be_verbose 0
95375fd0b74Schristos #endif
95475fd0b74Schristos
95575fd0b74Schristos if (be_verbose)
95675fd0b74Schristos {
95775fd0b74Schristos /* If requesting verbose error messages, use insert_errmsg.
95875fd0b74Schristos Failing that, use parse_errmsg. */
95975fd0b74Schristos tmp_errmsg = (insert_errmsg ? insert_errmsg :
96075fd0b74Schristos parse_errmsg ? parse_errmsg :
96175fd0b74Schristos recognized_mnemonic ?
96275fd0b74Schristos _("unrecognized form of instruction") :
96375fd0b74Schristos _("unrecognized instruction"));
96475fd0b74Schristos
96575fd0b74Schristos if (strlen (start) > 50)
96675fd0b74Schristos /* xgettext:c-format */
96775fd0b74Schristos sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
96875fd0b74Schristos else
96975fd0b74Schristos /* xgettext:c-format */
97075fd0b74Schristos sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
97175fd0b74Schristos }
97275fd0b74Schristos else
97375fd0b74Schristos {
97475fd0b74Schristos if (strlen (start) > 50)
97575fd0b74Schristos /* xgettext:c-format */
97675fd0b74Schristos sprintf (errbuf, _("bad instruction `%.50s...'"), start);
97775fd0b74Schristos else
97875fd0b74Schristos /* xgettext:c-format */
97975fd0b74Schristos sprintf (errbuf, _("bad instruction `%.50s'"), start);
98075fd0b74Schristos }
98175fd0b74Schristos
98275fd0b74Schristos *errmsg = errbuf;
98375fd0b74Schristos return NULL;
98475fd0b74Schristos }
98575fd0b74Schristos }
986