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