]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - cpu/or1k.opc
Add note about adding ChangeLog.git to src-release.sh
[thirdparty/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
6ce26ac7
SH
43/* Check applicability of instructions against machines. */
44#define CGEN_VALIDATE_INSN_SUPPORTED
45
46extern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
47
73589c9d
CS
48/* -- */
49
50/* -- opc.c */
6ce26ac7
SH
51
52/* Special check to ensure that instruction exists for given machine. */
53
54int
55or1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
56{
57 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
58
59 /* No mach attribute? Assume it's supported for all machs. */
60 if (machs == 0)
61 return 1;
62
63 return ((machs & cd->machs) != 0);
64}
65
73589c9d
CS
66/* -- */
67
68/* -- asm.c */
69
70static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
1c4f3780
RH
71static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
72static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
73589c9d
CS
73
74#define CGEN_VERBOSE_ASSEMBLER_ERRORS
75
76static const char *
77parse_disp26 (CGEN_CPU_DESC cd,
c151b1c6
AM
78 const char ** strp,
79 int opindex,
c8e98e36 80 int opinfo ATTRIBUTE_UNUSED,
c151b1c6
AM
81 enum cgen_parse_operand_result * resultp,
82 bfd_vma * valuep)
73589c9d 83{
c8e98e36 84 const char *str = *strp;
73589c9d 85 const char *errmsg = NULL;
c8e98e36 86 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
73589c9d 87
c8e98e36 88 if (strncasecmp (str, "plta(", 5) == 0)
73589c9d 89 {
c8e98e36
SH
90 *strp = str + 5;
91 reloc = BFD_RELOC_OR1K_PLTA26;
92 }
93 else if (strncasecmp (str, "plt(", 4) == 0)
94 {
95 *strp = str + 4;
96 reloc = BFD_RELOC_OR1K_PLT26;
97 }
73589c9d 98
c8e98e36
SH
99 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
100
101 if (reloc != BFD_RELOC_OR1K_REL_26)
102 {
73589c9d 103 if (**strp != ')')
c8e98e36
SH
104 errmsg = MISSING_CLOSING_PARENTHESIS;
105 else
106 ++*strp;
73589c9d 107 }
c8e98e36
SH
108
109 return errmsg;
110}
111
112static const char *
113parse_disp21 (CGEN_CPU_DESC cd,
114 const char ** strp,
115 int opindex,
116 int opinfo ATTRIBUTE_UNUSED,
117 enum cgen_parse_operand_result * resultp,
118 bfd_vma * valuep)
119{
120 const char *str = *strp;
121 const char *errmsg = NULL;
122 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
123
124 if (strncasecmp (str, "got(", 4) == 0)
125 {
126 *strp = str + 4;
127 reloc = BFD_RELOC_OR1K_GOT_PG21;
128 }
129 else if (strncasecmp (str, "tlsgd(", 6) == 0)
130 {
131 *strp = str + 6;
132 reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
133 }
134 else if (strncasecmp (str, "tlsldm(", 7) == 0)
135 {
136 *strp = str + 7;
137 reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
138 }
139 else if (strncasecmp (str, "gottp(", 6) == 0)
140 {
141 *strp = str + 6;
142 reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
143 }
144
145 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
146
147 if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
148 {
149 if (**strp != ')')
150 errmsg = MISSING_CLOSING_PARENTHESIS;
151 else
152 ++*strp;
153 }
154
155 return errmsg;
73589c9d
CS
156}
157
c8e98e36
SH
158enum or1k_rclass
159{
160 RCLASS_DIRECT = 0,
161 RCLASS_GOT = 1,
162 RCLASS_GOTPC = 2,
163 RCLASS_GOTOFF = 3,
164 RCLASS_TLSGD = 4,
165 RCLASS_TLSLDM = 5,
166 RCLASS_DTPOFF = 6,
167 RCLASS_GOTTPOFF = 7,
168 RCLASS_TPOFF = 8,
169};
170
171enum or1k_rtype
1c4f3780
RH
172{
173 RTYPE_LO = 0,
c8e98e36
SH
174 RTYPE_SLO = 1,
175 RTYPE_PO = 2,
176 RTYPE_SPO = 3,
177 RTYPE_HI = 4,
178 RTYPE_AHI = 5,
1c4f3780
RH
179};
180
c8e98e36
SH
181#define RCLASS_SHIFT 3
182#define RTYPE_MASK 7
183
184static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
1c4f3780 185 { BFD_RELOC_LO16,
c8e98e36
SH
186 BFD_RELOC_OR1K_SLO16,
187 BFD_RELOC_OR1K_LO13,
188 BFD_RELOC_OR1K_SLO13,
1c4f3780 189 BFD_RELOC_HI16,
c8e98e36 190 BFD_RELOC_HI16_S, },
1c4f3780 191 { BFD_RELOC_OR1K_GOT16,
c8e98e36
SH
192 BFD_RELOC_UNUSED,
193 BFD_RELOC_OR1K_GOT_LO13,
1c4f3780
RH
194 BFD_RELOC_UNUSED,
195 BFD_RELOC_UNUSED,
0b3e14c9 196 BFD_RELOC_OR1K_GOT_AHI16 },
1c4f3780 197 { BFD_RELOC_OR1K_GOTPC_LO16,
1c4f3780 198 BFD_RELOC_UNUSED,
c8e98e36
SH
199 BFD_RELOC_UNUSED,
200 BFD_RELOC_UNUSED,
201 BFD_RELOC_OR1K_GOTPC_HI16,
1c4f3780
RH
202 BFD_RELOC_UNUSED },
203 { BFD_RELOC_LO16_GOTOFF,
c8e98e36
SH
204 BFD_RELOC_OR1K_GOTOFF_SLO16,
205 BFD_RELOC_UNUSED,
206 BFD_RELOC_UNUSED,
1c4f3780 207 BFD_RELOC_HI16_GOTOFF,
c8e98e36 208 BFD_RELOC_HI16_S_GOTOFF },
1c4f3780 209 { BFD_RELOC_OR1K_TLS_GD_LO16,
1c4f3780 210 BFD_RELOC_UNUSED,
c8e98e36
SH
211 BFD_RELOC_OR1K_TLS_GD_LO13,
212 BFD_RELOC_UNUSED,
213 BFD_RELOC_OR1K_TLS_GD_HI16,
1c4f3780
RH
214 BFD_RELOC_UNUSED },
215 { BFD_RELOC_OR1K_TLS_LDM_LO16,
1c4f3780 216 BFD_RELOC_UNUSED,
c8e98e36
SH
217 BFD_RELOC_OR1K_TLS_LDM_LO13,
218 BFD_RELOC_UNUSED,
219 BFD_RELOC_OR1K_TLS_LDM_HI16,
1c4f3780
RH
220 BFD_RELOC_UNUSED },
221 { BFD_RELOC_OR1K_TLS_LDO_LO16,
1c4f3780 222 BFD_RELOC_UNUSED,
c8e98e36
SH
223 BFD_RELOC_UNUSED,
224 BFD_RELOC_UNUSED,
225 BFD_RELOC_OR1K_TLS_LDO_HI16,
1c4f3780
RH
226 BFD_RELOC_UNUSED },
227 { BFD_RELOC_OR1K_TLS_IE_LO16,
c8e98e36
SH
228 BFD_RELOC_UNUSED,
229 BFD_RELOC_OR1K_TLS_IE_LO13,
230 BFD_RELOC_UNUSED,
1c4f3780 231 BFD_RELOC_OR1K_TLS_IE_HI16,
c8e98e36 232 BFD_RELOC_OR1K_TLS_IE_AHI16 },
1c4f3780 233 { BFD_RELOC_OR1K_TLS_LE_LO16,
c8e98e36
SH
234 BFD_RELOC_OR1K_TLS_LE_SLO16,
235 BFD_RELOC_UNUSED,
236 BFD_RELOC_UNUSED,
1c4f3780 237 BFD_RELOC_OR1K_TLS_LE_HI16,
c8e98e36 238 BFD_RELOC_OR1K_TLS_LE_AHI16 },
1c4f3780
RH
239};
240
241static int
242parse_reloc (const char **strp)
243{
244 const char *str = *strp;
c8e98e36
SH
245 enum or1k_rclass cls = RCLASS_DIRECT;
246 enum or1k_rtype typ;
1c4f3780
RH
247
248 if (strncasecmp (str, "got(", 4) == 0)
249 {
250 *strp = str + 4;
c8e98e36
SH
251 return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
252 }
253 if (strncasecmp (str, "gotpo(", 6) == 0)
254 {
255 *strp = str + 6;
256 return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
257 }
258 if (strncasecmp (str, "gottppo(", 8) == 0)
259 {
260 *strp = str + 8;
261 return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
1c4f3780
RH
262 }
263
264 if (strncasecmp (str, "gotpc", 5) == 0)
265 {
266 str += 5;
c8e98e36 267 cls = RCLASS_GOTPC;
1c4f3780
RH
268 }
269 else if (strncasecmp (str, "gotoff", 6) == 0)
270 {
271 str += 6;
c8e98e36 272 cls = RCLASS_GOTOFF;
1c4f3780
RH
273 }
274 else if (strncasecmp (str, "tlsgd", 5) == 0)
275 {
276 str += 5;
c8e98e36 277 cls = RCLASS_TLSGD;
1c4f3780
RH
278 }
279 else if (strncasecmp (str, "tlsldm", 6) == 0)
280 {
281 str += 6;
c8e98e36 282 cls = RCLASS_TLSLDM;
1c4f3780
RH
283 }
284 else if (strncasecmp (str, "dtpoff", 6) == 0)
285 {
286 str += 6;
c8e98e36 287 cls = RCLASS_DTPOFF;
1c4f3780
RH
288 }
289 else if (strncasecmp (str, "gottpoff", 8) == 0)
290 {
291 str += 8;
c8e98e36 292 cls = RCLASS_GOTTPOFF;
1c4f3780
RH
293 }
294 else if (strncasecmp (str, "tpoff", 5) == 0)
295 {
296 str += 5;
c8e98e36 297 cls = RCLASS_TPOFF;
1c4f3780 298 }
0b3e14c9
SH
299 else if (strncasecmp (str, "got", 3) == 0)
300 {
301 str += 3;
302 cls = RCLASS_GOT;
303 }
1c4f3780
RH
304
305 if (strncasecmp (str, "hi(", 3) == 0)
306 {
307 str += 3;
c8e98e36 308 typ = RTYPE_HI;
1c4f3780
RH
309 }
310 else if (strncasecmp (str, "lo(", 3) == 0)
311 {
312 str += 3;
c8e98e36 313 typ = RTYPE_LO;
1c4f3780
RH
314 }
315 else if (strncasecmp (str, "ha(", 3) == 0)
316 {
317 str += 3;
c8e98e36
SH
318 typ = RTYPE_AHI;
319 }
320 else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
321 {
322 str += 3;
323 typ = RTYPE_PO;
1c4f3780
RH
324 }
325 else
326 return -1;
327
328 *strp = str;
c8e98e36 329 return (cls << RCLASS_SHIFT) | typ;
1c4f3780
RH
330}
331
73589c9d 332static const char *
1c4f3780
RH
333parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
334 long *valuep, int splitp)
73589c9d
CS
335{
336 const char *errmsg;
337 enum cgen_parse_operand_result result_type;
1c4f3780 338 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
c8e98e36
SH
339 enum or1k_rtype reloc_type;
340 int reloc_code;
1c4f3780 341 bfd_vma ret;
73589c9d
CS
342
343 if (**strp == '#')
344 ++*strp;
345
c8e98e36
SH
346 reloc_code = parse_reloc (strp);
347 reloc_type = reloc_code & RTYPE_MASK;
348 if (reloc_code >= 0)
73589c9d 349 {
c8e98e36 350 enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
1c4f3780 351 if (splitp)
73589c9d 352 {
c8e98e36
SH
353 if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
354 && reloc_class != RCLASS_GOT)
355 /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
356 reloc_type |= 1;
1c4f3780
RH
357 else
358 return INVALID_STORE_RELOC;
73589c9d 359 }
c8e98e36 360 reloc = or1k_imm16_relocs[reloc_class][reloc_type];
73589c9d 361 }
73589c9d 362
1c4f3780 363 if (reloc != BFD_RELOC_UNUSED)
73589c9d
CS
364 {
365 bfd_vma value;
366
1c4f3780 367 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
c151b1c6 368 &result_type, &value);
73589c9d 369 if (**strp != ')')
1c4f3780 370 errmsg = MISSING_CLOSING_PARENTHESIS;
73589c9d 371 ++*strp;
73589c9d 372
1c4f3780 373 ret = value;
73589c9d 374
1c4f3780 375 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
c8e98e36 376 switch (reloc_type)
1c4f3780
RH
377 {
378 case RTYPE_AHI:
379 ret += 0x8000;
380 /* FALLTHRU */
381 case RTYPE_HI:
382 ret >>= 16;
383 /* FALLTHRU */
384 case RTYPE_LO:
385 case RTYPE_SLO:
386 ret &= 0xffff;
387 ret = (ret ^ 0x8000) - 0x8000;
388 break;
c8e98e36
SH
389 case RTYPE_PO:
390 case RTYPE_SPO:
391 ret &= 0x1fff;
392 break;
1c4f3780
RH
393 default:
394 errmsg = INVALID_RELOC_TYPE;
395 }
73589c9d
CS
396 }
397 else
398 {
399 long value;
400 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
401 ret = value;
402 }
403
404 if (errmsg == NULL)
405 *valuep = ret;
406
407 return errmsg;
408}
409
410static const char *
1c4f3780 411parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
73589c9d 412{
1c4f3780
RH
413 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
414}
73589c9d 415
1c4f3780
RH
416static const char *
417parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
418 long *valuep)
419{
420 return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
421}
422
423static const char *
424parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
425 unsigned long *valuep)
426{
427 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
428 if (errmsg == NULL)
429 *valuep &= 0xffff;
430 return errmsg;
431}
432
433static const char *
434parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
435 unsigned long *valuep)
436{
437 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
73589c9d
CS
438 if (errmsg == NULL)
439 *valuep &= 0xffff;
440 return errmsg;
441}
442
6ce26ac7
SH
443/* Parse register pairs with syntax rA,rB to a flag + rA value. */
444
445static const char *
446parse_regpair (CGEN_CPU_DESC cd, const char **strp,
447 int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
448{
449 long reg1_index;
450 long reg2_index;
451 const char *errmsg;
452
453 /* The first part should just be a register. */
454 errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
455 &reg1_index);
456
457 /* If that worked skip the comma separator. */
458 if (errmsg == NULL)
459 {
460 if (**strp == ',')
461 ++*strp;
462 else
463 errmsg = "Unexpected character, expected ','";
464 }
465
466 /* If that worked the next part is just another register. */
467 if (errmsg == NULL)
468 errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
469 &reg2_index);
470
471 /* Validate the register pair is valid and create the output value. */
472 if (errmsg == NULL)
473 {
474 int regoffset = reg2_index - reg1_index;
475
476 if (regoffset == 1 || regoffset == 2)
477 {
478 unsigned short offsetmask;
479 unsigned short value;
480
481 offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
482 value = offsetmask | reg1_index;
483
484 *valuep = value;
485 }
486 else
487 errmsg = "Invalid register pair, offset not 1 or 2.";
488 }
489
490 return errmsg;
491}
492
493/* -- */
494
495/* -- dis.c */
496
497static void
498print_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
499 void * dis_info,
500 long value,
501 unsigned int attrs ATTRIBUTE_UNUSED,
502 bfd_vma pc ATTRIBUTE_UNUSED,
503 int length ATTRIBUTE_UNUSED)
504{
505 disassemble_info *info = dis_info;
506 char reg1_index;
507 char reg2_index;
508
509 reg1_index = value & 0x1f;
510 reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
511
512 (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
513}
514
73589c9d
CS
515/* -- */
516
517/* -- ibd.h */
518
519/* -- */