or1k: Add relocations for high-signed and low-stores
[deliverable/binutils-gdb.git] / cpu / or1k.opc
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
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");
53
54 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
55
56 static const char *
57 parse_disp26 (CGEN_CPU_DESC cd,
58 const char ** strp,
59 int opindex,
60 int opinfo,
61 enum cgen_parse_operand_result * resultp,
62 bfd_vma * valuep)
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,
73 & result_type, & value);
74 if (**strp != ')')
75 return MISSING_CLOSING_PARENTHESIS;
76 ++*strp;
77 if (errmsg == NULL
78 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
79 value = (value >> 2) & 0xffff;
80 *valuep = value;
81 return errmsg;
82 }
83 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
84 }
85
86 enum
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
103 static 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
142 static int
143 parse_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
212 static const char *
213 parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
214 long *valuep, int splitp)
215 {
216 const char *errmsg;
217 enum cgen_parse_operand_result result_type;
218 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
219 int reloc_type;
220 bfd_vma ret;
221
222 if (**strp == '#')
223 ++*strp;
224
225 reloc_type = parse_reloc (strp);
226 if (reloc_type >= 0)
227 {
228 if (splitp)
229 {
230 if ((reloc_type & 3) == RTYPE_LO && reloc_type != RTYPE_GOT)
231 reloc_type |= RTYPE_SLO;
232 else
233 return INVALID_STORE_RELOC;
234 }
235 reloc = or1k_imm16_relocs[reloc_type >> 2][reloc_type & 3];
236 }
237
238 if (reloc != BFD_RELOC_UNUSED)
239 {
240 bfd_vma value;
241
242 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
243 &result_type, &value);
244 if (**strp != ')')
245 errmsg = MISSING_CLOSING_PARENTHESIS;
246 ++*strp;
247
248 ret = value;
249
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 }
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
281 static const char *
282 parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
283 {
284 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
285 }
286
287 static const char *
288 parse_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
294 static const char *
295 parse_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
304 static const char *
305 parse_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);
309 if (errmsg == NULL)
310 *valuep &= 0xffff;
311 return errmsg;
312 }
313
314 /* -- */
315
316 /* -- ibd.h */
317
318 /* -- */
This page took 0.063614 seconds and 5 git commands to generate.