x86: eliminate ImmExt abuse
[deliverable/binutils-gdb.git] / opcodes / rx-dis.c
1 /* Disassembler code for Renesas RX.
2 Copyright (C) 2008-2019 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.045894 seconds and 4 git commands to generate.