mt.opc revision 1.3 1 1.1 christos /* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-
2 1.1 christos Copyright 2001, 2007, 2008, 2009, 2012 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Contributed by Red Hat Inc; developed under contract from
5 1.1 christos Morpho Technologies.
6 1.1 christos
7 1.1 christos This file is part of the GNU Binutils.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program; if not, write to the Free Software
21 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 1.1 christos MA 02110-1301, USA. */
23 1.1 christos
24 1.1 christos
25 1.1 christos /* Each section is delimited with start and end markers.
26 1.1 christos
27 1.1 christos <arch>-opc.h additions use: "-- opc.h"
28 1.1 christos <arch>-opc.c additions use: "-- opc.c"
29 1.1 christos <arch>-asm.c additions use: "-- asm.c"
30 1.1 christos <arch>-dis.c additions use: "-- dis.c"
31 1.1 christos <arch>-ibd.h additions use: "-- ibd.h" */
32 1.1 christos
33 1.1 christos /* -- opc.h */
35 1.1 christos
36 1.1 christos /* Check applicability of instructions against machines. */
37 1.1 christos #define CGEN_VALIDATE_INSN_SUPPORTED
38 1.1 christos
39 1.1 christos /* Allows reason codes to be output when assembler errors occur. */
40 1.1 christos #define CGEN_VERBOSE_ASSEMBLER_ERRORS
41 1.1 christos
42 1.1 christos /* Override disassembly hashing - there are variable bits in the top
43 1.1 christos byte of these instructions. */
44 1.1 christos #define CGEN_DIS_HASH_SIZE 8
45 1.1 christos #define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
46 1.1 christos
47 1.1 christos #define CGEN_ASM_HASH_SIZE 127
48 1.1 christos #define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
49 1.1 christos
50 1.1 christos extern unsigned int mt_asm_hash (const char *);
51 1.1 christos
52 1.1 christos extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
53 1.1 christos
54 1.1 christos
55 1.1 christos /* -- opc.c */
57 1.1 christos #include "safe-ctype.h"
58 1.1 christos
59 1.1 christos /* Special check to ensure that instruction exists for given machine. */
60 1.1 christos
61 1.1 christos int
62 1.1 christos mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
63 1.1 christos {
64 1.1 christos int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
65 1.1 christos
66 1.1 christos /* No mach attribute? Assume it's supported for all machs. */
67 1.1 christos if (machs == 0)
68 1.1 christos return 1;
69 1.1 christos
70 1.1 christos return ((machs & cd->machs) != 0);
71 1.1 christos }
72 1.1 christos
73 1.1 christos /* A better hash function for instruction mnemonics. */
74 1.1 christos
75 1.1 christos unsigned int
76 1.1 christos mt_asm_hash (const char* insn)
77 1.1 christos {
78 1.1 christos unsigned int hash;
79 1.1 christos const char* m = insn;
80 1.1 christos
81 1.1 christos for (hash = 0; *m && ! ISSPACE (*m); m++)
82 1.1 christos hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
83 1.1 christos
84 1.1 christos /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
85 1.1 christos
86 1.1 christos return hash % CGEN_ASM_HASH_SIZE;
87 1.1 christos }
88 1.1 christos
89 1.1 christos
90 1.1 christos /* -- asm.c */
92 1.1 christos /* Range checking for signed numbers. Returns 0 if acceptable
93 1.1 christos and 1 if the value is out of bounds for a signed quantity. */
94 1.1 christos
95 1.1 christos static int
96 1.1 christos signed_out_of_bounds (long val)
97 1.1 christos {
98 1.1 christos if ((val < -32768) || (val > 32767))
99 1.1 christos return 1;
100 1.1 christos return 0;
101 1.1 christos }
102 1.1 christos
103 1.1 christos static const char *
104 1.1 christos parse_loopsize (CGEN_CPU_DESC cd,
105 1.1 christos const char **strp,
106 1.1 christos int opindex,
107 1.1 christos void *arg)
108 1.1 christos {
109 1.1 christos signed long * valuep = (signed long *) arg;
110 1.1 christos const char *errmsg;
111 1.1 christos bfd_reloc_code_real_type code = BFD_RELOC_NONE;
112 1.1 christos enum cgen_parse_operand_result result_type;
113 1.1 christos bfd_vma value;
114 1.1 christos
115 1.1 christos /* Is it a control transfer instructions? */
116 1.1 christos if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
117 1.1 christos {
118 1.1 christos code = BFD_RELOC_MT_PCINSN8;
119 1.1 christos errmsg = cgen_parse_address (cd, strp, opindex, code,
120 1.1 christos & result_type, & value);
121 1.1 christos *valuep = value;
122 1.1 christos return errmsg;
123 1.1 christos }
124 1.1 christos
125 1.1 christos abort ();
126 1.1 christos }
127 1.1 christos
128 1.1 christos static const char *
129 1.1 christos parse_imm16 (CGEN_CPU_DESC cd,
130 1.1 christos const char **strp,
131 1.1 christos int opindex,
132 1.1 christos void *arg)
133 1.1 christos {
134 1.1 christos signed long * valuep = (signed long *) arg;
135 1.1 christos const char *errmsg;
136 1.1 christos enum cgen_parse_operand_result result_type;
137 1.1 christos bfd_reloc_code_real_type code = BFD_RELOC_NONE;
138 1.1 christos bfd_vma value;
139 1.1 christos
140 1.1 christos /* Is it a control transfer instructions? */
141 1.1 christos if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
142 1.1 christos {
143 1.1 christos code = BFD_RELOC_16_PCREL;
144 1.1 christos errmsg = cgen_parse_address (cd, strp, opindex, code,
145 1.1 christos & result_type, & value);
146 1.1 christos if (errmsg == NULL)
147 1.1 christos {
148 1.1 christos if (signed_out_of_bounds (value))
149 1.1 christos errmsg = _("Operand out of range. Must be between -32768 and 32767.");
150 1.1 christos }
151 1.1 christos *valuep = value;
152 1.1 christos return errmsg;
153 1.1 christos }
154 1.1 christos
155 1.1 christos /* If it's not a control transfer instruction, then
156 1.1 christos we have to check for %OP relocating operators. */
157 1.1 christos if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
158 1.1 christos ;
159 1.1 christos else if (strncmp (*strp, "%hi16", 5) == 0)
160 1.1 christos {
161 1.1 christos *strp += 5;
162 1.1 christos code = BFD_RELOC_HI16;
163 1.1 christos }
164 1.1 christos else if (strncmp (*strp, "%lo16", 5) == 0)
165 1.1 christos {
166 1.1 christos *strp += 5;
167 1.1 christos code = BFD_RELOC_LO16;
168 1.1 christos }
169 1.1 christos
170 1.1 christos /* If we found a %OP relocating operator, then parse it as an address.
171 1.1 christos If not, we need to parse it as an integer, either signed or unsigned
172 1.1 christos depending on which operand type we have. */
173 1.1 christos if (code != BFD_RELOC_NONE)
174 1.1 christos {
175 1.1 christos /* %OP relocating operator found. */
176 1.1 christos errmsg = cgen_parse_address (cd, strp, opindex, code,
177 1.1 christos & result_type, & value);
178 1.1 christos if (errmsg == NULL)
179 1.1 christos {
180 1.1 christos switch (result_type)
181 1.1 christos {
182 1.1 christos case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
183 1.1 christos if (code == BFD_RELOC_HI16)
184 1.1 christos value = (value >> 16) & 0xFFFF;
185 1.1 christos else if (code == BFD_RELOC_LO16)
186 1.1 christos value = value & 0xFFFF;
187 1.1 christos else
188 1.1 christos errmsg = _("Biiiig Trouble in parse_imm16!");
189 1.1 christos break;
190 1.1 christos
191 1.1 christos case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
192 1.1 christos /* No special processing for this case. */
193 1.1 christos break;
194 1.1 christos
195 1.1 christos default:
196 1.1 christos errmsg = _("The percent-operator's operand is not a symbol");
197 1.1 christos break;
198 1.1 christos }
199 1.1 christos }
200 1.1 christos *valuep = value;
201 1.1 christos }
202 1.1 christos else
203 1.1 christos {
204 1.1 christos /* Parse hex values like 0xffff as unsigned, and sign extend
205 1.1 christos them manually. */
206 1.1 christos int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
207 1.1 christos
208 1.1 christos if ((*strp)[0] == '0'
209 1.1 christos && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
210 1.1 christos parse_signed = 0;
211 1.1 christos
212 1.1 christos /* No relocating operator. Parse as an number. */
213 1.1 christos if (parse_signed)
214 1.1 christos {
215 1.1 christos /* Parse as as signed integer. */
216 1.1 christos
217 1.1 christos errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
218 1.1 christos
219 1.1 christos if (errmsg == NULL)
220 1.1 christos {
221 1.1 christos #if 0
222 1.1 christos /* Manual range checking is needed for the signed case. */
223 1.1 christos if (*valuep & 0x8000)
224 1.1 christos value = 0xffff0000 | *valuep;
225 1.1 christos else
226 1.1 christos value = *valuep;
227 1.1 christos
228 1.1 christos if (signed_out_of_bounds (value))
229 1.1 christos errmsg = _("Operand out of range. Must be between -32768 and 32767.");
230 1.1 christos /* Truncate to 16 bits. This is necessary
231 1.1 christos because cgen will have sign extended *valuep. */
232 1.1 christos *valuep &= 0xFFFF;
233 1.1 christos #endif
234 1.1 christos }
235 1.1 christos }
236 1.1 christos else
237 1.1 christos {
238 1.1 christos /* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */
239 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
240 1.1 christos
241 1.1 christos if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
242 1.1 christos && *valuep >= 0x8000
243 1.1 christos && *valuep <= 0xffff)
244 1.1 christos *valuep -= 0x10000;
245 1.1 christos }
246 1.1 christos }
247 1.1 christos
248 1.1 christos return errmsg;
249 1.1 christos }
250 1.1 christos
251 1.1 christos
252 1.1 christos static const char *
253 1.1 christos parse_dup (CGEN_CPU_DESC cd,
254 1.1 christos const char **strp,
255 1.1 christos int opindex,
256 1.1 christos unsigned long *valuep)
257 1.1 christos {
258 1.1 christos const char *errmsg = NULL;
259 1.1 christos
260 1.1 christos if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
261 1.1 christos {
262 1.1 christos *strp += 3;
263 1.1 christos *valuep = 1;
264 1.1 christos }
265 1.1 christos else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
266 1.1 christos {
267 1.1 christos *strp += 2;
268 1.1 christos *valuep = 0;
269 1.1 christos }
270 1.1 christos else
271 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
272 1.1 christos
273 1.1 christos return errmsg;
274 1.1 christos }
275 1.1 christos
276 1.1 christos
277 1.1 christos static const char *
278 1.1 christos parse_ball (CGEN_CPU_DESC cd,
279 1.1 christos const char **strp,
280 1.1 christos int opindex,
281 1.1 christos unsigned long *valuep)
282 1.1 christos {
283 1.1 christos const char *errmsg = NULL;
284 1.1 christos
285 1.1 christos if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
286 1.1 christos {
287 1.1 christos *strp += 3;
288 1.1 christos *valuep = 1;
289 1.1 christos }
290 1.1 christos else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
291 1.1 christos {
292 1.1 christos *strp += 3;
293 1.1 christos *valuep = 0;
294 1.1 christos }
295 1.1 christos else
296 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
297 1.1 christos
298 1.1 christos return errmsg;
299 1.1 christos }
300 1.1 christos
301 1.1 christos static const char *
302 1.1 christos parse_xmode (CGEN_CPU_DESC cd,
303 1.1 christos const char **strp,
304 1.1 christos int opindex,
305 1.1 christos unsigned long *valuep)
306 1.1 christos {
307 1.1 christos const char *errmsg = NULL;
308 1.1 christos
309 1.1 christos if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
310 1.1 christos {
311 1.1 christos *strp += 2;
312 1.1 christos *valuep = 1;
313 1.1 christos }
314 1.1 christos else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
315 1.1 christos {
316 1.1 christos *strp += 2;
317 1.1 christos *valuep = 0;
318 1.1 christos }
319 1.1 christos else
320 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
321 1.1 christos
322 1.1 christos return errmsg;
323 1.1 christos }
324 1.1 christos
325 1.1 christos static const char *
326 1.1 christos parse_rc (CGEN_CPU_DESC cd,
327 1.1 christos const char **strp,
328 1.1 christos int opindex,
329 1.1 christos unsigned long *valuep)
330 1.1 christos {
331 1.1 christos const char *errmsg = NULL;
332 1.1 christos
333 1.1 christos if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
334 1.1 christos {
335 1.1 christos *strp += 1;
336 1.1 christos *valuep = 1;
337 1.1 christos }
338 1.1 christos else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
339 1.1 christos {
340 1.1 christos *strp += 1;
341 1.1 christos *valuep = 0;
342 1.1 christos }
343 1.1 christos else
344 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
345 1.1 christos
346 1.1 christos return errmsg;
347 1.1 christos }
348 1.1 christos
349 1.1 christos static const char *
350 1.1 christos parse_cbrb (CGEN_CPU_DESC cd,
351 1.1 christos const char **strp,
352 1.1 christos int opindex,
353 1.1 christos unsigned long *valuep)
354 1.1 christos {
355 1.1 christos const char *errmsg = NULL;
356 1.1 christos
357 1.1 christos if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
358 1.1 christos {
359 1.1 christos *strp += 2;
360 1.1 christos *valuep = 1;
361 1.1 christos }
362 1.1 christos else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
363 1.1 christos {
364 1.1 christos *strp += 2;
365 1.1 christos *valuep = 0;
366 1.1 christos }
367 1.1 christos else
368 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
369 1.1 christos
370 1.1 christos return errmsg;
371 1.1 christos }
372 1.1 christos
373 1.1 christos static const char *
374 1.1 christos parse_rbbc (CGEN_CPU_DESC cd,
375 1.1 christos const char **strp,
376 1.1 christos int opindex,
377 1.1 christos unsigned long *valuep)
378 1.1 christos {
379 1.1 christos const char *errmsg = NULL;
380 1.1 christos
381 1.1 christos if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
382 1.1 christos {
383 1.1 christos *strp += 2;
384 1.1 christos *valuep = 0;
385 1.1 christos }
386 1.1 christos else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
387 1.1 christos {
388 1.1 christos *strp += 3;
389 1.1 christos *valuep = 1;
390 1.1 christos }
391 1.1 christos else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
392 1.1 christos {
393 1.1 christos *strp += 3;
394 1.1 christos *valuep = 2;
395 1.1 christos }
396 1.1 christos else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
397 1.1 christos {
398 1.1 christos *strp += 2;
399 1.1 christos *valuep = 3;
400 1.1 christos }
401 1.1 christos else
402 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
403 1.1 christos
404 1.1 christos return errmsg;
405 1.1 christos }
406 1.1 christos
407 1.1 christos static const char *
408 1.1 christos parse_type (CGEN_CPU_DESC cd,
409 1.1 christos const char **strp,
410 1.1 christos int opindex,
411 1.1 christos unsigned long *valuep)
412 1.1 christos {
413 1.1 christos const char *errmsg = NULL;
414 1.1 christos
415 1.1 christos if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
416 1.1 christos {
417 1.1 christos *strp += 3;
418 1.1 christos *valuep = 0;
419 1.1 christos }
420 1.1 christos else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
421 1.1 christos {
422 1.1 christos *strp += 4;
423 1.1 christos *valuep = 1;
424 1.1 christos }
425 1.1 christos else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
426 1.1 christos {
427 1.1 christos *strp += 2;
428 1.1 christos *valuep = 2;
429 1.1 christos }
430 1.1 christos else
431 1.1 christos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
432 1.1 christos
433 1.1 christos if ((errmsg == NULL) && (*valuep == 3))
434 1.1 christos errmsg = _("invalid operand. type may have values 0,1,2 only.");
435 1.1 christos
436 1.1 christos return errmsg;
437 1.1 christos }
438 1.1 christos
439 1.1 christos /* -- dis.c */
440 1.1 christos static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
441 1.1 christos static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
442 1.1 christos
443 1.1 christos static void
444 1.1 christos print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
445 1.1 christos void * dis_info,
446 1.1 christos long value,
447 1.1 christos unsigned int attrs ATTRIBUTE_UNUSED,
448 1.1 christos bfd_vma pc ATTRIBUTE_UNUSED,
449 1.1 christos int length ATTRIBUTE_UNUSED)
450 1.1 christos {
451 1.1 christos disassemble_info *info = (disassemble_info *) dis_info;
452 1.1 christos
453 1.1 christos info->fprintf_func (info->stream, "$%lx", value & 0xffffffff);
454 1.1 christos
455 1.1 christos if (0)
456 1.1 christos print_normal (cd, dis_info, value, attrs, pc, length);
457 1.1 christos }
458 1.1 christos
459 1.1 christos static void
460 1.1 christos print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
461 1.1 christos void * dis_info,
462 1.1 christos long value,
463 1.1 christos unsigned int attrs ATTRIBUTE_UNUSED,
464 1.1 christos bfd_vma pc ATTRIBUTE_UNUSED,
465 1.1 christos int length ATTRIBUTE_UNUSED)
466 1.1 christos {
467 1.1 christos print_address (cd, dis_info, value + pc, attrs, pc, length);
468 1.1 christos }
469 1.1 christos
470 1.1 christos /* -- */
471 1.1 christos
472 1.1 christos
473
474
475
476