Commit | Line | Data |
---|---|---|
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 | ||
50 | static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'"); | |
51 | ||
52 | #define CGEN_VERBOSE_ASSEMBLER_ERRORS | |
53 | ||
54 | static const char * | |
55 | parse_disp26 (CGEN_CPU_DESC cd, | |
c151b1c6 AM |
56 | const char ** strp, |
57 | int opindex, | |
58 | int opinfo, | |
59 | enum cgen_parse_operand_result * resultp, | |
60 | bfd_vma * valuep) | |
73589c9d CS |
61 | { |
62 | const char *errmsg = NULL; | |
63 | enum cgen_parse_operand_result result_type; | |
64 | ||
65 | if (strncasecmp (*strp, "plt(", 4) == 0) | |
66 | { | |
67 | bfd_vma value; | |
68 | ||
69 | *strp += 4; | |
70 | errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26, | |
c151b1c6 | 71 | & result_type, & value); |
73589c9d | 72 | if (**strp != ')') |
c151b1c6 | 73 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
74 | ++*strp; |
75 | if (errmsg == NULL | |
c151b1c6 AM |
76 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
77 | value = (value >> 2) & 0xffff; | |
73589c9d CS |
78 | *valuep = value; |
79 | return errmsg; | |
80 | } | |
81 | return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep); | |
82 | } | |
83 | ||
84 | static const char * | |
85 | parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep) | |
86 | { | |
87 | const char *errmsg; | |
88 | enum cgen_parse_operand_result result_type; | |
89 | long ret; | |
90 | ||
91 | if (**strp == '#') | |
92 | ++*strp; | |
93 | ||
94 | if (strncasecmp (*strp, "hi(", 3) == 0) | |
95 | { | |
96 | bfd_vma value; | |
97 | ||
98 | *strp += 3; | |
99 | errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, | |
c151b1c6 | 100 | & result_type, & value); |
73589c9d | 101 | if (**strp != ')') |
c151b1c6 | 102 | errmsg = MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
103 | ++*strp; |
104 | ||
105 | ret = value; | |
106 | ||
107 | if (errmsg == NULL | |
108 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) | |
109 | { | |
110 | ret >>= 16; | |
111 | ret &= 0xffff; | |
112 | ret = (ret ^ 0x8000) - 0x8000; | |
113 | } | |
114 | } | |
115 | else if (strncasecmp (*strp, "lo(", 3) == 0) | |
116 | { | |
117 | bfd_vma value; | |
118 | ||
119 | *strp += 3; | |
120 | errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, | |
c151b1c6 | 121 | & result_type, & value); |
73589c9d | 122 | if (**strp != ')') |
c151b1c6 | 123 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
124 | ++*strp; |
125 | ||
126 | ret = value; | |
127 | ||
128 | if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) | |
129 | { | |
130 | ret &= 0xffff; | |
131 | ret = (ret ^ 0x8000) - 0x8000; | |
132 | } | |
133 | } | |
134 | else if (strncasecmp (*strp, "got(", 4) == 0) | |
135 | { | |
136 | bfd_vma value; | |
137 | ||
138 | *strp += 4; | |
139 | errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16, | |
c151b1c6 | 140 | & result_type, & value); |
73589c9d | 141 | if (**strp != ')') |
c151b1c6 | 142 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
143 | ++*strp; |
144 | if (errmsg == NULL | |
c151b1c6 AM |
145 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
146 | value &= 0xffff; | |
73589c9d CS |
147 | *valuep = value; |
148 | return errmsg; | |
149 | } | |
150 | else if (strncasecmp (*strp, "gotpchi(", 8) == 0) | |
151 | { | |
152 | bfd_vma value; | |
153 | ||
154 | *strp += 8; | |
155 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
156 | BFD_RELOC_OR1K_GOTPC_HI16, |
157 | & result_type, & value); | |
73589c9d | 158 | if (**strp != ')') |
c151b1c6 | 159 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
160 | ++*strp; |
161 | if (errmsg == NULL | |
c151b1c6 AM |
162 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
163 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
164 | *valuep = value; |
165 | return errmsg; | |
166 | } | |
167 | else if (strncasecmp (*strp, "gotpclo(", 8) == 0) | |
168 | { | |
169 | bfd_vma value; | |
170 | ||
171 | *strp += 8; | |
172 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
173 | BFD_RELOC_OR1K_GOTPC_LO16, |
174 | &result_type, &value); | |
73589c9d | 175 | if (**strp != ')') |
c151b1c6 | 176 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
177 | ++*strp; |
178 | if (errmsg == NULL | |
c151b1c6 AM |
179 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
180 | value &= 0xffff; | |
73589c9d CS |
181 | *valuep = value; |
182 | return errmsg; | |
183 | } | |
184 | else if (strncasecmp (*strp, "gotoffhi(", 9) == 0) | |
185 | { | |
186 | bfd_vma value; | |
187 | ||
188 | *strp += 9; | |
189 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
190 | BFD_RELOC_OR1K_GOTOFF_HI16, |
191 | & result_type, & value); | |
73589c9d CS |
192 | |
193 | if (**strp != ')') | |
c151b1c6 | 194 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
195 | ++*strp; |
196 | if (errmsg == NULL | |
c151b1c6 AM |
197 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
198 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
199 | *valuep = value; |
200 | return errmsg; | |
201 | } | |
202 | else if (strncasecmp (*strp, "gotofflo(", 9) == 0) | |
203 | { | |
204 | bfd_vma value; | |
205 | ||
206 | *strp += 9; | |
207 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
208 | BFD_RELOC_OR1K_GOTOFF_LO16, |
209 | &result_type, &value); | |
73589c9d | 210 | if (**strp != ')') |
c151b1c6 | 211 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
212 | ++*strp; |
213 | if (errmsg == NULL | |
c151b1c6 AM |
214 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
215 | value &= 0xffff; | |
73589c9d CS |
216 | *valuep = value; |
217 | return errmsg; | |
218 | } | |
219 | else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0) | |
220 | { | |
221 | bfd_vma value; | |
222 | ||
223 | *strp += 8; | |
224 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
225 | BFD_RELOC_OR1K_TLS_GD_HI16, |
226 | & result_type, & value); | |
73589c9d CS |
227 | |
228 | if (**strp != ')') | |
c151b1c6 | 229 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
230 | ++*strp; |
231 | if (errmsg == NULL | |
c151b1c6 AM |
232 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
233 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
234 | *valuep = value; |
235 | return errmsg; | |
236 | } | |
237 | else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0) | |
238 | { | |
239 | bfd_vma value; | |
240 | ||
241 | *strp += 8; | |
242 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
243 | BFD_RELOC_OR1K_TLS_GD_LO16, |
244 | &result_type, &value); | |
73589c9d | 245 | if (**strp != ')') |
c151b1c6 | 246 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
247 | ++*strp; |
248 | if (errmsg == NULL | |
c151b1c6 AM |
249 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
250 | value &= 0xffff; | |
73589c9d CS |
251 | *valuep = value; |
252 | return errmsg; | |
253 | } | |
254 | else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0) | |
255 | { | |
256 | bfd_vma value; | |
257 | ||
258 | *strp += 9; | |
259 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
260 | BFD_RELOC_OR1K_TLS_LDM_HI16, |
261 | & result_type, & value); | |
73589c9d CS |
262 | |
263 | if (**strp != ')') | |
c151b1c6 | 264 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
265 | ++*strp; |
266 | if (errmsg == NULL | |
c151b1c6 AM |
267 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
268 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
269 | *valuep = value; |
270 | return errmsg; | |
271 | } | |
272 | else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0) | |
273 | { | |
274 | bfd_vma value; | |
275 | ||
276 | *strp += 9; | |
277 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
278 | BFD_RELOC_OR1K_TLS_LDM_LO16, |
279 | &result_type, &value); | |
73589c9d | 280 | if (**strp != ')') |
c151b1c6 | 281 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
282 | ++*strp; |
283 | if (errmsg == NULL | |
c151b1c6 AM |
284 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
285 | value &= 0xffff; | |
73589c9d CS |
286 | *valuep = value; |
287 | return errmsg; | |
288 | } | |
289 | else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0) | |
290 | { | |
291 | bfd_vma value; | |
292 | ||
293 | *strp += 9; | |
294 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
295 | BFD_RELOC_OR1K_TLS_LDO_HI16, |
296 | & result_type, & value); | |
73589c9d CS |
297 | |
298 | if (**strp != ')') | |
c151b1c6 | 299 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
300 | ++*strp; |
301 | if (errmsg == NULL | |
c151b1c6 AM |
302 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
303 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
304 | *valuep = value; |
305 | return errmsg; | |
306 | } | |
307 | else if (strncasecmp (*strp, "dtpofflo(", 9) == 0) | |
308 | { | |
309 | bfd_vma value; | |
310 | ||
311 | *strp += 9; | |
312 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
313 | BFD_RELOC_OR1K_TLS_LDO_LO16, |
314 | &result_type, &value); | |
73589c9d | 315 | if (**strp != ')') |
c151b1c6 | 316 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
317 | ++*strp; |
318 | if (errmsg == NULL | |
c151b1c6 AM |
319 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
320 | value &= 0xffff; | |
73589c9d CS |
321 | *valuep = value; |
322 | return errmsg; | |
323 | } | |
324 | else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0) | |
325 | { | |
326 | bfd_vma value; | |
327 | ||
328 | *strp += 11; | |
329 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
330 | BFD_RELOC_OR1K_TLS_IE_HI16, |
331 | & result_type, & value); | |
73589c9d CS |
332 | |
333 | if (**strp != ')') | |
c151b1c6 | 334 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
335 | ++*strp; |
336 | if (errmsg == NULL | |
c151b1c6 AM |
337 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
338 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
339 | *valuep = value; |
340 | return errmsg; | |
341 | } | |
342 | else if (strncasecmp (*strp, "gottpofflo(", 11) == 0) | |
343 | { | |
344 | bfd_vma value; | |
345 | ||
346 | *strp += 11; | |
347 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
348 | BFD_RELOC_OR1K_TLS_IE_LO16, |
349 | &result_type, &value); | |
73589c9d | 350 | if (**strp != ')') |
c151b1c6 | 351 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
352 | ++*strp; |
353 | if (errmsg == NULL | |
c151b1c6 AM |
354 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
355 | value &= 0xffff; | |
73589c9d CS |
356 | *valuep = value; |
357 | return errmsg; | |
358 | } | |
359 | else if (strncasecmp (*strp, "tpoffhi(", 8) == 0) | |
360 | { | |
361 | bfd_vma value; | |
362 | ||
363 | *strp += 8; | |
364 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
365 | BFD_RELOC_OR1K_TLS_LE_HI16, |
366 | & result_type, & value); | |
73589c9d CS |
367 | |
368 | if (**strp != ')') | |
c151b1c6 | 369 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
370 | ++*strp; |
371 | if (errmsg == NULL | |
c151b1c6 AM |
372 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
373 | value = (value >> 16) & 0xffff; | |
73589c9d CS |
374 | *valuep = value; |
375 | return errmsg; | |
376 | } | |
377 | else if (strncasecmp (*strp, "tpofflo(", 8) == 0) | |
378 | { | |
379 | bfd_vma value; | |
380 | ||
381 | *strp += 8; | |
382 | errmsg = cgen_parse_address (cd, strp, opindex, | |
c151b1c6 AM |
383 | BFD_RELOC_OR1K_TLS_LE_LO16, |
384 | &result_type, &value); | |
73589c9d | 385 | if (**strp != ')') |
c151b1c6 | 386 | return MISSING_CLOSING_PARENTHESIS; |
73589c9d CS |
387 | ++*strp; |
388 | if (errmsg == NULL | |
c151b1c6 AM |
389 | && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) |
390 | value &= 0xffff; | |
73589c9d CS |
391 | *valuep = value; |
392 | return errmsg; | |
393 | } | |
394 | else | |
395 | { | |
396 | long value; | |
397 | errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value); | |
398 | ret = value; | |
399 | } | |
400 | ||
401 | if (errmsg == NULL) | |
402 | *valuep = ret; | |
403 | ||
404 | return errmsg; | |
405 | } | |
406 | ||
407 | static const char * | |
408 | parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep) | |
409 | { | |
410 | const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep); | |
411 | ||
412 | if (errmsg == NULL) | |
413 | *valuep &= 0xffff; | |
414 | return errmsg; | |
415 | } | |
416 | ||
417 | /* -- */ | |
418 | ||
419 | /* -- ibd.h */ | |
420 | ||
421 | /* -- */ |