]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/rx-dis.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / opcodes / rx-dis.c
CommitLineData
c7927a3c 1/* Disassembler code for Renesas RX.
82704155 2 Copyright (C) 2008-2019 Free Software Foundation, Inc.
c7927a3c
NC
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
5eb3690e 23#include "sysdep.h"
c7927a3c
NC
24#include <stdio.h>
25
26#include "bfd.h"
27#include "dis-asm.h"
28#include "opcode/rx.h"
29
029e9d52
YQ
30#include <setjmp.h>
31
c7927a3c
NC
32typedef struct
33{
34 bfd_vma pc;
35 disassemble_info * dis;
36} RX_Data;
37
029e9d52
YQ
38struct private
39{
40 OPCODES_SIGJMP_BUF bailout;
41};
42
c7927a3c
NC
43static int
44rx_get_byte (void * vdata)
45{
46 bfd_byte buf[1];
47 RX_Data *rx_data = (RX_Data *) vdata;
029e9d52 48 int status;
c7927a3c 49
029e9d52
YQ
50 status = rx_data->dis->read_memory_func (rx_data->pc,
51 buf,
52 1,
53 rx_data->dis);
54 if (status != 0)
55 {
56 struct private *priv = (struct private *) rx_data->dis->private_data;
57
58 rx_data->dis->memory_error_func (status, rx_data->pc,
59 rx_data->dis);
60 OPCODES_SIGLONGJMP (priv->bailout, 1);
61 }
c7927a3c
NC
62
63 rx_data->pc ++;
64 return buf[0];
65}
66
f04265ec 67static char const * size_names[RX_MAX_SIZE] =
c7927a3c 68{
4ce8c66d 69 "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "", "<error>"
c7927a3c
NC
70};
71
f04265ec 72static char const * opsize_names[RX_MAX_SIZE] =
c7927a3c 73{
4ce8c66d 74 "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", ".d", "<error>"
c7927a3c
NC
75};
76
77static char const * register_names[] =
78{
79 /* general registers */
80 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
81 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
82 /* control register */
f04265ec 83 "psw", "pc", "usp", "fpsw", NULL, NULL, NULL, NULL,
a117b0a5
YS
84 "bpsw", "bpc", "isp", "fintv", "intb", "extb", NULL, NULL,
85 "a0", "a1", NULL, NULL, NULL, NULL, NULL, NULL,
f04265ec 86 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
c7927a3c
NC
87};
88
89static char const * condition_names[] =
90{
91 /* condition codes */
92 "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
e7286c56 93 "ge", "lt", "gt", "le", "o", "no", "<invalid>", "<invalid>"
c7927a3c
NC
94};
95
96static const char * flag_names[] =
97{
98 "c", "z", "s", "o", "", "", "", "",
99 "", "", "", "", "", "", "", "",
100 "i", "u", "", "", "", "", "", ""
101 "", "", "", "", "", "", "", "",
102};
103
4ce8c66d
YS
104static const char * double_register_names[] =
105{
106 "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
107 "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15",
108};
109
110static const char * double_register_high_names[] =
111{
112 "drh0", "drh1", "drh2", "drh3", "drh4", "drh5", "drh6", "drh7",
113 "drh8", "drh9", "drh10", "drh11", "drh12", "drh13", "drh14", "drh15",
114};
115
116static const char * double_register_low_names[] =
117{
118 "drl0", "drl1", "drl2", "drl3", "drl4", "drl5", "drl6", "drl7",
119 "drl8", "drl9", "drl10", "drl11", "drl12", "drl13", "drl14", "drl15",
120};
121
122static const char * double_control_register_names[] =
123{
124 "dpsw", "dcmr", "decnt", "depc",
125};
126
127static const char * double_condition_names[] =
128{
129 "", "un", "eq", "", "lt", "", "le",
130};
131
c7927a3c
NC
132int
133print_insn_rx (bfd_vma addr, disassemble_info * dis)
134{
135 int rv;
136 RX_Data rx_data;
137 RX_Opcode_Decoded opcode;
138 const char * s;
029e9d52 139 struct private priv;
c7927a3c 140
029e9d52 141 dis->private_data = (PTR) &priv;
c7927a3c
NC
142 rx_data.pc = addr;
143 rx_data.dis = dis;
144
029e9d52
YQ
145 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
146 {
147 /* Error return. */
148 return -1;
149 }
150
c7927a3c
NC
151 rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
152
153 dis->bytes_per_line = 10;
154
155#define PR (dis->fprintf_func)
156#define PS (dis->stream)
157#define PC(c) PR (PS, "%c", c)
158
f04265ec
NC
159 /* Detect illegal instructions. */
160 if (opcode.op[0].size == RX_Bad_Size
161 || register_names [opcode.op[0].reg] == NULL
162 || register_names [opcode.op[1].reg] == NULL
163 || register_names [opcode.op[2].reg] == NULL)
164 {
165 bfd_byte buf[10];
166 int i;
167
168 PR (PS, ".byte ");
169 rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
170
171 for (i = 0 ; i < rv; i++)
172 PR (PS, "0x%02x ", buf[i]);
173 return rv;
174 }
175
c7927a3c
NC
176 for (s = opcode.syntax; *s; s++)
177 {
178 if (*s != '%')
179 {
180 PC (*s);
181 }
182 else
183 {
184 RX_Opcode_Operand * oper;
185 int do_size = 0;
186 int do_hex = 0;
187 int do_addr = 0;
188
189 s ++;
190
191 if (*s == 'S')
192 {
193 do_size = 1;
194 s++;
195 }
196 if (*s == 'x')
197 {
198 do_hex = 1;
199 s++;
200 }
201 if (*s == 'a')
202 {
203 do_addr = 1;
204 s++;
205 }
206
207 switch (*s)
208 {
209 case '%':
210 PC ('%');
211 break;
212
213 case 's':
214 PR (PS, "%s", opsize_names[opcode.size]);
215 break;
216
4ce8c66d
YS
217 case 'b':
218 s ++;
219 if (*s == 'f') {
220 int imm = opcode.op[2].addend;
221 int slsb, dlsb, width;
222 dlsb = (imm >> 5) & 0x1f;
223 slsb = (imm & 0x1f);
224 slsb = (slsb >= 0x10?(slsb ^ 0x1f) + 1:slsb);
225 slsb = dlsb - slsb;
226 slsb = (slsb < 0?-slsb:slsb);
227 width = ((imm >> 10) & 0x1f) - dlsb;
228 PR (PS, "#%d, #%d, #%d, %s, %s",
229 slsb, dlsb, width,
230 register_names[opcode.op[1].reg],
231 register_names[opcode.op[0].reg]);
232 }
233 break;
c7927a3c
NC
234 case '0':
235 case '1':
236 case '2':
237 oper = opcode.op + *s - '0';
238 if (do_size)
239 {
e292aa7a 240 if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
c7927a3c
NC
241 PR (PS, "%s", size_names[oper->size]);
242 }
243 else
244 switch (oper->type)
245 {
246 case RX_Operand_Immediate:
247 if (do_addr)
248 dis->print_address_func (oper->addend, dis);
249 else if (do_hex
250 || oper->addend > 999
251 || oper->addend < -999)
252 PR (PS, "%#x", oper->addend);
253 else
254 PR (PS, "%d", oper->addend);
255 break;
256 case RX_Operand_Register:
90d6ff62 257 case RX_Operand_TwoReg:
c7927a3c
NC
258 PR (PS, "%s", register_names[oper->reg]);
259 break;
260 case RX_Operand_Indirect:
e292aa7a
NC
261 PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
262 break;
263 case RX_Operand_Zero_Indirect:
264 PR (PS, "[%s]", register_names[oper->reg]);
c7927a3c
NC
265 break;
266 case RX_Operand_Postinc:
267 PR (PS, "[%s+]", register_names[oper->reg]);
268 break;
269 case RX_Operand_Predec:
270 PR (PS, "[-%s]", register_names[oper->reg]);
271 break;
272 case RX_Operand_Condition:
273 PR (PS, "%s", condition_names[oper->reg]);
274 break;
275 case RX_Operand_Flag:
276 PR (PS, "%s", flag_names[oper->reg]);
277 break;
4ce8c66d
YS
278 case RX_Operand_DoubleReg:
279 PR (PS, "%s", double_register_names[oper->reg]);
280 break;
281 case RX_Operand_DoubleRegH:
282 PR (PS, "%s", double_register_high_names[oper->reg]);
283 break;
284 case RX_Operand_DoubleRegL:
285 PR (PS, "%s", double_register_low_names[oper->reg]);
286 break;
287 case RX_Operand_DoubleCReg:
288 PR (PS, "%s", double_control_register_names[oper->reg]);
289 break;
290 case RX_Operand_DoubleCond:
291 PR (PS, "%s", double_condition_names[oper->reg]);
292 break;
c7927a3c
NC
293 default:
294 PR (PS, "[???]");
295 break;
296 }
297 }
298 }
299 }
300
301 return rv;
302}