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