* frv.opc (parse_uhi16): Fix handling of %hi operator on 64-bit
[binutils.git] / cpu / fr30.opc
blobb09148e1c1515d914b83b6ad24b074906eb40387
1 /* FR30 opcode support.  -*- C -*-
2    Copyright 2011 Free Software Foundation, Inc.
4    Contributed by Red Hat Inc;
6    This file is part of the GNU Binutils.
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
23 /* This file is an addendum to fr30.cpu.  Heavy use of C code isn't
24    appropriate in .cpu files, so it resides here.  This especially applies
25    to assembly/disassembly where parsing/printing can be quite involved.
26    Such things aren't really part of the specification of the cpu, per se,
27    so .cpu files provide the general framework and .opc files handle the
28    nitty-gritty details as necessary.
30    Each section is delimited with start and end markers.
32    <arch>-opc.h additions use: "-- opc.h"
33    <arch>-opc.c additions use: "-- opc.c"
34    <arch>-asm.c additions use: "-- asm.c"
35    <arch>-dis.c additions use: "-- dis.c"
36    <arch>-ibd.h additions use: "-- ibd.h".  */
38 /* -- opc.h */
40 /* ??? This can be improved upon.  */
41 #undef  CGEN_DIS_HASH_SIZE
42 #define CGEN_DIS_HASH_SIZE 16
43 #undef  CGEN_DIS_HASH
44 #define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 4)
46 /* -- */
48 /* -- asm.c */
49 /* Handle register lists for LDMx and STMx.  */
51 static int
52 parse_register_number (const char **strp)
54   int regno;
56   if (**strp < '0' || **strp > '9')
57     return -1; /* Error.  */
58   regno = **strp - '0';
59   ++*strp;
61   if (**strp >= '0' && **strp <= '9')
62     {
63       regno = regno * 10 + (**strp - '0');
64       ++*strp;
65     }
67   return regno;
70 static const char *
71 parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
72                      const char **strp,
73                      int opindex ATTRIBUTE_UNUSED,
74                      unsigned long *valuep,
75                      int high_low,   /* 0 == high, 1 == low.  */
76                      int load_store) /* 0 == load, 1 == store.  */
78   *valuep = 0;
79   while (**strp && **strp != ')')
80     {
81       int regno;
83       if (**strp != 'R' && **strp != 'r')
84         break;
85       ++*strp;
87       regno = parse_register_number (strp);
88       if (regno == -1)
89         return _("Register number is not valid");
90       if (regno > 7 && !high_low)
91         return _("Register must be between r0 and r7");
92       if (regno < 8 && high_low)
93         return _("Register must be between r8 and r15");
95       if (high_low)
96         regno -= 8;
98       if (load_store) /* Mask is reversed for store.  */
99         *valuep |= 0x80 >> regno;
100       else
101         *valuep |= 1 << regno;
103       if (**strp == ',')
104         {
105           if (*(*strp + 1) == ')')
106             break;
107           ++*strp;
108         }
109     }
111   if (!*strp || **strp != ')')
112     return _("Register list is not valid");
114   return NULL;
117 static const char *
118 parse_low_register_list_ld (CGEN_CPU_DESC cd,
119                             const char **strp,
120                             int opindex,
121                             unsigned long *valuep)
123   return parse_register_list (cd, strp, opindex, valuep,
124                               0 /* Low.  */, 0 /* Load.  */);
127 static const char *
128 parse_hi_register_list_ld (CGEN_CPU_DESC cd,
129                            const char **strp,
130                            int opindex,
131                            unsigned long *valuep)
133   return parse_register_list (cd, strp, opindex, valuep,
134                               1 /* High.  */, 0 /* Load.  */);
137 static const char *
138 parse_low_register_list_st (CGEN_CPU_DESC cd,
139                             const char **strp,
140                             int opindex,
141                             unsigned long *valuep)
143   return parse_register_list (cd, strp, opindex, valuep,
144                               0 /* Low.  */, 1 /* Store.  */);
147 static const char *
148 parse_hi_register_list_st (CGEN_CPU_DESC cd,
149                            const char **strp,
150                            int opindex,
151                            unsigned long *valuep)
153   return parse_register_list (cd, strp, opindex, valuep,
154                               1 /* High.  */, 1 /* Store.  */);
157 /* -- */
159 /* -- dis.c */
160 static void
161 print_register_list (void * dis_info,
162                      long value,
163                      long offset,
164                      int load_store) /* 0 == load, 1 == store.  */
166   disassemble_info *info = dis_info;
167   int mask;
168   int reg_index = 0;
169   char * comma = "";
171   if (load_store)
172     mask = 0x80;
173   else
174     mask = 1;
176   if (value & mask)
177     {
178       (*info->fprintf_func) (info->stream, "r%li", reg_index + offset);
179       comma = ",";
180     }
181     
182   for (reg_index = 1; reg_index <= 7; ++reg_index)
183     {
184       if (load_store)
185         mask >>= 1;
186       else
187         mask <<= 1;
189       if (value & mask)
190         {
191           (*info->fprintf_func) (info->stream, "%sr%li", comma, reg_index + offset);
192           comma = ",";
193         }
194     }
197 static void
198 print_hi_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
199                            void * dis_info,
200                            long value,
201                            unsigned int attrs ATTRIBUTE_UNUSED,
202                            bfd_vma pc ATTRIBUTE_UNUSED,
203                            int length ATTRIBUTE_UNUSED)
205   print_register_list (dis_info, value, 8, 0 /* Load.  */);
208 static void
209 print_low_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
210                             void * dis_info,
211                             long value,
212                             unsigned int attrs ATTRIBUTE_UNUSED,
213                             bfd_vma pc ATTRIBUTE_UNUSED,
214                             int length ATTRIBUTE_UNUSED)
216   print_register_list (dis_info, value, 0, 0 /* Load.  */);
219 static void
220 print_hi_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
221                            void * dis_info,
222                            long value,
223                            unsigned int attrs ATTRIBUTE_UNUSED,
224                            bfd_vma pc ATTRIBUTE_UNUSED,
225                            int length ATTRIBUTE_UNUSED)
227   print_register_list (dis_info, value, 8, 1 /* Store.  */);
230 static void
231 print_low_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
232                             void * dis_info,
233                             long value,
234                             unsigned int attrs ATTRIBUTE_UNUSED,
235                             bfd_vma pc ATTRIBUTE_UNUSED,
236                             int length ATTRIBUTE_UNUSED)
238   print_register_list (dis_info, value, 0, 1 /* Store.  */);
241 static void
242 print_m4 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
243           void * dis_info,
244           long value,
245           unsigned int attrs ATTRIBUTE_UNUSED,
246           bfd_vma pc ATTRIBUTE_UNUSED,
247           int length ATTRIBUTE_UNUSED)
249   disassemble_info *info = (disassemble_info *) dis_info;
251   (*info->fprintf_func) (info->stream, "%ld", value);
253 /* -- */