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 `)'"); | |
1c4f3780 RH |
51 | static const char * INVALID_STORE_RELOC = N_("relocation invalid for store"); |
52 | static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid"); | |
73589c9d CS |
53 | |
54 | #define CGEN_VERBOSE_ASSEMBLER_ERRORS | |
55 | ||
56 | static const char * | |
57 | parse_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 |
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 | ||
73589c9d | 212 | static const char * |
1c4f3780 RH |
213 | parse_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 | ||
281 | static const char * | |
1c4f3780 | 282 | parse_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 |
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); | |
73589c9d CS |
309 | if (errmsg == NULL) |
310 | *valuep &= 0xffff; | |
311 | return errmsg; | |
312 | } | |
313 | ||
314 | /* -- */ | |
315 | ||
316 | /* -- ibd.h */ | |
317 | ||
318 | /* -- */ |