2006-07-25 Paolo Bonzini <bonzini@gnu.org>
[binutils.git] / cpu / mt.opc
blob7c394e1f0deb6c9e92cff1e6001f95dc14af85bb
1 /* Morpho Technologies mRISC opcode support, for GNU Binutils.  -*- C -*-
2    Copyright 2001 Free Software Foundation, Inc.
4    Contributed by Red Hat Inc; developed under contract from
5    Morpho Technologies.
7    This file is part of the GNU Binutils.
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.
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.
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.
26    Each section is delimited with start and end markers.
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"
35 /* -- opc.h */
37 /* Check applicability of instructions against machines.  */
38 #define CGEN_VALIDATE_INSN_SUPPORTED
40 /* Allows reason codes to be output when assembler errors occur.  */
41 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
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)
48 #define CGEN_ASM_HASH_SIZE 127
49 #define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
51 extern unsigned int mt_asm_hash (const char *);
53 extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
56 /* -- opc.c */
57 #include "safe-ctype.h"
59 /* Special check to ensure that instruction exists for given machine.  */
61 int
62 mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
64   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
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);
73 /* A better hash function for instruction mnemonics.  */
75 unsigned int
76 mt_asm_hash (const char* insn)
78   unsigned int hash;
79   const char* m = insn;
81   for (hash = 0; *m && ! ISSPACE (*m); m++)
82     hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
84   /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
86   return hash % CGEN_ASM_HASH_SIZE;
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.  */
94 static int 
95 signed_out_of_bounds (long val)
97   if ((val < -32768) || (val > 32767))
98     return 1;
99   return 0;
102 static const char *
103 parse_loopsize (CGEN_CPU_DESC cd,
104                 const char **strp,
105                 int opindex,
106                 void *arg)
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;
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     }
124   abort ();
127 static const char *
128 parse_imm16 (CGEN_CPU_DESC cd,
129              const char **strp,
130              int opindex,
131              void *arg)
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;
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     }
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     }
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;
190              case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
191                /* No special processing for this case.  */
192                break;
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);
207       if ((*strp)[0] == '0'
208           && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
209         parse_signed = 0;
211       /* No relocating operator.  Parse as an number.  */
212       if (parse_signed)
213         {
214           /* Parse as as signed integer.  */
216           errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
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;
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);
240           if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
241               && *valuep >= 0x8000
242               && *valuep <= 0xffff)
243             *valuep -= 0x10000;
244         }
245     }
247   return errmsg;
251 static const char *
252 parse_dup (CGEN_CPU_DESC cd,
253            const char **strp,
254            int opindex,
255            unsigned long *valuep)
257   const char *errmsg = NULL;
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);
272   return errmsg;
276 static const char *
277 parse_ball (CGEN_CPU_DESC cd,
278             const char **strp,
279             int opindex,
280             unsigned long *valuep)
282   const char *errmsg = NULL;
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);
297   return errmsg;
300 static const char *
301 parse_xmode (CGEN_CPU_DESC cd,
302              const char **strp,
303              int opindex,
304              unsigned long *valuep)
306   const char *errmsg = NULL;
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);
321   return errmsg;
324 static const char *
325 parse_rc (CGEN_CPU_DESC cd,
326           const char **strp,
327           int opindex,
328           unsigned long *valuep)
330   const char *errmsg = NULL;
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);
345   return errmsg;
348 static const char *
349 parse_cbrb (CGEN_CPU_DESC cd,
350             const char **strp,
351             int opindex,
352             unsigned long *valuep)
354   const char *errmsg = NULL;
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);
369   return errmsg;
372 static const char *
373 parse_rbbc (CGEN_CPU_DESC cd,
374             const char **strp,
375             int opindex,
376             unsigned long *valuep)
378   const char *errmsg = NULL;
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);
403   return errmsg;
406 static const char *
407 parse_type (CGEN_CPU_DESC cd,
408             const char **strp,
409             int opindex,
410             unsigned long *valuep)
412   const char *errmsg = NULL;
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);
432  if ((errmsg == NULL) && (*valuep == 3))
433     errmsg = _("invalid operand.  type may have values 0,1,2 only.");
435   return errmsg;
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);
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)
450   disassemble_info *info = (disassemble_info *) dis_info;
452   info->fprintf_func (info->stream, "$%lx", value);
454   if (0)
455     print_normal (cd, dis_info, value, attrs, pc, length);
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)
466   print_address (cd, dis_info, value + pc, attrs, pc, length);
469 /* -- */