[PATCH 40/57][Arm][OBJDUMP] Add support for MVE instructions: vdup, veor, vfma, vfms...
[binutils-gdb.git] / cpu / or1k.opc
blob5082a30cee1cd3dfea4754b8cb55f0094a175b22
1 /* OpenRISC 1000 opcode support.  -*- C -*-
2    Copyright 2000-2014 Free Software Foundation, Inc.
4    Originally ontributed for OR32 by Red Hat Inc;
6    This file is part of the GNU Binutils.
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.
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.
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/>. */
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.
28    Each section is delimited with start and end markers.
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"  */
36 /* -- opc.h */
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)
43 /* -- */
45 /* -- opc.c */
46 /* -- */
48 /* -- asm.c */
50 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
51 static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
52 static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
54 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
56 static const char *
57 parse_disp26 (CGEN_CPU_DESC cd,
58               const char ** strp,
59               int opindex,
60               int opinfo ATTRIBUTE_UNUSED,
61               enum cgen_parse_operand_result * resultp,
62               bfd_vma * valuep)
64   const char *str = *strp;
65   const char *errmsg = NULL;
66   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
68   if (strncasecmp (str, "plta(", 5) == 0)
69     {
70       *strp = str + 5;
71       reloc = BFD_RELOC_OR1K_PLTA26;
72     }
73   else if (strncasecmp (str, "plt(", 4) == 0)
74     {
75       *strp = str + 4;
76       reloc = BFD_RELOC_OR1K_PLT26;
77     }
79   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
81   if (reloc != BFD_RELOC_OR1K_REL_26)
82     {
83       if (**strp != ')')
84         errmsg = MISSING_CLOSING_PARENTHESIS;
85       else
86         ++*strp;
87     }
89   return errmsg;
92 static const char *
93 parse_disp21 (CGEN_CPU_DESC cd,
94               const char ** strp,
95               int opindex,
96               int opinfo ATTRIBUTE_UNUSED,
97               enum cgen_parse_operand_result * resultp,
98               bfd_vma * valuep)
100   const char *str = *strp;
101   const char *errmsg = NULL;
102   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
104   if (strncasecmp (str, "got(", 4) == 0)
105     {
106       *strp = str + 4;
107       reloc = BFD_RELOC_OR1K_GOT_PG21;
108     }
109   else if (strncasecmp (str, "tlsgd(", 6) == 0)
110     {
111       *strp = str + 6;
112       reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
113     }
114   else if (strncasecmp (str, "tlsldm(", 7) == 0)
115     {
116       *strp = str + 7;
117       reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
118     }
119   else if (strncasecmp (str, "gottp(", 6) == 0)
120     {
121       *strp = str + 6;
122       reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
123     }
125   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
127   if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
128     {
129       if (**strp != ')')
130         errmsg = MISSING_CLOSING_PARENTHESIS;
131       else
132         ++*strp;
133     }
135   return errmsg;
138 enum or1k_rclass
140   RCLASS_DIRECT   = 0,
141   RCLASS_GOT      = 1,
142   RCLASS_GOTPC    = 2,
143   RCLASS_GOTOFF   = 3,
144   RCLASS_TLSGD    = 4,
145   RCLASS_TLSLDM   = 5,
146   RCLASS_DTPOFF   = 6,
147   RCLASS_GOTTPOFF = 7,
148   RCLASS_TPOFF    = 8,
151 enum or1k_rtype
153   RTYPE_LO = 0,
154   RTYPE_SLO = 1,
155   RTYPE_PO = 2,
156   RTYPE_SPO = 3,
157   RTYPE_HI = 4,
158   RTYPE_AHI = 5,
161 #define RCLASS_SHIFT 3
162 #define RTYPE_MASK   7
164 static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
165   { BFD_RELOC_LO16,
166     BFD_RELOC_OR1K_SLO16,
167     BFD_RELOC_OR1K_LO13,
168     BFD_RELOC_OR1K_SLO13,
169     BFD_RELOC_HI16,
170     BFD_RELOC_HI16_S, },
171   { BFD_RELOC_OR1K_GOT16,
172     BFD_RELOC_UNUSED,
173     BFD_RELOC_OR1K_GOT_LO13,
174     BFD_RELOC_UNUSED,
175     BFD_RELOC_UNUSED,
176     BFD_RELOC_UNUSED },
177   { BFD_RELOC_OR1K_GOTPC_LO16,
178     BFD_RELOC_UNUSED,
179     BFD_RELOC_UNUSED,
180     BFD_RELOC_UNUSED,
181     BFD_RELOC_OR1K_GOTPC_HI16,
182     BFD_RELOC_UNUSED },
183   { BFD_RELOC_LO16_GOTOFF,
184     BFD_RELOC_OR1K_GOTOFF_SLO16,
185     BFD_RELOC_UNUSED,
186     BFD_RELOC_UNUSED,
187     BFD_RELOC_HI16_GOTOFF,
188     BFD_RELOC_HI16_S_GOTOFF },
189   { BFD_RELOC_OR1K_TLS_GD_LO16,
190     BFD_RELOC_UNUSED,
191     BFD_RELOC_OR1K_TLS_GD_LO13,
192     BFD_RELOC_UNUSED,
193     BFD_RELOC_OR1K_TLS_GD_HI16,
194     BFD_RELOC_UNUSED },
195   { BFD_RELOC_OR1K_TLS_LDM_LO16,
196     BFD_RELOC_UNUSED,
197     BFD_RELOC_OR1K_TLS_LDM_LO13,
198     BFD_RELOC_UNUSED,
199     BFD_RELOC_OR1K_TLS_LDM_HI16,
200     BFD_RELOC_UNUSED },
201   { BFD_RELOC_OR1K_TLS_LDO_LO16,
202     BFD_RELOC_UNUSED,
203     BFD_RELOC_UNUSED,
204     BFD_RELOC_UNUSED,
205     BFD_RELOC_OR1K_TLS_LDO_HI16,
206     BFD_RELOC_UNUSED },
207   { BFD_RELOC_OR1K_TLS_IE_LO16,
208     BFD_RELOC_UNUSED,
209     BFD_RELOC_OR1K_TLS_IE_LO13,
210     BFD_RELOC_UNUSED,
211     BFD_RELOC_OR1K_TLS_IE_HI16,
212     BFD_RELOC_OR1K_TLS_IE_AHI16 },
213   { BFD_RELOC_OR1K_TLS_LE_LO16,
214     BFD_RELOC_OR1K_TLS_LE_SLO16,
215     BFD_RELOC_UNUSED,
216     BFD_RELOC_UNUSED,
217     BFD_RELOC_OR1K_TLS_LE_HI16,
218     BFD_RELOC_OR1K_TLS_LE_AHI16 },
221 static int
222 parse_reloc (const char **strp)
224     const char *str = *strp;
225     enum or1k_rclass cls = RCLASS_DIRECT;
226     enum or1k_rtype typ;
228     if (strncasecmp (str, "got(", 4) == 0)
229       {
230         *strp = str + 4;
231         return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
232       }
233     if (strncasecmp (str, "gotpo(", 6) == 0)
234       {
235         *strp = str + 6;
236         return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
237       }
238     if (strncasecmp (str, "gottppo(", 8) == 0)
239       {
240         *strp = str + 8;
241         return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
242       }
244     if (strncasecmp (str, "gotpc", 5) == 0)
245       {
246         str += 5;
247         cls = RCLASS_GOTPC;
248       }
249     else if (strncasecmp (str, "gotoff", 6) == 0)
250       {
251         str += 6;
252         cls = RCLASS_GOTOFF;
253       }
254     else if (strncasecmp (str, "tlsgd", 5) == 0)
255       {
256         str += 5;
257         cls = RCLASS_TLSGD;
258       }
259     else if (strncasecmp (str, "tlsldm", 6) == 0)
260       {
261         str += 6;
262         cls = RCLASS_TLSLDM;
263       }
264     else if (strncasecmp (str, "dtpoff", 6) == 0)
265       {
266         str += 6;
267         cls = RCLASS_DTPOFF;
268       }
269     else if (strncasecmp (str, "gottpoff", 8) == 0)
270       {
271         str += 8;
272         cls = RCLASS_GOTTPOFF;
273       }
274     else if (strncasecmp (str, "tpoff", 5) == 0)
275       {
276         str += 5;
277         cls = RCLASS_TPOFF;
278       }
280     if (strncasecmp (str, "hi(", 3) == 0)
281       {
282         str += 3;
283         typ = RTYPE_HI;
284       }
285     else if (strncasecmp (str, "lo(", 3) == 0)
286       {
287         str += 3;
288         typ = RTYPE_LO;
289       }
290     else if (strncasecmp (str, "ha(", 3) == 0)
291       {
292         str += 3;
293         typ = RTYPE_AHI;
294       }
295     else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
296       {
297         str += 3;
298         typ = RTYPE_PO;
299       }
300     else
301       return -1;
303     *strp = str;
304     return (cls << RCLASS_SHIFT) | typ;
307 static const char *
308 parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
309              long *valuep, int splitp)
311   const char *errmsg;
312   enum cgen_parse_operand_result result_type;
313   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
314   enum or1k_rtype reloc_type;
315   int reloc_code;
316   bfd_vma ret;
318   if (**strp == '#')
319     ++*strp;
321   reloc_code = parse_reloc (strp);
322   reloc_type = reloc_code & RTYPE_MASK;
323   if (reloc_code >= 0)
324     {
325       enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
326       if (splitp)
327         {
328           if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
329               && reloc_class != RCLASS_GOT)
330             /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
331             reloc_type |= 1;
332           else
333             return INVALID_STORE_RELOC;
334         }
335       reloc = or1k_imm16_relocs[reloc_class][reloc_type];
336     }
338   if (reloc != BFD_RELOC_UNUSED)
339     {
340       bfd_vma value;
342       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
343                                    &result_type, &value);
344       if (**strp != ')')
345         errmsg = MISSING_CLOSING_PARENTHESIS;
346       ++*strp;
348       ret = value;
350       if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
351         switch (reloc_type)
352           {
353           case RTYPE_AHI:
354             ret += 0x8000;
355             /* FALLTHRU */
356           case RTYPE_HI:
357             ret >>= 16;
358             /* FALLTHRU */
359           case RTYPE_LO:
360           case RTYPE_SLO:
361             ret &= 0xffff;
362             ret = (ret ^ 0x8000) - 0x8000;
363             break;
364           case RTYPE_PO:
365           case RTYPE_SPO:
366             ret &= 0x1fff;
367             break;
368           default:
369             errmsg = INVALID_RELOC_TYPE;
370           }
371     }
372   else
373     {
374       long value;
375       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
376       ret = value;
377     }
379   if (errmsg == NULL)
380     *valuep = ret;
382   return errmsg;
385 static const char *
386 parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
388   return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
391 static const char *
392 parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
393                     long *valuep)
395   return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
398 static const char *
399 parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
400               unsigned long *valuep)
402   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
403   if (errmsg == NULL)
404     *valuep &= 0xffff;
405   return errmsg;
408 static const char *
409 parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
410                     unsigned long *valuep)
412   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
413   if (errmsg == NULL)
414     *valuep &= 0xffff;
415   return errmsg;
418 /* -- */
420 /* -- ibd.h */
422 /* -- */