]> Git Repo - binutils.git/blob - opcodes/rx-dis.c
Update year range in copyright notice of binutils files
[binutils.git] / opcodes / rx-dis.c
1 /* Disassembler code for Renesas RX.
2    Copyright (C) 2008-2021 Free Software Foundation, Inc.
3    Contributed by Red Hat.
4    Written by DJ Delorie.
5
6    This file is part of the GNU opcodes library.
7
8    This library 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, or (at your option)
11    any later version.
12
13    It is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17
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.  */
22
23 #include "sysdep.h"
24 #include <stdio.h>
25
26 #include "bfd.h"
27 #include "dis-asm.h"
28 #include "opcode/rx.h"
29 #include "libiberty.h"
30 #include "opintl.h"
31
32 #include <setjmp.h>
33
34 typedef struct
35 {
36   bfd_vma pc;
37   disassemble_info * dis;
38 } RX_Data;
39
40 struct private
41 {
42   OPCODES_SIGJMP_BUF bailout;
43 };
44
45 static int
46 rx_get_byte (void * vdata)
47 {
48   bfd_byte buf[1];
49   RX_Data *rx_data = (RX_Data *) vdata;
50   int status;
51
52   status = rx_data->dis->read_memory_func (rx_data->pc,
53                                            buf,
54                                            1,
55                                            rx_data->dis);
56   if (status != 0)
57     {
58       struct private *priv = (struct private *) rx_data->dis->private_data;
59
60       rx_data->dis->memory_error_func (status, rx_data->pc,
61                                        rx_data->dis);
62        OPCODES_SIGLONGJMP (priv->bailout, 1);
63     }
64
65   rx_data->pc ++;
66   return buf[0];
67 }
68
69 static char const * size_names[RX_MAX_SIZE] =
70 {
71   "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "", "<error>"
72 };
73
74 static char const * opsize_names[RX_MAX_SIZE] =
75 {
76   "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", ".d", "<error>"
77 };
78
79 static char const * register_names[] =
80 {
81   /* General registers.  */
82   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
83   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
84   /* Control registers.  */
85   "psw", "pc", "usp", "fpsw", NULL, NULL, NULL, NULL,
86   "bpsw", "bpc", "isp", "fintv", "intb", "extb", NULL, NULL,
87   "a0", "a1", NULL, NULL, NULL, NULL, NULL, NULL,
88   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
89 };
90
91 static char const * condition_names[] =
92 {
93   /* Condition codes.  */
94   "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
95   "ge", "lt", "gt", "le", "o", "no", "<invalid>", "<invalid>"
96 };
97
98 static const char * flag_names[] =
99 {
100   "c", "z", "s", "o", "", "", "", "",
101   "", "", "", "", "", "", "", "",
102   "i", "u", "", "", "", "", "", "",
103   "", "", "", "", "", "", "", ""
104 };
105
106 static const char * double_register_names[] =
107 {
108   "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
109   "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
110 };
111
112 static const char * double_register_high_names[] =
113 {
114   "drh0", "drh1", "drh2", "drh3", "drh4", "drh5", "drh6", "drh7",
115   "drh8", "drh9", "drh10", "drh11", "drh12", "drh13", "drh14", "drh15"
116 };
117
118 static const char * double_register_low_names[] =
119 {
120   "drl0", "drl1", "drl2", "drl3", "drl4", "drl5", "drl6", "drl7",
121   "drl8", "drl9", "drl10", "drl11", "drl12", "drl13", "drl14", "drl15"
122 };
123
124 static const char * double_control_register_names[] =
125 {
126   "dpsw", "dcmr", "decnt", "depc"
127 };
128
129 static const char * double_condition_names[] =
130 {
131   "", "un", "eq", "", "lt", "", "le"
132 };
133
134 static inline const char *
135 get_register_name (unsigned int reg)
136 {
137   if (reg < ARRAY_SIZE (register_names))
138     return register_names[reg];
139   return _("<invalid register number>");
140 }
141
142 static inline const char *
143 get_condition_name (unsigned int cond)
144 {
145   if (cond < ARRAY_SIZE (condition_names))
146     return condition_names[cond];
147   return _("<invalid condition code>");
148 }
149
150 static inline const char *
151 get_flag_name (unsigned int flag)
152 {
153   if (flag < ARRAY_SIZE (flag_names))
154     return flag_names[flag];
155   return _("<invalid flag>");
156 }
157
158 static inline const char *
159 get_double_register_name (unsigned int reg)
160 {
161   if (reg < ARRAY_SIZE (double_register_names))
162     return double_register_names[reg];
163   return _("<invalid register number>");
164 }
165
166 static inline const char *
167 get_double_register_high_name (unsigned int reg)
168 {
169   if (reg < ARRAY_SIZE (double_register_high_names))
170     return double_register_high_names[reg];
171   return _("<invalid register number>");
172 }
173
174 static inline const char *
175 get_double_register_low_name (unsigned int reg)
176 {
177   if (reg < ARRAY_SIZE (double_register_low_names))
178     return double_register_low_names[reg];
179   return _("<invalid register number>");
180 }
181
182 static inline const char *
183 get_double_control_register_name (unsigned int reg)
184 {
185   if (reg < ARRAY_SIZE (double_control_register_names))
186     return double_control_register_names[reg];
187   return _("<invalid register number>");
188 }
189
190 static inline const char *
191 get_double_condition_name (unsigned int cond)
192 {
193   if (cond < ARRAY_SIZE (double_condition_names))
194     return double_condition_names[cond];
195   return _("<invalid condition code>");
196 }
197
198 static inline const char *
199 get_opsize_name (unsigned int opsize)
200 {
201   if (opsize < ARRAY_SIZE (opsize_names))
202     return opsize_names[opsize];
203   return _("<invalid opsize>");
204 }
205
206 static inline const char *
207 get_size_name (unsigned int size)
208 {
209   if (size < ARRAY_SIZE (size_names))
210     return size_names[size];
211   return _("<invalid size>");
212 }
213
214
215 int
216 print_insn_rx (bfd_vma addr, disassemble_info * dis)
217 {
218   int rv;
219   RX_Data rx_data;
220   RX_Opcode_Decoded opcode;
221   const char * s;
222   struct private priv;
223
224   dis->private_data = (PTR) &priv;
225   rx_data.pc = addr;
226   rx_data.dis = dis;
227
228   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
229     {
230       /* Error return.  */
231       return -1;
232     }
233
234   rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
235
236   dis->bytes_per_line = 10;
237
238 #define PR (dis->fprintf_func)
239 #define PS (dis->stream)
240 #define PC(c) PR (PS, "%c", c)
241
242   /* Detect illegal instructions.  */
243   if (opcode.op[0].size == RX_Bad_Size
244       || register_names [opcode.op[0].reg] == NULL
245       || register_names [opcode.op[1].reg] == NULL
246       || register_names [opcode.op[2].reg] == NULL)
247     {
248       bfd_byte buf[10];
249       int i;
250
251       PR (PS, ".byte ");
252       rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
253       
254       for (i = 0 ; i < rv; i++)
255         PR (PS, "0x%02x ", buf[i]);
256       return rv;
257     }
258       
259   for (s = opcode.syntax; *s; s++)
260     {
261       if (*s != '%')
262         {
263           PC (*s);
264         }
265       else
266         {
267           RX_Opcode_Operand * oper;
268           int do_size = 0;
269           int do_hex = 0;
270           int do_addr = 0;
271
272           s ++;
273
274           if (*s == 'S')
275             {
276               do_size = 1;
277               s++;
278             }
279           if (*s == 'x')
280             {
281               do_hex = 1;
282               s++;
283             }
284           if (*s == 'a')
285             {
286               do_addr = 1;
287               s++;
288             }
289
290           switch (*s)
291             {
292             case '%':
293               PC ('%');
294               break;
295
296             case 's':
297               PR (PS, "%s", get_opsize_name (opcode.size));
298               break;
299
300             case 'b':
301               s ++;
302               if (*s == 'f')
303                 {
304                   int imm = opcode.op[2].addend;
305                   int slsb, dlsb, width;
306
307                   dlsb = (imm >> 5) & 0x1f;
308                   slsb = (imm & 0x1f);
309                   slsb = (slsb >= 0x10?(slsb ^ 0x1f) + 1:slsb);
310                   slsb = dlsb - slsb;
311                   slsb = (slsb < 0?-slsb:slsb);
312                   width = ((imm >> 10) & 0x1f) - dlsb;
313                   PR (PS, "#%d, #%d, #%d, %s, %s",
314                       slsb, dlsb, width,
315                       get_register_name (opcode.op[1].reg),
316                       get_register_name (opcode.op[0].reg));
317                 }
318               break;
319             case '0':
320             case '1':
321             case '2':
322               oper = opcode.op + (*s - '0');
323               if (do_size)
324                 {
325                   if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
326                     PR (PS, "%s", get_size_name (oper->size));
327                 }
328               else
329                 switch (oper->type)
330                   {
331                   case RX_Operand_Immediate:
332                     if (do_addr)
333                       dis->print_address_func (oper->addend, dis);
334                     else if (do_hex
335                              || oper->addend > 999
336                              || oper->addend < -999)
337                       PR (PS, "%#x", oper->addend);
338                     else
339                       PR (PS, "%d", oper->addend);
340                     break;
341                   case RX_Operand_Register:
342                   case RX_Operand_TwoReg:
343                     PR (PS, "%s", get_register_name (oper->reg));
344                     break;
345                   case RX_Operand_Indirect:
346                     PR (PS, "%d[%s]", oper->addend, get_register_name (oper->reg));
347                     break;
348                   case RX_Operand_Zero_Indirect:
349                     PR (PS, "[%s]", get_register_name (oper->reg));
350                     break;
351                   case RX_Operand_Postinc:
352                     PR (PS, "[%s+]", get_register_name (oper->reg));
353                     break;
354                   case RX_Operand_Predec:
355                     PR (PS, "[-%s]", get_register_name (oper->reg));
356                     break;
357                   case RX_Operand_Condition:
358                     PR (PS, "%s", get_condition_name (oper->reg));
359                     break;
360                   case RX_Operand_Flag:
361                     PR (PS, "%s", get_flag_name (oper->reg));
362                     break;
363                   case RX_Operand_DoubleReg:
364                     PR (PS, "%s", get_double_register_name (oper->reg));
365                     break;
366                   case RX_Operand_DoubleRegH:
367                     PR (PS, "%s", get_double_register_high_name (oper->reg));
368                     break;
369                   case RX_Operand_DoubleRegL:
370                     PR (PS, "%s", get_double_register_low_name (oper->reg));
371                     break;
372                   case RX_Operand_DoubleCReg:
373                     PR (PS, "%s", get_double_control_register_name (oper->reg));
374                     break;
375                   case RX_Operand_DoubleCond:
376                     PR (PS, "%s", get_double_condition_name (oper->reg));
377                     break;
378                   default:
379                     PR (PS, "[???]");
380                     break;
381                   }
382             }
383         }
384     }
385
386   return rv;
387 }
This page took 0.045031 seconds and 4 git commands to generate.