Apply patch supplied for case 102229 to implement new insns psrclr and psrset.
[external/binutils.git] / opcodes / mcore-dis.c
1 /* Disassemble Motorolla M*Core instructions.
2    Copyright (C) 1993, 1999 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 #include <stdio.h>
19 #define STATIC_TABLE
20 #define DEFINE_TABLE
21
22 #include "mcore-opc.h"
23 #include "dis-asm.h"
24
25 /* Mask for each mcore_opclass: */
26 static const unsigned short imsk[] =
27 {
28     /* O0  */ 0xFFFF,
29     /* OT  */ 0xFFFC,
30     /* O1  */ 0xFFF0,
31     /* OC  */ 0xFFE0,
32     /* O2  */ 0xFF00,
33     /* X1  */ 0xFFF0,
34     /* OI  */ 0xFE00,
35     /* OB  */ 0xFE00,
36               
37     /* OMa */ 0xFFF0,
38     /* SI  */ 0xFE00,
39     /* I7  */ 0xF800,
40     /* LS  */ 0xF000,
41     /* BR  */ 0xF800,
42     /* BL  */ 0xFF00,
43     /* LR  */ 0xF000,
44     /* LJ  */ 0xFF00,
45               
46     /* RM  */ 0xFFF0,
47     /* RQ  */ 0xFFF0,
48     /* JSR */ 0xFFF0,
49     /* JMP */ 0xFFF0,
50     /* OBRa*/ 0xFFF0,
51     /* OBRb*/ 0xFF80,
52     /* OBRc*/ 0xFF00,
53     /* OBR2*/ 0xFE00,
54               
55     /* O1R1*/ 0xFFF0,
56     /* OMb */ 0xFF80,
57     /* OMc */ 0xFF00,
58     /* SIa */ 0xFE00,
59
60 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
61
62 #include <stdio.h>
63 #define STATIC_TABLE
64 #define DEFINE_TABLE
65
66 #include "mcore-opc.h"
67 #include "dis-asm.h"
68
69 /* Mask for each mcore_opclass: */
70 static const unsigned short imsk[] =
71 {
72     /* O0  */ 0xFFFF,
73     /* OT  */ 0xFFFC,
74     /* O1  */ 0xFFF0,
75     /* OC  */ 0xFFE0,
76     /* O2  */ 0xFF00,
77     /* X1  */ 0xFFF0,
78     /* OI  */ 0xFE00,
79     /* OB  */ 0xFE00,
80               
81     /* OMa */ 0xFFF0,
82     /* SI  */ 0xFE00,
83     /* I7  */ 0xF800,
84     /* LS  */ 0xF000,
85     /* BR  */ 0xF800,
86     /* BL  */ 0xFF00,
87     /* LR  */ 0xF000,
88     /* LJ  */ 0xFF00,
89               
90     /* RM  */ 0xFFF0,
91     /* RQ  */ 0xFFF0,
92     /* JSR */ 0xFFF0,
93     /* JMP */ 0xFFF0,
94     /* OBRa*/ 0xFFF0,
95     /* OBRb*/ 0xFF80,
96     /* OBRc*/ 0xFF00,
97     /* OBR2*/ 0xFE00,
98               
99     /* O1R1*/ 0xFFF0,
100     /* OMb */ 0xFF80,
101     /* OMc */ 0xFF00,
102     /* SIa */ 0xFE00,
103
104   /* OPSR  */ 0xFFF8,   /* psrset/psrclr */
105                  
106     /* JC  */ 0,                /* JC,JU,JL don't appear in object */
107     /* JU  */ 0,
108     /* JL  */ 0,
109     /* RSI */ 0,
110     /* DO21*/ 0,
111     /* OB2 */ 0                 /* OB2 won't appear in object. */
112 };
113
114 static const char * grname[] =
115 {
116  "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
117  "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15"
118 };
119
120 static const char X[] = "??";
121
122 static const char * crname[] =
123 {
124   "psr",  "vbr", "epsr", "fpsr", "epc",  "fpc",  "ss0",  "ss1",
125   "ss2",  "ss3", "ss4",  "gcr",  "gsr",     X,      X,      X,
126      X,      X,      X,      X,      X,     X,      X,      X,
127      X,      X,      X,      X,      X,     X,      X,      X
128 };
129
130 static const unsigned isiz[] = { 2, 0, 1, 0 };
131
132 int 
133 print_insn_mcore (memaddr, info)
134      bfd_vma memaddr;
135      struct disassemble_info * info;
136 {
137   unsigned char       ibytes[4];
138   fprintf_ftype       fprintf = info->fprintf_func;
139   void *              stream = info->stream;
140   unsigned short      inst;
141   mcore_opcode_info * op;
142   int                 status;
143
144   info->bytes_per_chunk = 2;
145
146   status = info->read_memory_func (memaddr, ibytes, 2, info);
147
148   if (status != 0) 
149     {
150       info->memory_error_func (status, memaddr, info);
151       return -1;
152     }
153
154     inst = (ibytes[0] << 8) | ibytes[1];
155
156   /* Just a linear search of the table.  */
157   for (op = mcore_table; op->name != 0; op ++)
158     if (op->inst == (inst & imsk[op->opclass]))
159       break;
160
161   if (op->name == 0)
162     fprintf (stream, ".short 0x%04x", inst);
163   else
164     {
165       const char * name = grname[inst & 0x0F];
166       
167       fprintf (stream, "%s", op->name);
168       
169       switch (op->opclass)
170         {
171         case O0: break;
172         case OT: fprintf (stream, "\t%d", inst & 0x3); break;
173         case O1:
174         case JMP:
175         case JSR: fprintf (stream, "\t%s", name); break;
176         case OC:  fprintf (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]); break;
177         case O1R1: fprintf (stream, "\t%s, r1", name); break;
178         case O2: fprintf (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]); break;
179         case X1: fprintf (stream, "\tr1, %s", name); break;
180         case OI: fprintf (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1); break;
181         case RM: fprintf (stream, "\t%s-r15, (r0)", name); break;
182         case RQ: fprintf (stream, "\tr4-r7, (%s)", name); break;
183         case OB:
184         case OBRa:
185         case OBRb:
186         case OBRc:
187         case SI:
188         case SIa:
189         case OMa:
190         case OMb:
191         case OMc: fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x1F); break;
192         case I7: fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x7F); break;
193         case LS: fprintf (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
194                           name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
195           break;
196           
197         case BR:
198           {
199             long val = inst & 0x3FF;
200             
201             if (inst & 0x400)
202               val |= 0xFFFFFC00;
203             
204             fprintf (stream, "\t0x%x", memaddr + 2 + (val<<1));
205             
206             if (strcmp (op->name, "bsr") == 0)
207               {
208                 /* for bsr, we'll try to get a symbol for the target */
209                 val = memaddr + 2 + (val << 1);
210                 
211                 if (info->print_address_func && val != 0)
212                   {
213                     fprintf (stream, "\t// ");
214                     info->print_address_func (val, info);
215                   }
216               }
217           }
218           break;
219           
220         case BL:
221           {
222             long val;
223             val = (inst & 0x000F);
224             fprintf (stream, "\t%s, 0x%x",
225                     grname[(inst >> 4) & 0xF], memaddr - (val << 1));
226           }
227           break;
228           
229         case LR:
230           {
231             unsigned long val;
232             
233             val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
234             
235             status = info->read_memory_func (val, ibytes, 4, info);
236             if (status != 0) 
237               {
238                 info->memory_error_func (status, memaddr, info);
239                 break;
240               }
241             
242               val = (ibytes[0] << 24) | (ibytes[1] << 16)
243                 | (ibytes[2] << 8) | (ibytes[3]);
244             
245             /* Removed [] around literal value to match ABI syntax 12/95.  */
246             fprintf (stream, "\t%s, 0x%X", grname[(inst >> 8) & 0xF], val);
247
248             if (val == 0)
249               fprintf (stream, "\t// from address pool at 0x%x",
250                        (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
251           }
252           break;
253           
254         case LJ:
255           {
256             unsigned long val;
257             
258             val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
259             
260             status = info->read_memory_func (val, ibytes, 4, info);
261             if (status != 0) 
262               {
263                 info->memory_error_func (status, memaddr, info);
264                 break;
265               }
266
267               val = (ibytes[0] << 24) | (ibytes[1] << 16)
268                 | (ibytes[2] << 8) | (ibytes[3]);
269             
270             /* Removed [] around literal value to match ABI syntax 12/95.  */
271             fprintf (stream, "\t0x%X", val);
272             /* For jmpi/jsri, we'll try to get a symbol for the target.  */
273             if (info->print_address_func && val != 0)
274               {
275                 fprintf (stream, "\t// ");
276                 info->print_address_func (val, info);
277               }
278             else
279               {
280                 fprintf (stream, "\t// from address pool at 0x%x",
281                          (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
282               }
283           }
284           break;
285           
286         case OPSR:
287           {
288             static char * fields[] = 
289             {
290               "af", "ie",    "fe",    "fe,ie", 
291               "ee", "ee,ie", "ee,fe", "ee,fe,ie"
292             };
293             
294             fprintf (stream, "\t%s", fields[inst & 0x7]);
295           }
296           break;
297
298         default:
299           /* if the disassembler lags the instruction set */
300           fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
301           break;
302         }
303     }
304   
305   /* Say how many bytes we consumed? */
306   return 2;
307 }