[bfd]
[binutils.git] / cpu / ms1.opc
blob3655f14d458ef219816a0a904ca9323e446db189
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) ms1_asm_hash (insn)
51 extern unsigned int ms1_asm_hash (const char *);
53 extern int ms1_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 ms1_cgen_insn_supported (CGEN_CPU_DESC cd,
63                          const CGEN_INSN *insn)
65   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
67   /* No mach attribute?  Assume it's supported for all machs.  */
68   if (machs == 0)
69     return 1;
70   
71   return ((machs & cd->machs) != 0);
74 /* A better hash function for instruction mnemonics.  */
76 unsigned int
77 ms1_asm_hash (const char* insn)
79   unsigned int hash;
80   const char* m = insn;
82   for (hash = 0; *m && ! ISSPACE (*m); m++)
83     hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
85   /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
87   return hash % CGEN_ASM_HASH_SIZE;
91 /* -- asm.c */
92 /* Range checking for signed numbers.  Returns 0 if acceptable
93    and 1 if the value is out of bounds for a signed quantity.  */
95 static int 
96 signed_out_of_bounds (long val)
98   if ((val < -32768) || (val > 32767))
99     return 1;
100   return 0;
103 static const char *
104 parse_imm16 (CGEN_CPU_DESC cd,
105              const char **strp,
106              int opindex,
107              void *arg)
109   signed long * valuep = (signed long *) arg;
110   const char *errmsg;
111   enum cgen_parse_operand_result result_type;
112   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
113   bfd_vma value;
115   /* Is it a control transfer instructions?  */ 
116   if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
117     {
118       code = BFD_RELOC_16_PCREL;
119       errmsg = cgen_parse_address (cd, strp, opindex, code,
120                                    & result_type, & value);
121       if (errmsg == NULL)
122         {
123           if (signed_out_of_bounds (value))
124             errmsg = _("Operand out of range. Must be between -32768 and 32767.");
125         }
126       *valuep = value;
127       return errmsg;
128     }
130   /* If it's not a control transfer instruction, then
131      we have to check for %OP relocating operators.  */
132   if (strncmp (*strp, "%hi16", 5) == 0)
133     {
134       *strp += 5;
135       code = BFD_RELOC_HI16;
136     }
137   else if (strncmp (*strp, "%lo16", 5) == 0)
138     {
139       *strp += 5;
140       code = BFD_RELOC_LO16;
141     }
143   /* If we found a %OP relocating operator, then parse it as an address.
144      If not, we need to parse it as an integer, either signed or unsigned
145      depending on which operand type we have.  */
146   if (code != BFD_RELOC_NONE)
147     {
148        /* %OP relocating operator found.  */
149        errmsg = cgen_parse_address (cd, strp, opindex, code,
150                                    & result_type, & value);
151        if (errmsg == NULL)
152          {
153            switch (result_type)
154              {
155              case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
156                if (code == BFD_RELOC_HI16)
157                  value = (value >> 16) & 0xFFFF;
158                else if (code == BFD_RELOC_LO16)
159                  value = value  & 0xFFFF;
160                else 
161                  errmsg = _("Biiiig Trouble in parse_imm16!");
162                break;
164              case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
165                /* No special processing for this case.  */
166                break;
168              default:
169                errmsg = _("%operator operand is not a symbol");
170                break;
171              }
172          }
173        *valuep = value;
174     }
175   else
176     {
177       /* Parse hex values like 0xffff as unsigned, and sign extend
178          them manually.  */
179       int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
181       if ((*strp)[0] == '0'
182           && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
183         parse_signed = 0;
185       /* No relocating operator.  Parse as an number.  */
186       if (parse_signed)
187         {
188           /* Parse as as signed integer.  */
190           errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
192           if (errmsg == NULL) 
193             {
194 #if 0
195               /* Manual range checking is needed for the signed case.  */
196               if (*valuep & 0x8000)
197                 value = 0xffff0000 | *valuep;
198               else 
199                 value = *valuep;
201               if (signed_out_of_bounds (value))
202                 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
203               /* Truncate to 16 bits. This is necessary
204                  because cgen will have sign extended *valuep.  */
205               *valuep &= 0xFFFF; 
206 #endif
207             }
208         }
209       else  
210         {
211           /* MS1_OPERAND_IMM16Z.  Parse as an unsigned integer.  */
212           errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
214           if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16
215               && *valuep >= 0x8000
216               && *valuep <= 0xffff)
217             *valuep -= 0x10000;
218         }
219     }
221   return errmsg;
225 static const char *
226 parse_dup (CGEN_CPU_DESC cd,
227            const char **strp,
228            int opindex,
229            unsigned long *valuep)
231   const char *errmsg = NULL;
233   if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
234     {
235       *strp += 3;
236       *valuep = 1;
237     }
238   else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
239     {
240       *strp += 2;
241       *valuep = 0;
242     }
243   else
244     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
246   return errmsg;
250 static const char *
251 parse_ball (CGEN_CPU_DESC cd,
252             const char **strp,
253             int opindex,
254             unsigned long *valuep)
256   const char *errmsg = NULL;
258   if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
259     {
260       *strp += 3;
261       *valuep = 1;
262     }
263   else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
264     {
265       *strp += 3;
266       *valuep = 0;
267     }
268   else
269     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
271   return errmsg;
274 static const char *
275 parse_xmode (CGEN_CPU_DESC cd,
276              const char **strp,
277              int opindex,
278              unsigned long *valuep)
280   const char *errmsg = NULL;
282   if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
283     {
284       *strp += 2;
285       *valuep = 1;
286     }
287   else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
288     {
289       *strp += 2;
290       *valuep = 0;
291     }
292   else
293     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
295   return errmsg;
298 static const char *
299 parse_rc (CGEN_CPU_DESC cd,
300           const char **strp,
301           int opindex,
302           unsigned long *valuep)
304   const char *errmsg = NULL;
306   if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
307     {
308       *strp += 1;
309       *valuep = 1;
310     }
311   else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
312     {
313       *strp += 1;
314       *valuep = 0;
315     }
316   else
317     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
319   return errmsg;
322 static const char *
323 parse_cbrb (CGEN_CPU_DESC cd,
324             const char **strp,
325             int opindex,
326             unsigned long *valuep)
328   const char *errmsg = NULL;
330   if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
331     {
332       *strp += 2;
333       *valuep = 1;
334     }
335   else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
336     {
337       *strp += 2;
338       *valuep = 0;
339     }
340   else
341     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
343   return errmsg;
346 static const char *
347 parse_rbbc (CGEN_CPU_DESC cd,
348             const char **strp,
349             int opindex,
350             unsigned long *valuep)
352   const char *errmsg = NULL;
354   if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
355     {
356       *strp += 2;
357       *valuep = 0;
358     }
359   else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
360     {
361       *strp += 3;
362       *valuep = 1;
363     }
364   else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
365     {
366       *strp += 3;
367       *valuep = 2;
368     }
369   else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
370     {
371       *strp += 2;
372       *valuep = 3;
373     }
374   else
375     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
377   return errmsg;
380 static const char *
381 parse_type (CGEN_CPU_DESC cd,
382             const char **strp,
383             int opindex,
384             unsigned long *valuep)
386   const char *errmsg = NULL;
388   if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
389     {
390       *strp += 3;
391       *valuep = 0;
392     }
393   else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
394     {
395       *strp += 4;
396       *valuep = 1;
397     }
398   else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
399     {
400       *strp += 2;
401       *valuep = 2;
402     }
403   else
404     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
406  if ((errmsg == NULL) && (*valuep == 3))
407     errmsg = _("invalid operand.  type may have values 0,1,2 only.");
409   return errmsg;
412 /* -- dis.c */
413 static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
415 static void
416 print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
417                  void * dis_info,
418                  long value,
419                  unsigned int attrs ATTRIBUTE_UNUSED,
420                  bfd_vma pc ATTRIBUTE_UNUSED,
421                  int length ATTRIBUTE_UNUSED)
423   disassemble_info *info = (disassemble_info *) dis_info;
425   info->fprintf_func (info->stream, "$%lx", value);
427   if (0)
428     print_normal (cd, dis_info, value, attrs, pc, length);
432 /* -- */