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