Error Buddy
Do you have an error message from your application? Then find the answer with Error Buddy. You can search over 40000 source code files and troubleshooting documents using our beta lucene/nutch search interface or if you prefer, search as normal using google. With LXR technology you can drill right down into the line of source code where it came from with full cross-referencing.
If after searching you didn't get your ideal answer, or you are still unclear what the error means, you can choose to post that question to the community forums following the link included in the search results.
[1.6]001 /* Disassemble D30V instructions. 002 Copyright 1997, 1998, 2000, 2001 Free Software Foundation, Inc. 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU General Public License as published by 006 the Free Software Foundation; either version 2 of the License, or 007 (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU General Public License for more details. 013 014 You should have received a copy of the GNU General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 017 018 #include <stdio.h> 019 #include "sysdep.h" 020 #include "opcode/d30v.h" 021 #include "dis-asm.h" 022 #include "opintl.h" 023 024 #define PC_MASK 0xFFFFFFFF 025 026 static int lookup_opcode PARAMS ((struct d30v_insn *insn, long num, int is_long)); 027 static void print_insn PARAMS ((struct disassemble_info *info, bfd_vma memaddr, long long num, 028 struct d30v_insn *insn, int is_long, int show_ext)); 029 static int extract_value PARAMS ((long long num, struct d30v_operand *oper, int is_long)); 030 031 int 032 print_insn_d30v (memaddr, info) 033 bfd_vma memaddr; 034 struct disassemble_info *info; 035 { 036 int status, result; 037 bfd_byte buffer[12]; 038 unsigned long in1, in2; 039 struct d30v_insn insn; 040 long long num; 041 042 insn.form = (struct d30v_format *) NULL; 043 044 info->bytes_per_line = 8; 045 info->bytes_per_chunk = 4; 046 info->display_endian = BFD_ENDIAN_BIG; 047 048 status = (*info->read_memory_func) (memaddr, buffer, 4, info); 049 if (status != 0) 050 { 051 (*info->memory_error_func) (status, memaddr, info); 052 return -1; 053 } 054 in1 = bfd_getb32 (buffer); 055 056 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info); 057 if (status != 0) 058 { 059 info->bytes_per_line = 8; 060 if (!(result = lookup_opcode (&insn, in1, 0))) 061 (*info->fprintf_func) (info->stream, ".long\t0x%x", in1); 062 else 063 print_insn (info, memaddr, (long long) in1, &insn, 0, result); 064 return 4; 065 } 066 in2 = bfd_getb32 (buffer); 067 068 if (in1 & in2 & FM01) 069 { 070 /* LONG instruction. */ 071 if (!(result = lookup_opcode (&insn, in1, 1))) 072 { 073 (*info->fprintf_func) (info->stream, ".long\t0x%x,0x%x", in1, in2); 074 return 8; 075 } 076 num = (long long) in1 << 32 | in2; 077 print_insn (info, memaddr, num, &insn, 1, result); 078 } 079 else 080 { 081 num = in1; 082 if (!(result = lookup_opcode (&insn, in1, 0))) 083 (*info->fprintf_func) (info->stream, ".long\t0x%x", in1); 084 else 085 print_insn (info, memaddr, num, &insn, 0, result); 086 087 switch (((in1 >> 31) << 1) | (in2 >> 31)) 088 { 089 case 0: 090 (*info->fprintf_func) (info->stream, "\t||\t"); 091 break; 092 case 1: 093 (*info->fprintf_func) (info->stream, "\t->\t"); 094 break; 095 case 2: 096 (*info->fprintf_func) (info->stream, "\t<-\t"); 097 default: 098 break; 099 } 100 101 insn.form = (struct d30v_format *) NULL; 102 num = in2; 103 if (!(result = lookup_opcode (&insn, in2, 0))) 104 (*info->fprintf_func) (info->stream, ".long\t0x%x", in2); 105 else 106 print_insn (info, memaddr, num, &insn, 0, result); 107 } 108 return 8; 109 } 110 111 /* Return 0 if lookup fails, 112 1 if found and only one form, 113 2 if found and there are short and long forms. */ 114 115 static int 116 lookup_opcode (insn, num, is_long) 117 struct d30v_insn *insn; 118 long num; 119 int is_long; 120 { 121 int i = 0, index; 122 struct d30v_format *f; 123 struct d30v_opcode *op = (struct d30v_opcode *) d30v_opcode_table; 124 int op1 = (num >> 25) & 0x7; 125 int op2 = (num >> 20) & 0x1f; 126 int mod = (num >> 18) & 0x3; 127 128 /* Find the opcode. */ 129 do 130 { 131 if ((op->op1 == op1) && (op->op2 == op2)) 132 break; 133 op++; 134 } 135 while (op->name); 136 137 if (!op || !op->name) 138 return 0; 139 140 while (op->op1 == op1 && op->op2 == op2) 141 { 142 /* Scan through all the formats for the opcode. */ 143 index = op->format[i++]; 144 do 145 { 146 f = (struct d30v_format *) &d30v_format_table[index]; 147 while (f->form == index) 148 { 149 if ((!is_long || f->form >= LONG) && (f->modifier == mod)) 150 { 151 insn->form = f; 152 break; 153 } 154 f++; 155 } 156 if (insn->form) 157 break; 158 } 159 while ((index = op->format[i++]) != 0); 160 if (insn->form) 161 break; 162 op++; 163 i = 0; 164 } 165 if (insn->form == NULL) 166 return 0; 167 168 insn->op = op; 169 insn->ecc = (num >> 28) & 0x7; 170 if (op->format[1]) 171 return 2; 172 else 173 return 1; 174 } 175 176 static void 177 print_insn (info, memaddr, num, insn, is_long, show_ext) 178 struct disassemble_info *info; 179 bfd_vma memaddr; 180 long long num; 181 struct d30v_insn *insn; 182 int is_long; 183 int show_ext; 184 { 185 int val, opnum, need_comma = 0; 186 struct d30v_operand *oper; 187 int i, match, opind = 0, need_paren = 0, found_control = 0; 188 189 (*info->fprintf_func) (info->stream, "%s", insn->op->name); 190 191 /* Check for CMP or CMPU. */ 192 if (d30v_operand_table[insn->form->operands[0]].flags & OPERAND_NAME) 193 { 194 opind++; 195 val = 196 extract_value (num, 197 (struct d30v_operand *) &d30v_operand_table[insn->form->operands[0]], 198 is_long); 199 (*info->fprintf_func) (info->stream, "%s", d30v_cc_names[val]); 200 } 201 202 /* Add in ".s" or ".l". */ 203 if (show_ext == 2) 204 { 205 if (is_long) 206 (*info->fprintf_func) (info->stream, ".l"); 207 else 208 (*info->fprintf_func) (info->stream, ".s"); 209 } 210 211 if (insn->ecc) 212 (*info->fprintf_func) (info->stream, "/%s", d30v_ecc_names[insn->ecc]); 213 214 (*info->fprintf_func) (info->stream, "\t"); 215 216 while ((opnum = insn->form->operands[opind++]) != 0) 217 { 218 int bits; 219 oper = (struct d30v_operand *) &d30v_operand_table[opnum]; 220 bits = oper->bits; 221 if (oper->flags & OPERAND_SHIFT) 222 bits += 3; 223 224 if (need_comma 225 && oper->flags != OPERAND_PLUS 226 && oper->flags != OPERAND_MINUS) 227 { 228 need_comma = 0; 229 (*info->fprintf_func) (info->stream, ", "); 230 } 231 232 if (oper->flags == OPERAND_ATMINUS) 233 { 234 (*info->fprintf_func) (info->stream, "@-"); 235 continue; 236 } 237 if (oper->flags == OPERAND_MINUS) 238 { 239 (*info->fprintf_func) (info->stream, "-"); 240 continue; 241 } 242 if (oper->flags == OPERAND_PLUS) 243 { 244 (*info->fprintf_func) (info->stream, "+"); 245 continue; 246 } 247 if (oper->flags == OPERAND_ATSIGN) 248 { 249 (*info->fprintf_func) (info->stream, "@"); 250 continue; 251 } 252 if (oper->flags == OPERAND_ATPAR) 253 { 254 (*info->fprintf_func) (info->stream, "@("); 255 need_paren = 1; 256 continue; 257 } 258 259 if (oper->flags == OPERAND_SPECIAL) 260 continue; 261 262 val = extract_value (num, oper, is_long); 263 264 if (oper->flags & OPERAND_REG) 265 { 266 match = 0; 267 if (oper->flags & OPERAND_CONTROL) 268 { 269 struct d30v_operand *oper3 = 270 (struct d30v_operand *) &d30v_operand_table[insn->form->operands[2]]; 271 int id = extract_value (num, oper3, is_long); 272 found_control = 1; 273 switch (id) 274 { 275 case 0: 276 val |= OPERAND_CONTROL; 277 break; 278 case 1: 279 case 2: 280 val = OPERAND_CONTROL + MAX_CONTROL_REG + id; 281 break; 282 case 3: 283 val |= OPERAND_FLAG; 284 break; 285 default: 286 fprintf (stderr, "illegal id (%d)\n", id); 287 } 288 } 289 else if (oper->flags & OPERAND_ACC) 290 val |= OPERAND_ACC; 291 else if (oper->flags & OPERAND_FLAG) 292 val |= OPERAND_FLAG; 293 for (i = 0; i < reg_name_cnt (); i++) 294 { 295 if (val == pre_defined_registers[i].value) 296 { 297 if (pre_defined_registers[i].pname) 298 (*info->fprintf_func) 299 (info->stream, "%s", pre_defined_registers[i].pname); 300 else 301 (*info->fprintf_func) 302 (info->stream, "%s", pre_defined_registers[i].name); 303 match = 1; 304 break; 305 } 306 } 307 if (match == 0) 308 { 309 /* This would only get executed if a register was not in 310 the register table. */ 311 (*info->fprintf_func) 312 (info->stream, _("<unknown register %d>"), val & 0x3F); 313 } 314 } 315 /* repeati has a relocation, but its first argument is a plain 316 immediate. OTOH instructions like djsri have a pc-relative 317 delay target, but an absolute jump target. Therefore, a test 318 of insn->op->reloc_flag is not specific enough; we must test 319 if the actual operand we are handling now is pc-relative. */ 320 else if (oper->flags & OPERAND_PCREL) 321 { 322 int neg = 0; 323 324 /* IMM6S3 is unsigned. */ 325 if (oper->flags & OPERAND_SIGNED || bits == 32) 326 { 327 long max; 328 max = (1 << (bits - 1)); 329 if (val & max) 330 { 331 if (bits == 32) 332 val = -val; 333 else 334 val = -val & ((1 << bits) - 1); 335 neg = 1; 336 } 337 } 338 if (neg) 339 { 340 (*info->fprintf_func) (info->stream, "-%x\t(", val); 341 (*info->print_address_func) ((memaddr - val) & PC_MASK, info); 342 (*info->fprintf_func) (info->stream, ")"); 343 } 344 else 345 { 346 (*info->fprintf_func) (info->stream, "%x\t(", val); 347 (*info->print_address_func) ((memaddr + val) & PC_MASK, info); 348 (*info->fprintf_func) (info->stream, ")"); 349 } 350 } 351 else if (insn->op->reloc_flag == RELOC_ABS) 352 { 353 (*info->print_address_func) (val, info); 354 } 355 else 356 { 357 if (oper->flags & OPERAND_SIGNED) 358 { 359 int max = (1 << (bits - 1)); 360 if (val & max) 361 { 362 val = -val; 363 if (bits < 32) 364 val &= ((1 << bits) - 1); 365 (*info->fprintf_func) (info->stream, "-"); 366 } 367 } 368 (*info->fprintf_func) (info->stream, "0x%x", val); 369 } 370 /* If there is another operand, then write a comma and space. */ 371 if (insn->form->operands[opind] && !(found_control && opind == 2)) 372 need_comma = 1; 373 } 374 if (need_paren) 375 (*info->fprintf_func) (info->stream, ")"); 376 } 377 378 static int 379 extract_value (num, oper, is_long) 380 long long num; 381 struct d30v_operand *oper; 382 int is_long; 383 { 384 int val; 385 int shift = 12 - oper->position; 386 int mask = (0xFFFFFFFF >> (32 - oper->bits)); 387 388 if (is_long) 389 { 390 if (oper->bits == 32) 391 { 392 /* Piece together 32-bit constant. */ 393 val = ((num & 0x3FFFF) 394 | ((num & 0xFF00000) >> 2) 395 | ((num & 0x3F00000000LL) >> 6)); 396 } 397 else 398 val = (num >> (32 + shift)) & mask; 399 } 400 else 401 val = (num >> shift) & mask; 402 403 if (oper->flags & OPERAND_SHIFT) 404 val <<= 3; 405 406 return val; 407 }
Testing
