OSDN Git Service

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