or1k: Add relocations for high-signed and low-stores
[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,
60 int opinfo,
61 enum cgen_parse_operand_result * resultp,
62 bfd_vma * valuep)
73589c9d
CS
63{
64 const char *errmsg = NULL;
65 enum cgen_parse_operand_result result_type;
66
67 if (strncasecmp (*strp, "plt(", 4) == 0)
68 {
69 bfd_vma value;
70
71 *strp += 4;
72 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
c151b1c6 73 & result_type, & value);
73589c9d 74 if (**strp != ')')
c151b1c6 75 return MISSING_CLOSING_PARENTHESIS;
73589c9d
CS
76 ++*strp;
77 if (errmsg == NULL
c151b1c6
AM
78 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
79 value = (value >> 2) & 0xffff;
73589c9d
CS
80 *valuep = value;
81 return errmsg;
82 }
83 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
84}
85
1c4f3780
RH
86enum
87{
88 RTYPE_LO = 0,
89 RTYPE_HI = 1,
90 RTYPE_AHI = 2,
91 RTYPE_SLO = 3,
92
93 RTYPE_GOT = (1 << 2),
94 RTYPE_GOTPC = (2 << 2),
95 RTYPE_GOTOFF = (3 << 2),
96 RTYPE_TLSGD = (4 << 2),
97 RTYPE_TLSLDM = (5 << 2),
98 RTYPE_DTPOFF = (6 << 2),
99 RTYPE_GOTTPOFF = (7 << 2),
100 RTYPE_TPOFF = (8 << 2),
101};
102
103static const bfd_reloc_code_real_type or1k_imm16_relocs[][4] = {
104 { BFD_RELOC_LO16,
105 BFD_RELOC_HI16,
106 BFD_RELOC_HI16_S,
107 BFD_RELOC_OR1K_SLO16 },
108 { BFD_RELOC_OR1K_GOT16,
109 BFD_RELOC_UNUSED,
110 BFD_RELOC_UNUSED,
111 BFD_RELOC_UNUSED },
112 { BFD_RELOC_OR1K_GOTPC_LO16,
113 BFD_RELOC_OR1K_GOTPC_HI16,
114 BFD_RELOC_UNUSED,
115 BFD_RELOC_UNUSED },
116 { BFD_RELOC_LO16_GOTOFF,
117 BFD_RELOC_HI16_GOTOFF,
118 BFD_RELOC_HI16_S_GOTOFF,
119 BFD_RELOC_OR1K_GOTOFF_SLO16 },
120 { BFD_RELOC_OR1K_TLS_GD_LO16,
121 BFD_RELOC_OR1K_TLS_GD_HI16,
122 BFD_RELOC_UNUSED,
123 BFD_RELOC_UNUSED },
124 { BFD_RELOC_OR1K_TLS_LDM_LO16,
125 BFD_RELOC_OR1K_TLS_LDM_HI16,
126 BFD_RELOC_UNUSED,
127 BFD_RELOC_UNUSED },
128 { BFD_RELOC_OR1K_TLS_LDO_LO16,
129 BFD_RELOC_OR1K_TLS_LDO_HI16,
130 BFD_RELOC_UNUSED,
131 BFD_RELOC_UNUSED },
132 { BFD_RELOC_OR1K_TLS_IE_LO16,
133 BFD_RELOC_OR1K_TLS_IE_HI16,
134 BFD_RELOC_OR1K_TLS_IE_AHI16,
135 BFD_RELOC_UNUSED },
136 { BFD_RELOC_OR1K_TLS_LE_LO16,
137 BFD_RELOC_OR1K_TLS_LE_HI16,
138 BFD_RELOC_OR1K_TLS_LE_AHI16,
139 BFD_RELOC_OR1K_TLS_LE_SLO16 }
140};
141
142static int
143parse_reloc (const char **strp)
144{
145 const char *str = *strp;
146 int ret = 0;
147
148 if (strncasecmp (str, "got(", 4) == 0)
149 {
150 *strp = str + 4;
151 return RTYPE_GOT | RTYPE_LO;
152 }
153
154 if (strncasecmp (str, "gotpc", 5) == 0)
155 {
156 str += 5;
157 ret = RTYPE_GOTPC;
158 }
159 else if (strncasecmp (str, "gotoff", 6) == 0)
160 {
161 str += 6;
162 ret = RTYPE_GOTOFF;
163 }
164 else if (strncasecmp (str, "tlsgd", 5) == 0)
165 {
166 str += 5;
167 ret = RTYPE_TLSGD;
168 }
169 else if (strncasecmp (str, "tlsldm", 6) == 0)
170 {
171 str += 6;
172 ret = RTYPE_TLSLDM;
173 }
174 else if (strncasecmp (str, "dtpoff", 6) == 0)
175 {
176 str += 6;
177 ret = RTYPE_DTPOFF;
178 }
179 else if (strncasecmp (str, "gottpoff", 8) == 0)
180 {
181 str += 8;
182 ret = RTYPE_GOTTPOFF;
183 }
184 else if (strncasecmp (str, "tpoff", 5) == 0)
185 {
186 str += 5;
187 ret = RTYPE_TPOFF;
188 }
189
190 if (strncasecmp (str, "hi(", 3) == 0)
191 {
192 str += 3;
193 ret |= RTYPE_HI;
194 }
195 else if (strncasecmp (str, "lo(", 3) == 0)
196 {
197 str += 3;
198 ret |= RTYPE_LO;
199 }
200 else if (strncasecmp (str, "ha(", 3) == 0)
201 {
202 str += 3;
203 ret |= RTYPE_AHI;
204 }
205 else
206 return -1;
207
208 *strp = str;
209 return ret;
210}
211
73589c9d 212static const char *
1c4f3780
RH
213parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
214 long *valuep, int splitp)
73589c9d
CS
215{
216 const char *errmsg;
217 enum cgen_parse_operand_result result_type;
1c4f3780
RH
218 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
219 int reloc_type;
220 bfd_vma ret;
73589c9d
CS
221
222 if (**strp == '#')
223 ++*strp;
224
1c4f3780
RH
225 reloc_type = parse_reloc (strp);
226 if (reloc_type >= 0)
73589c9d 227 {
1c4f3780 228 if (splitp)
73589c9d 229 {
1c4f3780
RH
230 if ((reloc_type & 3) == RTYPE_LO && reloc_type != RTYPE_GOT)
231 reloc_type |= RTYPE_SLO;
232 else
233 return INVALID_STORE_RELOC;
73589c9d 234 }
1c4f3780 235 reloc = or1k_imm16_relocs[reloc_type >> 2][reloc_type & 3];
73589c9d 236 }
73589c9d 237
1c4f3780 238 if (reloc != BFD_RELOC_UNUSED)
73589c9d
CS
239 {
240 bfd_vma value;
241
1c4f3780 242 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
c151b1c6 243 &result_type, &value);
73589c9d 244 if (**strp != ')')
1c4f3780 245 errmsg = MISSING_CLOSING_PARENTHESIS;
73589c9d 246 ++*strp;
73589c9d 247
1c4f3780 248 ret = value;
73589c9d 249
1c4f3780
RH
250 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
251 switch (reloc_type & 3)
252 {
253 case RTYPE_AHI:
254 ret += 0x8000;
255 /* FALLTHRU */
256 case RTYPE_HI:
257 ret >>= 16;
258 /* FALLTHRU */
259 case RTYPE_LO:
260 case RTYPE_SLO:
261 ret &= 0xffff;
262 ret = (ret ^ 0x8000) - 0x8000;
263 break;
264 default:
265 errmsg = INVALID_RELOC_TYPE;
266 }
73589c9d
CS
267 }
268 else
269 {
270 long value;
271 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
272 ret = value;
273 }
274
275 if (errmsg == NULL)
276 *valuep = ret;
277
278 return errmsg;
279}
280
281static const char *
1c4f3780 282parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
73589c9d 283{
1c4f3780
RH
284 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
285}
73589c9d 286
1c4f3780
RH
287static const char *
288parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
289 long *valuep)
290{
291 return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
292}
293
294static const char *
295parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
296 unsigned long *valuep)
297{
298 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
299 if (errmsg == NULL)
300 *valuep &= 0xffff;
301 return errmsg;
302}
303
304static const char *
305parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
306 unsigned long *valuep)
307{
308 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
73589c9d
CS
309 if (errmsg == NULL)
310 *valuep &= 0xffff;
311 return errmsg;
312}
313
314/* -- */
315
316/* -- ibd.h */
317
318/* -- */
This page took 0.212444 seconds and 4 git commands to generate.