This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / opcodes / h8300-dis.c
1 /* Disassemble h8300 instructions.
2    Copyright (C) 1993, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #define DEFINE_TABLE
19
20 #define h8_opcodes h8ops
21 #include "opcode/h8300.h"
22 #include "dis-asm.h"
23 #include "opintl.h"
24
25
26 /* Run through the opcodes and sort them into order to make them easy
27    to disassemble
28  */
29 static void
30 bfd_h8_disassemble_init ()
31 {
32   unsigned int i;
33
34
35   struct h8_opcode *p;
36
37   for (p = h8_opcodes; p->name; p++)
38     {
39       int n1 = 0;
40       int n2 = 0;
41
42       if ((int) p->data.nib[0] < 16)
43         {
44           n1 = (int) p->data.nib[0];
45         }
46       else
47         n1 = 0;
48       if ((int) p->data.nib[1] < 16)
49         {
50           n2 = (int) p->data.nib[1];
51         }
52       else
53         n2 = 0;
54
55       /* Just make sure there are an even number of nibbles in it, and
56          that the count is the same s the length */
57       for (i = 0; p->data.nib[i] != E; i++)
58         /*EMPTY*/ ;
59       if (i & 1)
60         abort ();
61       p->length = i / 2;
62     }
63
64 }
65
66
67 unsigned int
68 bfd_h8_disassemble (addr, info, mode)
69      bfd_vma addr;
70      disassemble_info *info;
71      int mode;
72 {
73   /* Find the first entry in the table for this opcode */
74   static CONST char *regnames[] =
75     {
76       "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
77       "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l"};
78   
79   static CONST char *wregnames[] =
80     {
81       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
82       "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"
83       };
84   
85   static CONST char *lregnames[] =
86     {
87       "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
88       "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"
89       }
90   ;
91
92   int rs = 0;
93   int rd = 0;
94   int rdisp = 0;
95   int abs = 0;
96   int bit = 0;
97   int plen = 0;
98   static boolean init = 0;
99   struct h8_opcode *q = h8_opcodes;
100   char CONST **pregnames = mode != 0 ? lregnames : wregnames;
101   int status;
102   int l;
103   
104   unsigned char data[20];  
105   void *stream = info->stream;
106   fprintf_ftype fprintf = info->fprintf_func;
107
108   if (!init)
109     {
110       bfd_h8_disassemble_init ();
111       init = 1;
112     }
113
114   status = info->read_memory_func(addr, data, 2, info);
115   if (status != 0) 
116     {
117       info->memory_error_func(status, addr, info);
118       return -1;
119     }
120   for (l = 2; status == 0 && l < 10; l+=2)
121     {
122       status = info->read_memory_func(addr+l, data+l, 2, info);
123     }
124   
125   
126
127   /* Find the exact opcode/arg combo */
128   while (q->name)
129     {
130       op_type *nib;
131       unsigned int len = 0;
132
133       nib = q->data.nib;
134       
135       while (1)
136         {
137           op_type looking_for = *nib;
138           int thisnib = data[len >> 1];
139           
140           thisnib = (len & 1) ? (thisnib & 0xf) : ((thisnib >> 4) & 0xf);
141           
142           if (looking_for < 16 && looking_for >=0) 
143             {
144               
145               if (looking_for != thisnib) 
146                 goto fail;
147             }
148           
149           else 
150             {
151               
152               if ((int) looking_for & (int) B31)
153                 {
154                   if (! (((int) thisnib & 0x8) != 0)) 
155                     goto fail;
156                   looking_for = (op_type) ((int) looking_for & ~(int) B31);
157                 }
158               if ((int) looking_for & (int) B30)
159                 {
160                   if (!(((int) thisnib & 0x8) == 0)) 
161                     goto fail;
162                   looking_for = (op_type) ((int) looking_for & ~(int) B30);
163                 }
164
165               if (looking_for & DBIT)
166                 {
167                   if ((looking_for & 5) != (thisnib &5)) goto fail;
168                   abs = (thisnib & 0x8) ? 2 : 1;
169                 }                 
170               
171               else  if (looking_for & (REG | IND|INC|DEC))
172                 {
173                   if (looking_for & SRC)
174                     {
175                       rs = thisnib;
176                     }
177                   else
178                     {
179                       rd = thisnib;
180                     }
181                 }
182               else if (looking_for & L_16)
183                 {
184                   abs = (data[len >> 1]) * 256 + data[(len + 2) >> 1];
185                   plen = 16;
186               
187                 }
188               else if(looking_for & ABSJMP)
189                 {
190                   abs =
191                     (data[1] << 16)
192                       | (data[2] << 8)
193                         | (data[3]);
194                 }
195               else if(looking_for & MEMIND)
196                 {
197                   abs = data[1];
198                 }
199               else if (looking_for & L_32)
200                 {
201                   int i = len >> 1;
202                   abs = (data[i] << 24)
203                     | (data[i + 1] << 16)
204                       | (data[i + 2] << 8)
205                         | (data[i+ 3]);
206
207                   plen =32;
208               
209                 }
210               else if (looking_for & L_24)
211                 {
212                   int i = len >> 1;
213                   abs = (data[i] << 16) | (data[i + 1] << 8)|  (data[i+2]);
214                   plen =24;
215                 }
216               else if (looking_for & IGNORE)
217                 {
218                   
219                 }
220               else if (looking_for & DISPREG)
221                 {
222                   rdisp = thisnib;
223                 }
224               else if (looking_for & KBIT)
225                 {
226                   switch (thisnib) 
227                     {
228                     case 9:
229                       abs = 4;
230                       break;
231                     case 8:
232                       abs = 2;
233                       break;
234                     case 0:
235                       abs = 1;
236                       break;
237                     default:
238                       goto fail;
239                     }
240                 }
241               else if (looking_for & L_8)
242                 {
243                   plen = 8;               
244                   abs = data[len >> 1];
245                 }
246               else if (looking_for & L_3)
247                 {
248                   bit = thisnib & 0x7;
249                 }
250               else if (looking_for & L_2)
251                 {
252                   plen = 2;
253                   abs = thisnib & 0x3;
254                 }
255               else if (looking_for & MACREG)
256                 {
257                   abs = (thisnib == 3);
258                 }
259               else if (looking_for == E)
260                 {
261
262                   {
263                     int i;
264
265                     for (i = 0; i < q->length; i++)
266                       {
267                         fprintf (stream, "%02x ", data[i]);
268                       }
269                     for (; i < 6; i++)
270                       {
271                         fprintf (stream, "   ");
272                       }
273                   }
274                   fprintf (stream, "%s\t", q->name);
275
276                   /* Gross.  Disgusting.  */
277                   if (strcmp (q->name, "ldm.l") == 0)
278                     {
279                       int count, high;
280
281                       count = (data[1] >> 4) & 0x3;
282                       high = data[3] & 0x7;
283
284                       fprintf (stream, "@sp+,er%d-er%d", high - count, high);
285                       return q->length;
286                     }
287
288                   if (strcmp (q->name, "stm.l") == 0)
289                     {
290                       int count, low;
291
292                       count = (data[1] >> 4) & 0x3;
293                       low = data[3] & 0x7;
294
295                       fprintf (stream, "er%d-er%d,@-sp", low, low + count);
296                       return q->length;
297                     }
298
299                   /* Fill in the args */
300                   {
301                     op_type *args = q->args.nib;
302                     int hadone = 0;
303
304
305                     while (*args != E)
306                       {
307                         int x = *args;
308                         if (hadone)
309                           fprintf (stream, ",");
310
311
312                         if (x & L_3)
313                           {
314                             fprintf (stream, "#0x%x", (unsigned) bit);
315                           }
316                         else if (x & (IMM|KBIT|DBIT))
317                           {
318                             /* Bletch.  For shal #2,er0 and friends.  */
319                             if (*(args+1) & SRC_IN_DST)
320                               abs = 2;
321
322                             fprintf (stream, "#0x%x", (unsigned) abs);
323                           }
324                         else if (x & REG)
325                           {
326                             int rn = (x & DST) ? rd : rs;
327                             switch (x & SIZE)
328                               {
329                               case L_8:
330                                 fprintf (stream, "%s", regnames[rn]);
331                                 break;
332                               case L_16:
333                                 fprintf (stream, "%s", wregnames[rn]);
334                                 break;
335                               case L_P:
336                               case L_32:
337                                 fprintf (stream, "%s", lregnames[rn]);
338                                 break;
339                     
340                               }
341                           }
342                         else if (x & MACREG)
343                           {
344                             fprintf (stream, "mac%c", abs ? 'l' : 'h');
345                           }
346                         else if (x & INC)
347                           {
348                             fprintf (stream, "@%s+", pregnames[rs]);
349                           }
350                         else if (x & DEC)
351                           {
352                             fprintf (stream, "@-%s", pregnames[rd]);
353                           }
354
355                         else if (x & IND)
356                           {
357                             int rn = (x & DST) ? rd : rs;
358                             fprintf (stream, "@%s", pregnames[rn]);
359                           }
360
361                         else if (x & ABS8MEM)
362                           {
363                             fprintf (stream, "@0x%x:8", (unsigned) abs);
364                           }
365
366                         else if (x & (ABS|ABSJMP))
367                           {
368                             fprintf (stream, "@0x%x:%d", (unsigned) abs, plen);
369                           }
370
371                         else if (x & MEMIND)
372                           {
373                             fprintf (stream, "@@%d (%x)", abs, abs);
374                           }
375
376                         else if (x & PCREL)
377                           {
378                             if (x & L_16) 
379                               {
380                                 abs  +=2;
381                                 fprintf (stream, ".%s%d (%x)", (short) abs > 0 ? "+" : "", (short) abs,
382                                          addr + (short) abs + 2);
383                               }
384                             else {
385                               fprintf (stream, ".%s%d (%x)", (char) abs > 0 ? "+" : "", (char) abs,
386                                        addr + (char) abs + 2);
387                             }
388                           }
389                         else if (x & DISP)
390                           {
391                             fprintf (stream, "@(0x%x:%d,%s)", abs,plen, pregnames[rdisp]);
392                           }
393
394                         else if (x & CCR)
395                           {
396                             fprintf (stream, "ccr");
397                           }
398                         else if (x & EXR)
399                           {
400                             fprintf (stream, "exr");
401                           }
402                         else
403                           /* xgettext:c-format */
404                           fprintf (stream, _("Hmmmm %x"), x);
405                         hadone = 1;
406                         args++;
407                       }
408                   }
409                   return q->length;
410                 }
411
412       
413               else
414                 {
415                   /* xgettext:c-format */
416                   fprintf (stream, _("Don't understand %x \n"), looking_for);
417                 }
418             }
419           
420           len++;
421           nib++;
422         }
423       
424     fail:
425       q++;
426     }
427
428   /* Fell of the end */
429   fprintf (stream, "%02x %02x        .word\tH'%x,H'%x",
430            data[0], data[1],
431            data[0], data[1]);
432   return 2;
433 }
434
435 int 
436 print_insn_h8300 (addr, info)
437 bfd_vma addr; 
438 disassemble_info *info;
439 {
440   return bfd_h8_disassemble (addr, info , 0);
441 }
442
443 int 
444 print_insn_h8300h (addr, info)
445 bfd_vma addr;
446 disassemble_info *info;
447 {
448   return bfd_h8_disassemble (addr, info , 1);
449 }
450
451 int 
452 print_insn_h8300s (addr, info)
453 bfd_vma addr;
454 disassemble_info *info;
455 {
456   return bfd_h8_disassemble (addr, info , 2);
457 }