1 /* Disassembler code for Renesas RX.
2 Copyright (C) 2008-2024 Free Software Foundation, Inc.
3 Contributed by Red Hat.
6 This file is part of the GNU opcodes library.
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)
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.
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. */
28 #include "opcode/rx.h"
29 #include "libiberty.h"
37 disassemble_info
* dis
;
42 OPCODES_SIGJMP_BUF bailout
;
46 rx_get_byte (void * vdata
)
49 RX_Data
*rx_data
= (RX_Data
*) vdata
;
52 status
= rx_data
->dis
->read_memory_func (rx_data
->pc
,
58 struct private *priv
= (struct private *) rx_data
->dis
->private_data
;
60 rx_data
->dis
->memory_error_func (status
, rx_data
->pc
,
62 OPCODES_SIGLONGJMP (priv
->bailout
, 1);
69 static char const * size_names
[RX_MAX_SIZE
] =
71 "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "", "<error>"
74 static char const * opsize_names
[RX_MAX_SIZE
] =
76 "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", ".d", "<error>"
79 static char const * register_names
[] =
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
91 static char const * condition_names
[] =
93 /* Condition codes. */
94 "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
95 "ge", "lt", "gt", "le", "o", "no", "<invalid>", "<invalid>"
98 static const char * flag_names
[] =
100 "c", "z", "s", "o", "", "", "", "",
101 "", "", "", "", "", "", "", "",
102 "i", "u", "", "", "", "", "", "",
103 "", "", "", "", "", "", "", ""
106 static const char * double_register_names
[] =
108 "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
109 "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
112 static const char * double_register_high_names
[] =
114 "drh0", "drh1", "drh2", "drh3", "drh4", "drh5", "drh6", "drh7",
115 "drh8", "drh9", "drh10", "drh11", "drh12", "drh13", "drh14", "drh15"
118 static const char * double_register_low_names
[] =
120 "drl0", "drl1", "drl2", "drl3", "drl4", "drl5", "drl6", "drl7",
121 "drl8", "drl9", "drl10", "drl11", "drl12", "drl13", "drl14", "drl15"
124 static const char * double_control_register_names
[] =
126 "dpsw", "dcmr", "decnt", "depc"
129 static const char * double_condition_names
[] =
131 "", "un", "eq", "", "lt", "", "le"
134 static inline const char *
135 get_register_name (unsigned int reg
)
137 if (reg
< ARRAY_SIZE (register_names
))
138 return register_names
[reg
];
139 return _("<invalid register number>");
142 static inline const char *
143 get_condition_name (unsigned int cond
)
145 if (cond
< ARRAY_SIZE (condition_names
))
146 return condition_names
[cond
];
147 return _("<invalid condition code>");
150 static inline const char *
151 get_flag_name (unsigned int flag
)
153 if (flag
< ARRAY_SIZE (flag_names
))
154 return flag_names
[flag
];
155 return _("<invalid flag>");
158 static inline const char *
159 get_double_register_name (unsigned int reg
)
161 if (reg
< ARRAY_SIZE (double_register_names
))
162 return double_register_names
[reg
];
163 return _("<invalid register number>");
166 static inline const char *
167 get_double_register_high_name (unsigned int reg
)
169 if (reg
< ARRAY_SIZE (double_register_high_names
))
170 return double_register_high_names
[reg
];
171 return _("<invalid register number>");
174 static inline const char *
175 get_double_register_low_name (unsigned int reg
)
177 if (reg
< ARRAY_SIZE (double_register_low_names
))
178 return double_register_low_names
[reg
];
179 return _("<invalid register number>");
182 static inline const char *
183 get_double_control_register_name (unsigned int reg
)
185 if (reg
< ARRAY_SIZE (double_control_register_names
))
186 return double_control_register_names
[reg
];
187 return _("<invalid register number>");
190 static inline const char *
191 get_double_condition_name (unsigned int cond
)
193 if (cond
< ARRAY_SIZE (double_condition_names
))
194 return double_condition_names
[cond
];
195 return _("<invalid condition code>");
198 static inline const char *
199 get_opsize_name (unsigned int opsize
)
201 if (opsize
< ARRAY_SIZE (opsize_names
))
202 return opsize_names
[opsize
];
203 return _("<invalid opsize>");
206 static inline const char *
207 get_size_name (unsigned int size
)
209 if (size
< ARRAY_SIZE (size_names
))
210 return size_names
[size
];
211 return _("<invalid size>");
216 print_insn_rx (bfd_vma addr
, disassemble_info
* dis
)
220 RX_Opcode_Decoded opcode
;
224 dis
->private_data
= &priv
;
228 if (OPCODES_SIGSETJMP (priv
.bailout
) != 0)
234 rv
= rx_decode_opcode (addr
, &opcode
, rx_get_byte
, &rx_data
);
236 dis
->bytes_per_line
= 10;
238 #define PR (dis->fprintf_func)
239 #define PS (dis->stream)
240 #define PC(c) PR (PS, "%c", c)
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
)
252 rx_data
.dis
->read_memory_func (rx_data
.pc
- rv
, buf
, rv
, rx_data
.dis
);
254 for (i
= 0 ; i
< rv
; i
++)
255 PR (PS
, "0x%02x ", buf
[i
]);
259 for (s
= opcode
.syntax
; *s
; s
++)
267 RX_Opcode_Operand
* oper
;
297 PR (PS
, "%s", get_opsize_name (opcode
.size
));
304 int imm
= opcode
.op
[2].addend
;
305 int slsb
, dlsb
, width
;
307 dlsb
= (imm
>> 5) & 0x1f;
309 slsb
= (slsb
>= 0x10?(slsb
^ 0x1f) + 1:slsb
);
311 slsb
= (slsb
< 0?-slsb
:slsb
);
312 width
= ((imm
>> 10) & 0x1f) - dlsb
;
313 PR (PS
, "#%d, #%d, #%d, %s, %s",
315 get_register_name (opcode
.op
[1].reg
),
316 get_register_name (opcode
.op
[0].reg
));
322 oper
= opcode
.op
+ (*s
- '0');
325 if (oper
->type
== RX_Operand_Indirect
|| oper
->type
== RX_Operand_Zero_Indirect
)
326 PR (PS
, "%s", get_size_name (oper
->size
));
331 case RX_Operand_Immediate
:
333 dis
->print_address_func (oper
->addend
, dis
);
335 || oper
->addend
> 999
336 || oper
->addend
< -999)
337 PR (PS
, "%#x", oper
->addend
);
339 PR (PS
, "%d", oper
->addend
);
341 case RX_Operand_Register
:
342 case RX_Operand_TwoReg
:
343 PR (PS
, "%s", get_register_name (oper
->reg
));
345 case RX_Operand_Indirect
:
346 PR (PS
, "%d[%s]", oper
->addend
, get_register_name (oper
->reg
));
348 case RX_Operand_Zero_Indirect
:
349 PR (PS
, "[%s]", get_register_name (oper
->reg
));
351 case RX_Operand_Postinc
:
352 PR (PS
, "[%s+]", get_register_name (oper
->reg
));
354 case RX_Operand_Predec
:
355 PR (PS
, "[-%s]", get_register_name (oper
->reg
));
357 case RX_Operand_Condition
:
358 PR (PS
, "%s", get_condition_name (oper
->reg
));
360 case RX_Operand_Flag
:
361 PR (PS
, "%s", get_flag_name (oper
->reg
));
363 case RX_Operand_DoubleReg
:
364 PR (PS
, "%s", get_double_register_name (oper
->reg
));
366 case RX_Operand_DoubleRegH
:
367 PR (PS
, "%s", get_double_register_high_name (oper
->reg
));
369 case RX_Operand_DoubleRegL
:
370 PR (PS
, "%s", get_double_register_low_name (oper
->reg
));
372 case RX_Operand_DoubleCReg
:
373 PR (PS
, "%s", get_double_control_register_name (oper
->reg
));
375 case RX_Operand_DoubleCond
:
376 PR (PS
, "%s", get_double_condition_name (oper
->reg
));