Add markers for 2.32 branch to NEWS and ChangeLog files.
[deliverable/binutils-gdb.git] / cpu / or1k.opc
CommitLineData
73589c9d
CS
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 `)'");
1c4f3780
RH
51static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
52static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
73589c9d
CS
53
54#define CGEN_VERBOSE_ASSEMBLER_ERRORS
55
56static const char *
57parse_disp26 (CGEN_CPU_DESC cd,
c151b1c6
AM
58 const char ** strp,
59 int opindex,
c8e98e36 60 int opinfo ATTRIBUTE_UNUSED,
c151b1c6
AM
61 enum cgen_parse_operand_result * resultp,
62 bfd_vma * valuep)
73589c9d 63{
c8e98e36 64 const char *str = *strp;
73589c9d 65 const char *errmsg = NULL;
c8e98e36 66 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
73589c9d 67
c8e98e36 68 if (strncasecmp (str, "plta(", 5) == 0)
73589c9d 69 {
c8e98e36
SH
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 }
73589c9d 78
c8e98e36
SH
79 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
80
81 if (reloc != BFD_RELOC_OR1K_REL_26)
82 {
73589c9d 83 if (**strp != ')')
c8e98e36
SH
84 errmsg = MISSING_CLOSING_PARENTHESIS;
85 else
86 ++*strp;
73589c9d 87 }
c8e98e36
SH
88
89 return errmsg;
90}
91
92static const char *
93parse_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)
99{
100 const char *str = *strp;
101 const char *errmsg = NULL;
102 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
103
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 }
124
125 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
126
127 if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
128 {
129 if (**strp != ')')
130 errmsg = MISSING_CLOSING_PARENTHESIS;
131 else
132 ++*strp;
133 }
134
135 return errmsg;
73589c9d
CS
136}
137
c8e98e36
SH
138enum or1k_rclass
139{
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,
149};
150
151enum or1k_rtype
1c4f3780
RH
152{
153 RTYPE_LO = 0,
c8e98e36
SH
154 RTYPE_SLO = 1,
155 RTYPE_PO = 2,
156 RTYPE_SPO = 3,
157 RTYPE_HI = 4,
158 RTYPE_AHI = 5,
1c4f3780
RH
159};
160
c8e98e36
SH
161#define RCLASS_SHIFT 3
162#define RTYPE_MASK 7
163
164static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
1c4f3780 165 { BFD_RELOC_LO16,
c8e98e36
SH
166 BFD_RELOC_OR1K_SLO16,
167 BFD_RELOC_OR1K_LO13,
168 BFD_RELOC_OR1K_SLO13,
1c4f3780 169 BFD_RELOC_HI16,
c8e98e36 170 BFD_RELOC_HI16_S, },
1c4f3780 171 { BFD_RELOC_OR1K_GOT16,
c8e98e36
SH
172 BFD_RELOC_UNUSED,
173 BFD_RELOC_OR1K_GOT_LO13,
1c4f3780
RH
174 BFD_RELOC_UNUSED,
175 BFD_RELOC_UNUSED,
176 BFD_RELOC_UNUSED },
177 { BFD_RELOC_OR1K_GOTPC_LO16,
1c4f3780 178 BFD_RELOC_UNUSED,
c8e98e36
SH
179 BFD_RELOC_UNUSED,
180 BFD_RELOC_UNUSED,
181 BFD_RELOC_OR1K_GOTPC_HI16,
1c4f3780
RH
182 BFD_RELOC_UNUSED },
183 { BFD_RELOC_LO16_GOTOFF,
c8e98e36
SH
184 BFD_RELOC_OR1K_GOTOFF_SLO16,
185 BFD_RELOC_UNUSED,
186 BFD_RELOC_UNUSED,
1c4f3780 187 BFD_RELOC_HI16_GOTOFF,
c8e98e36 188 BFD_RELOC_HI16_S_GOTOFF },
1c4f3780 189 { BFD_RELOC_OR1K_TLS_GD_LO16,
1c4f3780 190 BFD_RELOC_UNUSED,
c8e98e36
SH
191 BFD_RELOC_OR1K_TLS_GD_LO13,
192 BFD_RELOC_UNUSED,
193 BFD_RELOC_OR1K_TLS_GD_HI16,
1c4f3780
RH
194 BFD_RELOC_UNUSED },
195 { BFD_RELOC_OR1K_TLS_LDM_LO16,
1c4f3780 196 BFD_RELOC_UNUSED,
c8e98e36
SH
197 BFD_RELOC_OR1K_TLS_LDM_LO13,
198 BFD_RELOC_UNUSED,
199 BFD_RELOC_OR1K_TLS_LDM_HI16,
1c4f3780
RH
200 BFD_RELOC_UNUSED },
201 { BFD_RELOC_OR1K_TLS_LDO_LO16,
1c4f3780 202 BFD_RELOC_UNUSED,
c8e98e36
SH
203 BFD_RELOC_UNUSED,
204 BFD_RELOC_UNUSED,
205 BFD_RELOC_OR1K_TLS_LDO_HI16,
1c4f3780
RH
206 BFD_RELOC_UNUSED },
207 { BFD_RELOC_OR1K_TLS_IE_LO16,
c8e98e36
SH
208 BFD_RELOC_UNUSED,
209 BFD_RELOC_OR1K_TLS_IE_LO13,
210 BFD_RELOC_UNUSED,
1c4f3780 211 BFD_RELOC_OR1K_TLS_IE_HI16,
c8e98e36 212 BFD_RELOC_OR1K_TLS_IE_AHI16 },
1c4f3780 213 { BFD_RELOC_OR1K_TLS_LE_LO16,
c8e98e36
SH
214 BFD_RELOC_OR1K_TLS_LE_SLO16,
215 BFD_RELOC_UNUSED,
216 BFD_RELOC_UNUSED,
1c4f3780 217 BFD_RELOC_OR1K_TLS_LE_HI16,
c8e98e36 218 BFD_RELOC_OR1K_TLS_LE_AHI16 },
1c4f3780
RH
219};
220
221static int
222parse_reloc (const char **strp)
223{
224 const char *str = *strp;
c8e98e36
SH
225 enum or1k_rclass cls = RCLASS_DIRECT;
226 enum or1k_rtype typ;
1c4f3780
RH
227
228 if (strncasecmp (str, "got(", 4) == 0)
229 {
230 *strp = str + 4;
c8e98e36
SH
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;
1c4f3780
RH
242 }
243
244 if (strncasecmp (str, "gotpc", 5) == 0)
245 {
246 str += 5;
c8e98e36 247 cls = RCLASS_GOTPC;
1c4f3780
RH
248 }
249 else if (strncasecmp (str, "gotoff", 6) == 0)
250 {
251 str += 6;
c8e98e36 252 cls = RCLASS_GOTOFF;
1c4f3780
RH
253 }
254 else if (strncasecmp (str, "tlsgd", 5) == 0)
255 {
256 str += 5;
c8e98e36 257 cls = RCLASS_TLSGD;
1c4f3780
RH
258 }
259 else if (strncasecmp (str, "tlsldm", 6) == 0)
260 {
261 str += 6;
c8e98e36 262 cls = RCLASS_TLSLDM;
1c4f3780
RH
263 }
264 else if (strncasecmp (str, "dtpoff", 6) == 0)
265 {
266 str += 6;
c8e98e36 267 cls = RCLASS_DTPOFF;
1c4f3780
RH
268 }
269 else if (strncasecmp (str, "gottpoff", 8) == 0)
270 {
271 str += 8;
c8e98e36 272 cls = RCLASS_GOTTPOFF;
1c4f3780
RH
273 }
274 else if (strncasecmp (str, "tpoff", 5) == 0)
275 {
276 str += 5;
c8e98e36 277 cls = RCLASS_TPOFF;
1c4f3780
RH
278 }
279
280 if (strncasecmp (str, "hi(", 3) == 0)
281 {
282 str += 3;
c8e98e36 283 typ = RTYPE_HI;
1c4f3780
RH
284 }
285 else if (strncasecmp (str, "lo(", 3) == 0)
286 {
287 str += 3;
c8e98e36 288 typ = RTYPE_LO;
1c4f3780
RH
289 }
290 else if (strncasecmp (str, "ha(", 3) == 0)
291 {
292 str += 3;
c8e98e36
SH
293 typ = RTYPE_AHI;
294 }
295 else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
296 {
297 str += 3;
298 typ = RTYPE_PO;
1c4f3780
RH
299 }
300 else
301 return -1;
302
303 *strp = str;
c8e98e36 304 return (cls << RCLASS_SHIFT) | typ;
1c4f3780
RH
305}
306
73589c9d 307static const char *
1c4f3780
RH
308parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
309 long *valuep, int splitp)
73589c9d
CS
310{
311 const char *errmsg;
312 enum cgen_parse_operand_result result_type;
1c4f3780 313 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
c8e98e36
SH
314 enum or1k_rtype reloc_type;
315 int reloc_code;
1c4f3780 316 bfd_vma ret;
73589c9d
CS
317
318 if (**strp == '#')
319 ++*strp;
320
c8e98e36
SH
321 reloc_code = parse_reloc (strp);
322 reloc_type = reloc_code & RTYPE_MASK;
323 if (reloc_code >= 0)
73589c9d 324 {
c8e98e36 325 enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
1c4f3780 326 if (splitp)
73589c9d 327 {
c8e98e36
SH
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;
1c4f3780
RH
332 else
333 return INVALID_STORE_RELOC;
73589c9d 334 }
c8e98e36 335 reloc = or1k_imm16_relocs[reloc_class][reloc_type];
73589c9d 336 }
73589c9d 337
1c4f3780 338 if (reloc != BFD_RELOC_UNUSED)
73589c9d
CS
339 {
340 bfd_vma value;
341
1c4f3780 342 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
c151b1c6 343 &result_type, &value);
73589c9d 344 if (**strp != ')')
1c4f3780 345 errmsg = MISSING_CLOSING_PARENTHESIS;
73589c9d 346 ++*strp;
73589c9d 347
1c4f3780 348 ret = value;
73589c9d 349
1c4f3780 350 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
c8e98e36 351 switch (reloc_type)
1c4f3780
RH
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;
c8e98e36
SH
364 case RTYPE_PO:
365 case RTYPE_SPO:
366 ret &= 0x1fff;
367 break;
1c4f3780
RH
368 default:
369 errmsg = INVALID_RELOC_TYPE;
370 }
73589c9d
CS
371 }
372 else
373 {
374 long value;
375 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
376 ret = value;
377 }
378
379 if (errmsg == NULL)
380 *valuep = ret;
381
382 return errmsg;
383}
384
385static const char *
1c4f3780 386parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
73589c9d 387{
1c4f3780
RH
388 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
389}
73589c9d 390
1c4f3780
RH
391static const char *
392parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
393 long *valuep)
394{
395 return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
396}
397
398static const char *
399parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
400 unsigned long *valuep)
401{
402 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
403 if (errmsg == NULL)
404 *valuep &= 0xffff;
405 return errmsg;
406}
407
408static const char *
409parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
410 unsigned long *valuep)
411{
412 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
73589c9d
CS
413 if (errmsg == NULL)
414 *valuep &= 0xffff;
415 return errmsg;
416}
417
418/* -- */
419
420/* -- ibd.h */
421
422/* -- */
This page took 0.246518 seconds and 4 git commands to generate.