1 /* Disassembler code for Renesas RX. 2 Copyright 2008, 2009 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 <stdio.h> 24 25 #include "bfd.h" 26 #include "dis-asm.h" 27 #include "opcode/rx.h" 28 29 typedef struct 30 { 31 bfd_vma pc; 32 disassemble_info * dis; 33 } RX_Data; 34 35 static int 36 rx_get_byte (void * vdata) 37 { 38 bfd_byte buf[1]; 39 RX_Data *rx_data = (RX_Data *) vdata; 40 41 rx_data->dis->read_memory_func (rx_data->pc, 42 buf, 43 1, 44 rx_data->dis); 45 46 rx_data->pc ++; 47 return buf[0]; 48 } 49 50 static char const * size_names[] = 51 { 52 "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l" 53 }; 54 55 static char const * opsize_names[] = 56 { 57 "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l" 58 }; 59 60 static char const * register_names[] = 61 { 62 /* general registers */ 63 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 64 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 65 /* control register */ 66 "psw", "pc", "usp", "fpsw", "", "", "", "wr", 67 "bpsw", "bpc", "isp", "fintv", "intb", "", "", "", 68 "pbp", "pben", "", "", "", "", "", "", 69 "bbpsw", "bbpc", "", "", "", "", "", "" 70 }; 71 72 static char const * condition_names[] = 73 { 74 /* condition codes */ 75 "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", 76 "ge", "lt", "gt", "le", "o", "no", "always", "never" 77 }; 78 79 static const char * flag_names[] = 80 { 81 "c", "z", "s", "o", "", "", "", "", 82 "", "", "", "", "", "", "", "", 83 "i", "u", "", "", "", "", "", "" 84 "", "", "", "", "", "", "", "", 85 }; 86 87 int 88 print_insn_rx (bfd_vma addr, disassemble_info * dis) 89 { 90 int rv; 91 RX_Data rx_data; 92 RX_Opcode_Decoded opcode; 93 const char * s; 94 95 rx_data.pc = addr; 96 rx_data.dis = dis; 97 98 rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data); 99 100 dis->bytes_per_line = 10; 101 102 #define PR (dis->fprintf_func) 103 #define PS (dis->stream) 104 #define PC(c) PR (PS, "%c", c) 105 106 for (s = opcode.syntax; *s; s++) 107 { 108 if (*s != '%') 109 { 110 PC (*s); 111 } 112 else 113 { 114 RX_Opcode_Operand * oper; 115 int do_size = 0; 116 int do_hex = 0; 117 int do_addr = 0; 118 119 s ++; 120 121 if (*s == 'S') 122 { 123 do_size = 1; 124 s++; 125 } 126 if (*s == 'x') 127 { 128 do_hex = 1; 129 s++; 130 } 131 if (*s == 'a') 132 { 133 do_addr = 1; 134 s++; 135 } 136 137 switch (*s) 138 { 139 case '%': 140 PC ('%'); 141 break; 142 143 case 's': 144 PR (PS, "%s", opsize_names[opcode.size]); 145 break; 146 147 case '0': 148 case '1': 149 case '2': 150 oper = opcode.op + *s - '0'; 151 if (do_size) 152 { 153 if (oper->type == RX_Operand_Indirect) 154 PR (PS, "%s", size_names[oper->size]); 155 } 156 else 157 switch (oper->type) 158 { 159 case RX_Operand_Immediate: 160 if (do_addr) 161 dis->print_address_func (oper->addend, dis); 162 else if (do_hex 163 || oper->addend > 999 164 || oper->addend < -999) 165 PR (PS, "%#x", oper->addend); 166 else 167 PR (PS, "%d", oper->addend); 168 break; 169 case RX_Operand_Register: 170 PR (PS, "%s", register_names[oper->reg]); 171 break; 172 case RX_Operand_Indirect: 173 if (oper->addend) 174 PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]); 175 else 176 PR (PS, "[%s]", register_names[oper->reg]); 177 break; 178 case RX_Operand_Postinc: 179 PR (PS, "[%s+]", register_names[oper->reg]); 180 break; 181 case RX_Operand_Predec: 182 PR (PS, "[-%s]", register_names[oper->reg]); 183 break; 184 case RX_Operand_Condition: 185 PR (PS, "%s", condition_names[oper->reg]); 186 break; 187 case RX_Operand_Flag: 188 PR (PS, "%s", flag_names[oper->reg]); 189 break; 190 default: 191 PR (PS, "[???]"); 192 break; 193 } 194 } 195 } 196 } 197 198 return rv; 199 } 200