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