1/* OpenRISC 1000 opcode support.  -*- C -*-
2   Copyright 2000-2014 Free Software Foundation, Inc.
3
4   Originally ontributed for OR32 by Red Hat Inc;
5
6   This file is part of the GNU Binutils.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, see <http://www.gnu.org/licenses/>. */
20
21/* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
22   appropriate in .cpu files, so it resides here.  This especially applies
23   to assembly/disassembly where parsing/printing can be quite involved.
24   Such things aren't really part of the specification of the cpu, per se,
25   so .cpu files provide the general framework and .opc files handle the
26   nitty-gritty details as necessary.
27
28   Each section is delimited with start and end markers.
29
30   <arch>-opc.h additions use: "-- opc.h"
31   <arch>-opc.c additions use: "-- opc.c"
32   <arch>-asm.c additions use: "-- asm.c"
33   <arch>-dis.c additions use: "-- dis.c"
34   <arch>-ibd.h additions use: "-- ibd.h"  */
35
36/* -- opc.h */
37
38#undef  CGEN_DIS_HASH_SIZE
39#define CGEN_DIS_HASH_SIZE 256
40#undef  CGEN_DIS_HASH
41#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
42
43/* -- */
44
45/* -- opc.c */
46/* -- */
47
48/* -- asm.c */
49
50static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
51
52#define CGEN_VERBOSE_ASSEMBLER_ERRORS
53
54static const char *
55parse_disp26 (CGEN_CPU_DESC cd,
56	      const char ** strp,
57	      int opindex,
58	      int opinfo,
59	      enum cgen_parse_operand_result * resultp,
60	      bfd_vma * valuep)
61{
62  const char *errmsg = NULL;
63  enum cgen_parse_operand_result result_type;
64
65  if (strncasecmp (*strp, "plt(", 4) == 0)
66    {
67      bfd_vma value;
68
69      *strp += 4;
70      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
71				   & result_type, & value);
72      if (**strp != ')')
73	return MISSING_CLOSING_PARENTHESIS;
74      ++*strp;
75      if (errmsg == NULL
76	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
77	value = (value >> 2) & 0xffff;
78      *valuep = value;
79      return errmsg;
80    }
81  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
82}
83
84static const char *
85parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
86{
87  const char *errmsg;
88  enum cgen_parse_operand_result result_type;
89  long ret;
90
91  if (**strp == '#')
92    ++*strp;
93
94  if (strncasecmp (*strp, "hi(", 3) == 0)
95    {
96      bfd_vma value;
97
98      *strp += 3;
99      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
100				   & result_type, & value);
101      if (**strp != ')')
102	errmsg = MISSING_CLOSING_PARENTHESIS;
103      ++*strp;
104
105      ret = value;
106
107      if (errmsg == NULL
108	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
109	{
110	  ret >>= 16;
111	  ret &= 0xffff;
112	  ret = (ret ^ 0x8000) - 0x8000;
113	}
114    }
115  else if (strncasecmp (*strp, "lo(", 3) == 0)
116    {
117      bfd_vma value;
118
119      *strp += 3;
120      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
121				   & result_type, & value);
122      if (**strp != ')')
123	return MISSING_CLOSING_PARENTHESIS;
124      ++*strp;
125
126      ret = value;
127
128      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
129	{
130	  ret &= 0xffff;
131	  ret = (ret ^ 0x8000) - 0x8000;
132	}
133    }
134  else if (strncasecmp (*strp, "got(", 4) == 0)
135    {
136      bfd_vma value;
137
138      *strp += 4;
139      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
140				   & result_type, & value);
141      if (**strp != ')')
142	return MISSING_CLOSING_PARENTHESIS;
143      ++*strp;
144      if (errmsg == NULL
145	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
146	value &= 0xffff;
147      *valuep = value;
148      return errmsg;
149    }
150  else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
151    {
152      bfd_vma value;
153
154      *strp += 8;
155      errmsg = cgen_parse_address (cd, strp, opindex,
156				   BFD_RELOC_OR1K_GOTPC_HI16,
157				   & result_type, & value);
158      if (**strp != ')')
159	return MISSING_CLOSING_PARENTHESIS;
160      ++*strp;
161      if (errmsg == NULL
162	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
163	value = (value >> 16) & 0xffff;
164      *valuep = value;
165      return errmsg;
166    }
167  else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
168    {
169      bfd_vma value;
170
171      *strp += 8;
172      errmsg = cgen_parse_address (cd, strp, opindex,
173				   BFD_RELOC_OR1K_GOTPC_LO16,
174				   &result_type, &value);
175      if (**strp != ')')
176	return MISSING_CLOSING_PARENTHESIS;
177      ++*strp;
178      if (errmsg == NULL
179	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
180	value &= 0xffff;
181      *valuep = value;
182      return errmsg;
183    }
184  else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
185    {
186      bfd_vma value;
187
188      *strp += 9;
189      errmsg = cgen_parse_address (cd, strp, opindex,
190				   BFD_RELOC_OR1K_GOTOFF_HI16,
191				   & result_type, & value);
192
193      if (**strp != ')')
194	return MISSING_CLOSING_PARENTHESIS;
195      ++*strp;
196      if (errmsg == NULL
197	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
198	value = (value >> 16) & 0xffff;
199      *valuep = value;
200      return errmsg;
201    }
202  else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
203    {
204      bfd_vma value;
205
206      *strp += 9;
207      errmsg = cgen_parse_address (cd, strp, opindex,
208				   BFD_RELOC_OR1K_GOTOFF_LO16,
209				   &result_type, &value);
210      if (**strp != ')')
211	return MISSING_CLOSING_PARENTHESIS;
212      ++*strp;
213      if (errmsg == NULL
214	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
215	value &= 0xffff;
216      *valuep = value;
217      return errmsg;
218    }
219  else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
220    {
221      bfd_vma value;
222
223      *strp += 8;
224      errmsg = cgen_parse_address (cd, strp, opindex,
225				   BFD_RELOC_OR1K_TLS_GD_HI16,
226				   & result_type, & value);
227
228      if (**strp != ')')
229	return MISSING_CLOSING_PARENTHESIS;
230      ++*strp;
231      if (errmsg == NULL
232	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
233	value = (value >> 16) & 0xffff;
234      *valuep = value;
235      return errmsg;
236    }
237  else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
238    {
239      bfd_vma value;
240
241      *strp += 8;
242      errmsg = cgen_parse_address (cd, strp, opindex,
243				   BFD_RELOC_OR1K_TLS_GD_LO16,
244				   &result_type, &value);
245      if (**strp != ')')
246	return MISSING_CLOSING_PARENTHESIS;
247      ++*strp;
248      if (errmsg == NULL
249	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
250	value &= 0xffff;
251      *valuep = value;
252      return errmsg;
253    }
254  else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
255    {
256      bfd_vma value;
257
258      *strp += 9;
259      errmsg = cgen_parse_address (cd, strp, opindex,
260				   BFD_RELOC_OR1K_TLS_LDM_HI16,
261				   & result_type, & value);
262
263      if (**strp != ')')
264	return MISSING_CLOSING_PARENTHESIS;
265      ++*strp;
266      if (errmsg == NULL
267	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
268	value = (value >> 16) & 0xffff;
269      *valuep = value;
270      return errmsg;
271    }
272  else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
273    {
274      bfd_vma value;
275
276      *strp += 9;
277      errmsg = cgen_parse_address (cd, strp, opindex,
278				   BFD_RELOC_OR1K_TLS_LDM_LO16,
279				   &result_type, &value);
280      if (**strp != ')')
281	return MISSING_CLOSING_PARENTHESIS;
282      ++*strp;
283      if (errmsg == NULL
284	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
285	value &= 0xffff;
286      *valuep = value;
287      return errmsg;
288    }
289  else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
290    {
291      bfd_vma value;
292
293      *strp += 9;
294      errmsg = cgen_parse_address (cd, strp, opindex,
295				   BFD_RELOC_OR1K_TLS_LDO_HI16,
296				   & result_type, & value);
297
298      if (**strp != ')')
299	return MISSING_CLOSING_PARENTHESIS;
300      ++*strp;
301      if (errmsg == NULL
302	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
303	value = (value >> 16) & 0xffff;
304      *valuep = value;
305      return errmsg;
306    }
307  else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
308    {
309      bfd_vma value;
310
311      *strp += 9;
312      errmsg = cgen_parse_address (cd, strp, opindex,
313				   BFD_RELOC_OR1K_TLS_LDO_LO16,
314				   &result_type, &value);
315      if (**strp != ')')
316	return MISSING_CLOSING_PARENTHESIS;
317      ++*strp;
318      if (errmsg == NULL
319	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
320	value &= 0xffff;
321      *valuep = value;
322      return errmsg;
323    }
324  else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
325    {
326      bfd_vma value;
327
328      *strp += 11;
329      errmsg = cgen_parse_address (cd, strp, opindex,
330				   BFD_RELOC_OR1K_TLS_IE_HI16,
331				   & result_type, & value);
332
333      if (**strp != ')')
334	return MISSING_CLOSING_PARENTHESIS;
335      ++*strp;
336      if (errmsg == NULL
337	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
338	value = (value >> 16) & 0xffff;
339      *valuep = value;
340      return errmsg;
341    }
342  else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
343    {
344      bfd_vma value;
345
346      *strp += 11;
347      errmsg = cgen_parse_address (cd, strp, opindex,
348				   BFD_RELOC_OR1K_TLS_IE_LO16,
349				   &result_type, &value);
350      if (**strp != ')')
351	return MISSING_CLOSING_PARENTHESIS;
352      ++*strp;
353      if (errmsg == NULL
354	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
355	value &= 0xffff;
356      *valuep = value;
357      return errmsg;
358    }
359  else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
360    {
361      bfd_vma value;
362
363      *strp += 8;
364      errmsg = cgen_parse_address (cd, strp, opindex,
365				   BFD_RELOC_OR1K_TLS_LE_HI16,
366				   & result_type, & value);
367
368      if (**strp != ')')
369	return MISSING_CLOSING_PARENTHESIS;
370      ++*strp;
371      if (errmsg == NULL
372	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
373	value = (value >> 16) & 0xffff;
374      *valuep = value;
375      return errmsg;
376    }
377  else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
378    {
379      bfd_vma value;
380
381      *strp += 8;
382      errmsg = cgen_parse_address (cd, strp, opindex,
383				   BFD_RELOC_OR1K_TLS_LE_LO16,
384				   &result_type, &value);
385      if (**strp != ')')
386	return MISSING_CLOSING_PARENTHESIS;
387      ++*strp;
388      if (errmsg == NULL
389	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
390	value &= 0xffff;
391      *valuep = value;
392      return errmsg;
393    }
394  else
395    {
396      long value;
397      errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
398      ret = value;
399    }
400
401  if (errmsg == NULL)
402    *valuep = ret;
403
404  return errmsg;
405}
406
407static const char *
408parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
409{
410  const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
411
412  if (errmsg == NULL)
413    *valuep &= 0xffff;
414  return errmsg;
415}
416
417/* -- */
418
419/* -- ibd.h */
420
421/* -- */
422