or1k.opc revision 1.1.1.4 1 1.1 christos /* OpenRISC 1000 opcode support. -*- C -*-
2 1.1 christos Copyright 2000-2014 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Originally ontributed for OR32 by Red Hat Inc;
5 1.1 christos
6 1.1 christos This file is part of the GNU Binutils.
7 1.1 christos
8 1.1 christos This program is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3 of the License, or
11 1.1 christos (at your option) any later version.
12 1.1 christos
13 1.1 christos This program is distributed in the hope that it will be useful,
14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 christos GNU General Public License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program; if not, see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos /* This file is an addendum to or1k.cpu. Heavy use of C code isn't
22 1.1 christos appropriate in .cpu files, so it resides here. This especially applies
23 1.1 christos to assembly/disassembly where parsing/printing can be quite involved.
24 1.1 christos Such things aren't really part of the specification of the cpu, per se,
25 1.1 christos so .cpu files provide the general framework and .opc files handle the
26 1.1 christos nitty-gritty details as necessary.
27 1.1 christos
28 1.1 christos Each section is delimited with start and end markers.
29 1.1 christos
30 1.1 christos <arch>-opc.h additions use: "-- opc.h"
31 1.1 christos <arch>-opc.c additions use: "-- opc.c"
32 1.1 christos <arch>-asm.c additions use: "-- asm.c"
33 1.1 christos <arch>-dis.c additions use: "-- dis.c"
34 1.1 christos <arch>-ibd.h additions use: "-- ibd.h" */
35 1.1 christos
36 1.1 christos /* -- opc.h */
37 1.1 christos
38 1.1 christos #undef CGEN_DIS_HASH_SIZE
39 1.1 christos #define CGEN_DIS_HASH_SIZE 256
40 1.1 christos #undef CGEN_DIS_HASH
41 1.1 christos #define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
42 1.1 christos
43 1.1.1.3 christos /* Check applicability of instructions against machines. */
44 1.1.1.3 christos #define CGEN_VALIDATE_INSN_SUPPORTED
45 1.1.1.3 christos
46 1.1.1.3 christos extern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
47 1.1.1.3 christos
48 1.1 christos /* -- */
49 1.1 christos
50 1.1 christos /* -- opc.c */
51 1.1.1.3 christos
52 1.1.1.3 christos /* Special check to ensure that instruction exists for given machine. */
53 1.1.1.3 christos
54 1.1.1.3 christos int
55 1.1.1.3 christos or1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
56 1.1.1.3 christos {
57 1.1.1.3 christos int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
58 1.1.1.3 christos
59 1.1.1.3 christos /* No mach attribute? Assume it's supported for all machs. */
60 1.1.1.3 christos if (machs == 0)
61 1.1.1.3 christos return 1;
62 1.1.1.3 christos
63 1.1.1.3 christos return ((machs & cd->machs) != 0);
64 1.1.1.3 christos }
65 1.1.1.3 christos
66 1.1 christos /* -- */
67 1.1 christos
68 1.1 christos /* -- asm.c */
69 1.1 christos
70 1.1 christos static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
71 1.1.1.2 christos static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
72 1.1.1.2 christos static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
73 1.1 christos
74 1.1 christos #define CGEN_VERBOSE_ASSEMBLER_ERRORS
75 1.1 christos
76 1.1 christos static const char *
77 1.1 christos parse_disp26 (CGEN_CPU_DESC cd,
78 1.1 christos const char ** strp,
79 1.1 christos int opindex,
80 1.1.1.2 christos int opinfo ATTRIBUTE_UNUSED,
81 1.1 christos enum cgen_parse_operand_result * resultp,
82 1.1 christos bfd_vma * valuep)
83 1.1 christos {
84 1.1.1.2 christos const char *str = *strp;
85 1.1 christos const char *errmsg = NULL;
86 1.1.1.2 christos bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
87 1.1 christos
88 1.1.1.2 christos if (strncasecmp (str, "plta(", 5) == 0)
89 1.1 christos {
90 1.1.1.2 christos *strp = str + 5;
91 1.1.1.2 christos reloc = BFD_RELOC_OR1K_PLTA26;
92 1.1.1.2 christos }
93 1.1.1.2 christos else if (strncasecmp (str, "plt(", 4) == 0)
94 1.1.1.2 christos {
95 1.1.1.2 christos *strp = str + 4;
96 1.1.1.2 christos reloc = BFD_RELOC_OR1K_PLT26;
97 1.1 christos }
98 1.1 christos
99 1.1.1.2 christos errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
100 1.1 christos
101 1.1.1.2 christos if (reloc != BFD_RELOC_OR1K_REL_26)
102 1.1 christos {
103 1.1 christos if (**strp != ')')
104 1.1 christos errmsg = MISSING_CLOSING_PARENTHESIS;
105 1.1.1.2 christos else
106 1.1.1.2 christos ++*strp;
107 1.1 christos }
108 1.1 christos
109 1.1.1.2 christos return errmsg;
110 1.1.1.2 christos }
111 1.1 christos
112 1.1.1.2 christos static const char *
113 1.1.1.2 christos parse_disp21 (CGEN_CPU_DESC cd,
114 1.1.1.2 christos const char ** strp,
115 1.1.1.2 christos int opindex,
116 1.1.1.2 christos int opinfo ATTRIBUTE_UNUSED,
117 1.1.1.2 christos enum cgen_parse_operand_result * resultp,
118 1.1.1.2 christos bfd_vma * valuep)
119 1.1.1.2 christos {
120 1.1.1.2 christos const char *str = *strp;
121 1.1.1.2 christos const char *errmsg = NULL;
122 1.1.1.2 christos bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
123 1.1 christos
124 1.1.1.2 christos if (strncasecmp (str, "got(", 4) == 0)
125 1.1 christos {
126 1.1.1.2 christos *strp = str + 4;
127 1.1.1.2 christos reloc = BFD_RELOC_OR1K_GOT_PG21;
128 1.1 christos }
129 1.1.1.2 christos else if (strncasecmp (str, "tlsgd(", 6) == 0)
130 1.1 christos {
131 1.1.1.2 christos *strp = str + 6;
132 1.1.1.2 christos reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
133 1.1 christos }
134 1.1.1.2 christos else if (strncasecmp (str, "tlsldm(", 7) == 0)
135 1.1 christos {
136 1.1.1.2 christos *strp = str + 7;
137 1.1.1.2 christos reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
138 1.1 christos }
139 1.1.1.2 christos else if (strncasecmp (str, "gottp(", 6) == 0)
140 1.1 christos {
141 1.1.1.2 christos *strp = str + 6;
142 1.1.1.2 christos reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
143 1.1.1.2 christos }
144 1.1 christos
145 1.1.1.2 christos errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
146 1.1 christos
147 1.1.1.2 christos if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
148 1.1 christos {
149 1.1 christos if (**strp != ')')
150 1.1.1.2 christos errmsg = MISSING_CLOSING_PARENTHESIS;
151 1.1.1.2 christos else
152 1.1.1.2 christos ++*strp;
153 1.1 christos }
154 1.1 christos
155 1.1.1.2 christos return errmsg;
156 1.1.1.2 christos }
157 1.1 christos
158 1.1.1.2 christos enum or1k_rclass
159 1.1.1.2 christos {
160 1.1.1.2 christos RCLASS_DIRECT = 0,
161 1.1.1.2 christos RCLASS_GOT = 1,
162 1.1.1.2 christos RCLASS_GOTPC = 2,
163 1.1.1.2 christos RCLASS_GOTOFF = 3,
164 1.1.1.2 christos RCLASS_TLSGD = 4,
165 1.1.1.2 christos RCLASS_TLSLDM = 5,
166 1.1.1.2 christos RCLASS_DTPOFF = 6,
167 1.1.1.2 christos RCLASS_GOTTPOFF = 7,
168 1.1.1.2 christos RCLASS_TPOFF = 8,
169 1.1.1.2 christos };
170 1.1 christos
171 1.1.1.2 christos enum or1k_rtype
172 1.1.1.2 christos {
173 1.1.1.2 christos RTYPE_LO = 0,
174 1.1.1.2 christos RTYPE_SLO = 1,
175 1.1.1.2 christos RTYPE_PO = 2,
176 1.1.1.2 christos RTYPE_SPO = 3,
177 1.1.1.2 christos RTYPE_HI = 4,
178 1.1.1.2 christos RTYPE_AHI = 5,
179 1.1.1.2 christos };
180 1.1.1.2 christos
181 1.1.1.2 christos #define RCLASS_SHIFT 3
182 1.1.1.2 christos #define RTYPE_MASK 7
183 1.1.1.2 christos
184 1.1.1.2 christos static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
185 1.1.1.2 christos { BFD_RELOC_LO16,
186 1.1.1.2 christos BFD_RELOC_OR1K_SLO16,
187 1.1.1.2 christos BFD_RELOC_OR1K_LO13,
188 1.1.1.2 christos BFD_RELOC_OR1K_SLO13,
189 1.1.1.2 christos BFD_RELOC_HI16,
190 1.1.1.2 christos BFD_RELOC_HI16_S, },
191 1.1.1.2 christos { BFD_RELOC_OR1K_GOT16,
192 1.1.1.2 christos BFD_RELOC_UNUSED,
193 1.1.1.2 christos BFD_RELOC_OR1K_GOT_LO13,
194 1.1.1.2 christos BFD_RELOC_UNUSED,
195 1.1.1.2 christos BFD_RELOC_UNUSED,
196 1.1.1.4 christos BFD_RELOC_OR1K_GOT_AHI16 },
197 1.1.1.2 christos { BFD_RELOC_OR1K_GOTPC_LO16,
198 1.1.1.2 christos BFD_RELOC_UNUSED,
199 1.1.1.2 christos BFD_RELOC_UNUSED,
200 1.1.1.2 christos BFD_RELOC_UNUSED,
201 1.1.1.2 christos BFD_RELOC_OR1K_GOTPC_HI16,
202 1.1.1.2 christos BFD_RELOC_UNUSED },
203 1.1.1.2 christos { BFD_RELOC_LO16_GOTOFF,
204 1.1.1.2 christos BFD_RELOC_OR1K_GOTOFF_SLO16,
205 1.1.1.2 christos BFD_RELOC_UNUSED,
206 1.1.1.2 christos BFD_RELOC_UNUSED,
207 1.1.1.2 christos BFD_RELOC_HI16_GOTOFF,
208 1.1.1.2 christos BFD_RELOC_HI16_S_GOTOFF },
209 1.1.1.2 christos { BFD_RELOC_OR1K_TLS_GD_LO16,
210 1.1.1.2 christos BFD_RELOC_UNUSED,
211 1.1.1.2 christos BFD_RELOC_OR1K_TLS_GD_LO13,
212 1.1.1.2 christos BFD_RELOC_UNUSED,
213 1.1.1.2 christos BFD_RELOC_OR1K_TLS_GD_HI16,
214 1.1.1.2 christos BFD_RELOC_UNUSED },
215 1.1.1.2 christos { BFD_RELOC_OR1K_TLS_LDM_LO16,
216 1.1.1.2 christos BFD_RELOC_UNUSED,
217 1.1.1.2 christos BFD_RELOC_OR1K_TLS_LDM_LO13,
218 1.1.1.2 christos BFD_RELOC_UNUSED,
219 1.1.1.2 christos BFD_RELOC_OR1K_TLS_LDM_HI16,
220 1.1.1.2 christos BFD_RELOC_UNUSED },
221 1.1.1.2 christos { BFD_RELOC_OR1K_TLS_LDO_LO16,
222 1.1.1.2 christos BFD_RELOC_UNUSED,
223 1.1.1.2 christos BFD_RELOC_UNUSED,
224 1.1.1.2 christos BFD_RELOC_UNUSED,
225 1.1.1.2 christos BFD_RELOC_OR1K_TLS_LDO_HI16,
226 1.1.1.2 christos BFD_RELOC_UNUSED },
227 1.1.1.2 christos { BFD_RELOC_OR1K_TLS_IE_LO16,
228 1.1.1.2 christos BFD_RELOC_UNUSED,
229 1.1.1.2 christos BFD_RELOC_OR1K_TLS_IE_LO13,
230 1.1.1.2 christos BFD_RELOC_UNUSED,
231 1.1.1.2 christos BFD_RELOC_OR1K_TLS_IE_HI16,
232 1.1.1.2 christos BFD_RELOC_OR1K_TLS_IE_AHI16 },
233 1.1.1.2 christos { BFD_RELOC_OR1K_TLS_LE_LO16,
234 1.1.1.2 christos BFD_RELOC_OR1K_TLS_LE_SLO16,
235 1.1.1.2 christos BFD_RELOC_UNUSED,
236 1.1.1.2 christos BFD_RELOC_UNUSED,
237 1.1.1.2 christos BFD_RELOC_OR1K_TLS_LE_HI16,
238 1.1.1.2 christos BFD_RELOC_OR1K_TLS_LE_AHI16 },
239 1.1.1.2 christos };
240 1.1 christos
241 1.1.1.2 christos static int
242 1.1.1.2 christos parse_reloc (const char **strp)
243 1.1.1.2 christos {
244 1.1.1.2 christos const char *str = *strp;
245 1.1.1.2 christos enum or1k_rclass cls = RCLASS_DIRECT;
246 1.1.1.2 christos enum or1k_rtype typ;
247 1.1.1.2 christos
248 1.1.1.2 christos if (strncasecmp (str, "got(", 4) == 0)
249 1.1.1.2 christos {
250 1.1.1.2 christos *strp = str + 4;
251 1.1.1.2 christos return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
252 1.1.1.2 christos }
253 1.1.1.2 christos if (strncasecmp (str, "gotpo(", 6) == 0)
254 1.1.1.2 christos {
255 1.1.1.2 christos *strp = str + 6;
256 1.1.1.2 christos return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
257 1.1.1.2 christos }
258 1.1.1.2 christos if (strncasecmp (str, "gottppo(", 8) == 0)
259 1.1.1.2 christos {
260 1.1.1.2 christos *strp = str + 8;
261 1.1.1.2 christos return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
262 1.1.1.2 christos }
263 1.1.1.2 christos
264 1.1.1.2 christos if (strncasecmp (str, "gotpc", 5) == 0)
265 1.1.1.2 christos {
266 1.1.1.2 christos str += 5;
267 1.1.1.2 christos cls = RCLASS_GOTPC;
268 1.1.1.2 christos }
269 1.1.1.2 christos else if (strncasecmp (str, "gotoff", 6) == 0)
270 1.1.1.2 christos {
271 1.1.1.2 christos str += 6;
272 1.1.1.2 christos cls = RCLASS_GOTOFF;
273 1.1.1.2 christos }
274 1.1.1.2 christos else if (strncasecmp (str, "tlsgd", 5) == 0)
275 1.1.1.2 christos {
276 1.1.1.2 christos str += 5;
277 1.1.1.2 christos cls = RCLASS_TLSGD;
278 1.1.1.2 christos }
279 1.1.1.2 christos else if (strncasecmp (str, "tlsldm", 6) == 0)
280 1.1.1.2 christos {
281 1.1.1.2 christos str += 6;
282 1.1.1.2 christos cls = RCLASS_TLSLDM;
283 1.1.1.2 christos }
284 1.1.1.2 christos else if (strncasecmp (str, "dtpoff", 6) == 0)
285 1.1.1.2 christos {
286 1.1.1.2 christos str += 6;
287 1.1.1.2 christos cls = RCLASS_DTPOFF;
288 1.1.1.2 christos }
289 1.1.1.2 christos else if (strncasecmp (str, "gottpoff", 8) == 0)
290 1.1.1.2 christos {
291 1.1.1.2 christos str += 8;
292 1.1.1.2 christos cls = RCLASS_GOTTPOFF;
293 1.1.1.2 christos }
294 1.1.1.2 christos else if (strncasecmp (str, "tpoff", 5) == 0)
295 1.1.1.2 christos {
296 1.1.1.2 christos str += 5;
297 1.1.1.2 christos cls = RCLASS_TPOFF;
298 1.1.1.2 christos }
299 1.1.1.4 christos else if (strncasecmp (str, "got", 3) == 0)
300 1.1.1.4 christos {
301 1.1.1.4 christos str += 3;
302 1.1.1.4 christos cls = RCLASS_GOT;
303 1.1.1.4 christos }
304 1.1.1.2 christos
305 1.1.1.2 christos if (strncasecmp (str, "hi(", 3) == 0)
306 1.1.1.2 christos {
307 1.1.1.2 christos str += 3;
308 1.1.1.2 christos typ = RTYPE_HI;
309 1.1.1.2 christos }
310 1.1.1.2 christos else if (strncasecmp (str, "lo(", 3) == 0)
311 1.1.1.2 christos {
312 1.1.1.2 christos str += 3;
313 1.1.1.2 christos typ = RTYPE_LO;
314 1.1.1.2 christos }
315 1.1.1.2 christos else if (strncasecmp (str, "ha(", 3) == 0)
316 1.1.1.2 christos {
317 1.1.1.2 christos str += 3;
318 1.1.1.2 christos typ = RTYPE_AHI;
319 1.1.1.2 christos }
320 1.1.1.2 christos else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
321 1.1.1.2 christos {
322 1.1.1.2 christos str += 3;
323 1.1.1.2 christos typ = RTYPE_PO;
324 1.1.1.2 christos }
325 1.1.1.2 christos else
326 1.1.1.2 christos return -1;
327 1.1 christos
328 1.1.1.2 christos *strp = str;
329 1.1.1.2 christos return (cls << RCLASS_SHIFT) | typ;
330 1.1.1.2 christos }
331 1.1 christos
332 1.1.1.2 christos static const char *
333 1.1.1.2 christos parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
334 1.1.1.2 christos long *valuep, int splitp)
335 1.1.1.2 christos {
336 1.1.1.2 christos const char *errmsg;
337 1.1.1.2 christos enum cgen_parse_operand_result result_type;
338 1.1.1.2 christos bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
339 1.1.1.2 christos enum or1k_rtype reloc_type;
340 1.1.1.2 christos int reloc_code;
341 1.1.1.2 christos bfd_vma ret;
342 1.1 christos
343 1.1.1.2 christos if (**strp == '#')
344 1.1.1.2 christos ++*strp;
345 1.1 christos
346 1.1.1.2 christos reloc_code = parse_reloc (strp);
347 1.1.1.2 christos reloc_type = reloc_code & RTYPE_MASK;
348 1.1.1.2 christos if (reloc_code >= 0)
349 1.1 christos {
350 1.1.1.2 christos enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
351 1.1.1.2 christos if (splitp)
352 1.1.1.2 christos {
353 1.1.1.2 christos if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
354 1.1.1.2 christos && reloc_class != RCLASS_GOT)
355 1.1.1.2 christos /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
356 1.1.1.2 christos reloc_type |= 1;
357 1.1.1.2 christos else
358 1.1.1.2 christos return INVALID_STORE_RELOC;
359 1.1.1.2 christos }
360 1.1.1.2 christos reloc = or1k_imm16_relocs[reloc_class][reloc_type];
361 1.1 christos }
362 1.1 christos
363 1.1.1.2 christos if (reloc != BFD_RELOC_UNUSED)
364 1.1 christos {
365 1.1 christos bfd_vma value;
366 1.1 christos
367 1.1.1.2 christos errmsg = cgen_parse_address (cd, strp, opindex, reloc,
368 1.1 christos &result_type, &value);
369 1.1 christos if (**strp != ')')
370 1.1.1.2 christos errmsg = MISSING_CLOSING_PARENTHESIS;
371 1.1 christos ++*strp;
372 1.1 christos
373 1.1.1.2 christos ret = value;
374 1.1 christos
375 1.1.1.2 christos if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
376 1.1.1.2 christos switch (reloc_type)
377 1.1.1.2 christos {
378 1.1.1.2 christos case RTYPE_AHI:
379 1.1.1.2 christos ret += 0x8000;
380 1.1.1.2 christos /* FALLTHRU */
381 1.1.1.2 christos case RTYPE_HI:
382 1.1.1.2 christos ret >>= 16;
383 1.1.1.2 christos /* FALLTHRU */
384 1.1.1.2 christos case RTYPE_LO:
385 1.1.1.2 christos case RTYPE_SLO:
386 1.1.1.2 christos ret &= 0xffff;
387 1.1.1.2 christos ret = (ret ^ 0x8000) - 0x8000;
388 1.1.1.2 christos break;
389 1.1.1.2 christos case RTYPE_PO:
390 1.1.1.2 christos case RTYPE_SPO:
391 1.1.1.2 christos ret &= 0x1fff;
392 1.1.1.2 christos break;
393 1.1.1.2 christos default:
394 1.1.1.2 christos errmsg = INVALID_RELOC_TYPE;
395 1.1.1.2 christos }
396 1.1 christos }
397 1.1 christos else
398 1.1 christos {
399 1.1 christos long value;
400 1.1 christos errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
401 1.1 christos ret = value;
402 1.1 christos }
403 1.1 christos
404 1.1 christos if (errmsg == NULL)
405 1.1 christos *valuep = ret;
406 1.1 christos
407 1.1 christos return errmsg;
408 1.1 christos }
409 1.1 christos
410 1.1 christos static const char *
411 1.1.1.2 christos parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
412 1.1 christos {
413 1.1.1.2 christos return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
414 1.1.1.2 christos }
415 1.1 christos
416 1.1.1.2 christos static const char *
417 1.1.1.2 christos parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
418 1.1.1.2 christos long *valuep)
419 1.1.1.2 christos {
420 1.1.1.2 christos return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
421 1.1.1.2 christos }
422 1.1.1.2 christos
423 1.1.1.2 christos static const char *
424 1.1.1.2 christos parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
425 1.1.1.2 christos unsigned long *valuep)
426 1.1.1.2 christos {
427 1.1.1.2 christos const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
428 1.1.1.2 christos if (errmsg == NULL)
429 1.1.1.2 christos *valuep &= 0xffff;
430 1.1.1.2 christos return errmsg;
431 1.1.1.2 christos }
432 1.1.1.2 christos
433 1.1.1.2 christos static const char *
434 1.1.1.2 christos parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
435 1.1.1.2 christos unsigned long *valuep)
436 1.1.1.2 christos {
437 1.1.1.2 christos const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
438 1.1 christos if (errmsg == NULL)
439 1.1 christos *valuep &= 0xffff;
440 1.1 christos return errmsg;
441 1.1 christos }
442 1.1 christos
443 1.1.1.3 christos /* Parse register pairs with syntax rA,rB to a flag + rA value. */
444 1.1.1.3 christos
445 1.1.1.3 christos static const char *
446 1.1.1.3 christos parse_regpair (CGEN_CPU_DESC cd, const char **strp,
447 1.1.1.3 christos int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
448 1.1.1.3 christos {
449 1.1.1.3 christos long reg1_index;
450 1.1.1.3 christos long reg2_index;
451 1.1.1.3 christos const char *errmsg;
452 1.1.1.3 christos
453 1.1.1.3 christos /* The first part should just be a register. */
454 1.1.1.3 christos errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
455 1.1.1.3 christos ®1_index);
456 1.1.1.3 christos
457 1.1.1.3 christos /* If that worked skip the comma separator. */
458 1.1.1.3 christos if (errmsg == NULL)
459 1.1.1.3 christos {
460 1.1.1.3 christos if (**strp == ',')
461 1.1.1.3 christos ++*strp;
462 1.1.1.3 christos else
463 1.1.1.3 christos errmsg = "Unexpected character, expected ','";
464 1.1.1.3 christos }
465 1.1.1.3 christos
466 1.1.1.3 christos /* If that worked the next part is just another register. */
467 1.1.1.3 christos if (errmsg == NULL)
468 1.1.1.3 christos errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
469 1.1.1.3 christos ®2_index);
470 1.1.1.3 christos
471 1.1.1.3 christos /* Validate the register pair is valid and create the output value. */
472 1.1.1.3 christos if (errmsg == NULL)
473 1.1.1.3 christos {
474 1.1.1.3 christos int regoffset = reg2_index - reg1_index;
475 1.1.1.3 christos
476 1.1.1.3 christos if (regoffset == 1 || regoffset == 2)
477 1.1.1.3 christos {
478 1.1.1.3 christos unsigned short offsetmask;
479 1.1.1.3 christos unsigned short value;
480 1.1.1.3 christos
481 1.1.1.3 christos offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
482 1.1.1.3 christos value = offsetmask | reg1_index;
483 1.1.1.3 christos
484 1.1.1.3 christos *valuep = value;
485 1.1.1.3 christos }
486 1.1.1.3 christos else
487 1.1.1.3 christos errmsg = "Invalid register pair, offset not 1 or 2.";
488 1.1.1.3 christos }
489 1.1.1.3 christos
490 1.1.1.3 christos return errmsg;
491 1.1.1.3 christos }
492 1.1.1.3 christos
493 1.1.1.3 christos /* -- */
494 1.1.1.3 christos
495 1.1.1.3 christos /* -- dis.c */
496 1.1.1.3 christos
497 1.1.1.3 christos static void
498 1.1.1.3 christos print_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
499 1.1.1.3 christos void * dis_info,
500 1.1.1.3 christos long value,
501 1.1.1.3 christos unsigned int attrs ATTRIBUTE_UNUSED,
502 1.1.1.3 christos bfd_vma pc ATTRIBUTE_UNUSED,
503 1.1.1.3 christos int length ATTRIBUTE_UNUSED)
504 1.1.1.3 christos {
505 1.1.1.3 christos disassemble_info *info = dis_info;
506 1.1.1.3 christos char reg1_index;
507 1.1.1.3 christos char reg2_index;
508 1.1.1.3 christos
509 1.1.1.3 christos reg1_index = value & 0x1f;
510 1.1.1.3 christos reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
511 1.1.1.3 christos
512 1.1.1.3 christos (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
513 1.1.1.3 christos }
514 1.1.1.3 christos
515 1.1 christos /* -- */
516 1.1 christos
517 1.1 christos /* -- ibd.h */
518 1.1 christos
519 1.1 christos /* -- */
520