* z8kgen.c (struct op): Replace unused flavor with id.
[platform/upstream/binutils.git] / opcodes / h8500-dis.c
1 /* Disassemble h8500 instructions.
2    Copyright 1993, 1998, 2000, 2001, 2002, 2004, 2005, 2007
3    Free Software Foundation, Inc.
4
5    This file is part of the GNU opcodes library.
6
7    This library is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11
12    It is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22 #include <stdio.h>
23
24 #define DISASSEMBLER_TABLE
25 #define DEFINE_TABLE
26
27 #include "sysdep.h"
28 #include "h8500-opc.h"
29 #include "dis-asm.h"
30 #include "opintl.h"
31
32 /* Maximum length of an instruction.  */
33 #define MAXLEN 8
34
35 #include <setjmp.h>
36
37 struct private
38 {
39   /* Points to first byte not fetched.  */
40   bfd_byte *max_fetched;
41   bfd_byte the_buffer[MAXLEN];
42   bfd_vma insn_start;
43   jmp_buf bailout;
44 };
45
46 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
47    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
48    on error.  */
49 #define FETCH_DATA(info, addr) \
50   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
51    ? 1 : fetch_data ((info), (addr)))
52
53 static int
54 fetch_data (struct disassemble_info *info, bfd_byte *addr)
55 {
56   int status;
57   struct private *priv = (struct private *) info->private_data;
58   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
59
60   status = (*info->read_memory_func) (start,
61                                       priv->max_fetched,
62                                       addr - priv->max_fetched,
63                                       info);
64   if (status != 0)
65     {
66       (*info->memory_error_func) (status, start, info);
67       longjmp (priv->bailout, 1);
68     }
69   else
70     priv->max_fetched = addr;
71   return 1;
72 }
73
74 static char *crname[] = { "sr", "ccr", "*", "br", "ep", "dp", "*", "tp" };
75
76 int
77 print_insn_h8500 (bfd_vma addr, disassemble_info *info)
78 {
79   const h8500_opcode_info *opcode;
80   void *stream = info->stream;
81   fprintf_ftype func = info->fprintf_func;
82   struct private priv;
83   bfd_byte *buffer = priv.the_buffer;
84
85   info->private_data = (PTR) & priv;
86   priv.max_fetched = priv.the_buffer;
87   priv.insn_start = addr;
88   if (setjmp (priv.bailout) != 0)
89     /* Error return.  */
90     return -1;
91
92   /* Run down the table to find the one which matches.  */
93   for (opcode = h8500_table; opcode->name; opcode++)
94     {
95       int byte;
96       int rn = 0;
97       int rd = 0;
98       int rs = 0;
99       int disp = 0;
100       int abs = 0;
101       int imm = 0;
102       int pcrel = 0;
103       int qim = 0;
104       int i;
105       int cr = 0;
106
107       for (byte = 0; byte < opcode->length; byte++)
108         {
109           FETCH_DATA (info, buffer + byte + 1);
110           if ((buffer[byte] & opcode->bytes[byte].mask)
111               != (opcode->bytes[byte].contents))
112             goto next;
113
114           else
115             {
116               /* Extract any info parts.  */
117               switch (opcode->bytes[byte].insert)
118                 {
119                 case 0:
120                 case FP:
121                   break;
122                 default:
123                   /* xgettext:c-format */
124                   func (stream, _("can't cope with insert %d\n"),
125                         opcode->bytes[byte].insert);
126                   break;
127                 case RN:
128                   rn = buffer[byte] & 0x7;
129                   break;
130                 case RS:
131                   rs = buffer[byte] & 0x7;
132                   break;
133                 case CRB:
134                   cr = buffer[byte] & 0x7;
135                   if (cr == 0)
136                     goto next;
137                   break;
138                 case CRW:
139                   cr = buffer[byte] & 0x7;
140                   if (cr != 0)
141                     goto next;
142                   break;
143                 case DISP16:
144                   FETCH_DATA (info, buffer + byte + 2);
145                   disp = (buffer[byte] << 8) | (buffer[byte + 1]);
146                   break;
147                 case FPIND_D8:
148                 case DISP8:
149                   disp = ((char) (buffer[byte]));
150                   break;
151                 case RD:
152                 case RDIND:
153                   rd = buffer[byte] & 0x7;
154                   break;
155                 case ABS24:
156                   FETCH_DATA (info, buffer + byte + 3);
157                   abs =
158                     (buffer[byte] << 16)
159                     | (buffer[byte + 1] << 8)
160                     | (buffer[byte + 2]);
161                   break;
162                 case ABS16:
163                   FETCH_DATA (info, buffer + byte + 2);
164                   abs = (buffer[byte] << 8) | (buffer[byte + 1]);
165                   break;
166                 case ABS8:
167                   abs = (buffer[byte]);
168                   break;
169                 case IMM16:
170                   FETCH_DATA (info, buffer + byte + 2);
171                   imm = (buffer[byte] << 8) | (buffer[byte + 1]);
172                   break;
173                 case IMM4:
174                   imm = (buffer[byte]) & 0xf;
175                   break;
176                 case IMM8:
177                 case RLIST:
178                   imm = (buffer[byte]);
179                   break;
180                 case PCREL16:
181                   FETCH_DATA (info, buffer + byte + 2);
182                   pcrel = (buffer[byte] << 8) | (buffer[byte + 1]);
183                   break;
184                 case PCREL8:
185                   pcrel = (buffer[byte]);
186                   break;
187                 case QIM:
188                   switch (buffer[byte] & 0x7)
189                     {
190                     case 0:
191                       qim = 1;
192                       break;
193                     case 1:
194                       qim = 2;
195                       break;
196                     case 4:
197                       qim = -1;
198                       break;
199                     case 5:
200                       qim = -2;
201                       break;
202                     }
203                   break;
204
205                 }
206             }
207         }
208       /* We get here when all the masks have passed so we can output
209          the operands.  */
210       FETCH_DATA (info, buffer + opcode->length);
211       (func) (stream, "%s\t", opcode->name);
212       for (i = 0; i < opcode->nargs; i++)
213         {
214           if (i)
215             (func) (stream, ",");
216           switch (opcode->arg_type[i])
217             {
218             case FP:
219               func (stream, "fp");
220               break;
221             case RNIND_D16:
222               func (stream, "@(0x%x:16,r%d)", disp, rn);
223               break;
224             case RNIND_D8:
225               func (stream, "@(0x%x:8 (%d),r%d)", disp & 0xff, disp, rn);
226               break;
227             case RDIND_D16:
228               func (stream, "@(0x%x:16,r%d)", disp, rd);
229               break;
230             case RDIND_D8:
231               func (stream, "@(0x%x:8 (%d), r%d)", disp & 0xff, disp, rd);
232               break;
233             case FPIND_D8:
234               func (stream, "@(0x%x:8 (%d), fp)", disp & 0xff, disp);
235               break;
236             case CRB:
237             case CRW:
238               func (stream, "%s", crname[cr]);
239               break;
240             case RN:
241               func (stream, "r%d", rn);
242               break;
243             case RD:
244               func (stream, "r%d", rd);
245               break;
246             case RS:
247               func (stream, "r%d", rs);
248               break;
249             case RNDEC:
250               func (stream, "@-r%d", rn);
251               break;
252             case RNINC:
253               func (stream, "@r%d+", rn);
254               break;
255             case RNIND:
256               func (stream, "@r%d", rn);
257               break;
258             case RDIND:
259               func (stream, "@r%d", rd);
260               break;
261             case SPINC:
262               func (stream, "@sp+");
263               break;
264             case SPDEC:
265               func (stream, "@-sp");
266               break;
267             case ABS24:
268               func (stream, "@0x%0x:24", abs);
269               break;
270             case ABS16:
271               func (stream, "@0x%0x:16", abs & 0xffff);
272               break;
273             case ABS8:
274               func (stream, "@0x%0x:8", abs & 0xff);
275               break;
276             case IMM16:
277               func (stream, "#0x%0x:16", imm & 0xffff);
278               break;
279             case RLIST:
280               {
281                 int i;
282                 int nc = 0;
283
284                 func (stream, "(");
285                 for (i = 0; i < 8; i++)
286                   {
287                     if (imm & (1 << i))
288                       {
289                         func (stream, "r%d", i);
290                         if (nc)
291                           func (stream, ",");
292                         nc = 1;
293                       }
294                   }
295                 func (stream, ")");
296               }
297               break;
298             case IMM8:
299               func (stream, "#0x%0x:8", imm & 0xff);
300               break;
301             case PCREL16:
302               func (stream, "0x%0x:16",
303                     (int)(pcrel + addr + opcode->length) & 0xffff);
304               break;
305             case PCREL8:
306               func (stream, "#0x%0x:8",
307                     (int)((char) pcrel + addr + opcode->length) & 0xffff);
308               break;
309             case QIM:
310               func (stream, "#%d:q", qim);
311               break;
312             case IMM4:
313               func (stream, "#%d:4", imm);
314               break;
315             }
316         }
317       return opcode->length;
318     next:
319       ;
320     }
321
322   /* Couldn't understand anything.  */
323   /* xgettext:c-format */
324   func (stream, _("%02x\t\t*unknown*"), buffer[0]);
325   return 1;
326 }