OLD | NEW |
(Empty) | |
| 1 /* xgate-dis.c -- Freescale XGATE disassembly |
| 2 Copyright 2009, 2010, 2011, 2012 |
| 3 Free Software Foundation, Inc. |
| 4 Written by Sean Keys (skeys@ipdatasys.com) |
| 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 <assert.h> |
| 25 #include "dis-asm.h" |
| 26 #include "opintl.h" |
| 27 #include "libiberty.h" |
| 28 #include "ansidecl.h" |
| 29 #include "opcode/xgate.h" |
| 30 |
| 31 #define XGATE_TWO_BYTES 0x02 |
| 32 #define XGATE_NINE_BITS 0x1FF |
| 33 #define XGATE_TEN_BITS 0x3FF |
| 34 #define XGATE_NINE_SIGNBIT 0x100 |
| 35 #define XGATE_TEN_SIGNBIT 0x200 |
| 36 |
| 37 /* Structures. */ |
| 38 struct decodeInfo |
| 39 { |
| 40 unsigned int operMask; |
| 41 unsigned int operMasksRegisterBits; |
| 42 struct xgate_opcode *opcodePTR; |
| 43 }; |
| 44 |
| 45 /* Prototypes for local functions. */ |
| 46 static int print_insn (bfd_vma, struct disassemble_info *); |
| 47 static int read_memory (bfd_vma, bfd_byte*, int, struct disassemble_info *); |
| 48 static int ripBits (unsigned int *, int, |
| 49 struct xgate_opcode *, unsigned int); |
| 50 static int macro_search (char *, char *); |
| 51 static struct decodeInfo * find_match (unsigned int); |
| 52 |
| 53 /* Statics. */ |
| 54 static struct decodeInfo *decodeTable; |
| 55 static int initialized; |
| 56 static char previousOpName[10]; |
| 57 static unsigned int perviousBin; |
| 58 |
| 59 /* Disassemble one instruction at address 'memaddr'. Returns the number |
| 60 of bytes used by that instruction. */ |
| 61 |
| 62 static int |
| 63 print_insn (bfd_vma memaddr, struct disassemble_info* info) |
| 64 { |
| 65 int status; |
| 66 unsigned int raw_code; |
| 67 char *s = 0; |
| 68 long bytesRead = 0; |
| 69 int i = 0; |
| 70 struct xgate_opcode *opcodePTR = (struct xgate_opcode*) xgate_opcodes; |
| 71 struct decodeInfo *decodeTablePTR = 0; |
| 72 struct decodeInfo *decodePTR = 0; |
| 73 unsigned int operandRegisterBits = 0; |
| 74 signed int relAddr = 0; |
| 75 signed int operandOne = 0; |
| 76 signed int operandTwo = 0; |
| 77 bfd_byte buffer[4]; |
| 78 bfd_vma absAddress; |
| 79 |
| 80 unsigned int operMaskReg = 0; |
| 81 /* Initialize our array of opcode masks and check them against our constant |
| 82 table. */ |
| 83 if (!initialized) |
| 84 { |
| 85 decodeTable = xmalloc (sizeof (struct decodeInfo) * xgate_num_opcodes); |
| 86 for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes; |
| 87 i++, decodeTablePTR++, opcodePTR++) |
| 88 { |
| 89 unsigned int bin = 0; |
| 90 unsigned int mask = 0; |
| 91 for (s = opcodePTR->format; *s; s++) |
| 92 { |
| 93 bin <<= 1; |
| 94 mask <<= 1; |
| 95 operandRegisterBits <<= 1; |
| 96 bin |= (*s == '1'); |
| 97 mask |= (*s == '0' || *s == '1'); |
| 98 operandRegisterBits |= (*s == 'r'); |
| 99 } |
| 100 /* Asserting will uncover inconsistencies in our table. */ |
| 101 assert ((s - opcodePTR->format) == 16 || (s - opcodePTR->format) == 32
); |
| 102 assert (opcodePTR->bin_opcode == bin); |
| 103 |
| 104 decodeTablePTR->operMask = mask; |
| 105 decodeTablePTR->operMasksRegisterBits = operandRegisterBits; |
| 106 decodeTablePTR->opcodePTR = opcodePTR; |
| 107 } |
| 108 initialized = 1; |
| 109 } |
| 110 |
| 111 /* Read 16 bits. */ |
| 112 bytesRead += XGATE_TWO_BYTES; |
| 113 status = read_memory (memaddr, buffer, XGATE_TWO_BYTES, info); |
| 114 if (status == 0) |
| 115 { |
| 116 raw_code = buffer[0]; |
| 117 raw_code <<= 8; |
| 118 raw_code += buffer[1]; |
| 119 |
| 120 decodePTR = find_match (raw_code); |
| 121 if (decodePTR) |
| 122 { |
| 123 operMaskReg = decodePTR->operMasksRegisterBits; |
| 124 (*info->fprintf_func)(info->stream, "%s", decodePTR->opcodePTR->name); |
| 125 |
| 126 /* First we compare the shorthand format of the constraints. If we |
| 127 still are unable to pinpoint the operands |
| 128 we analyze the opcodes constraint string. */ |
| 129 switch (decodePTR->opcodePTR->sh_format) |
| 130 { |
| 131 case XG_R_C: |
| 132 (*info->fprintf_func)(info->stream, " R%x, CCR", |
| 133 (raw_code >> 8) & 0x7); |
| 134 break; |
| 135 case XG_C_R: |
| 136 (*info->fprintf_func)(info->stream, " CCR, R%x", |
| 137 (raw_code >> 8) & 0x7); |
| 138 break; |
| 139 case XG_R_P: |
| 140 (*info->fprintf_func)(info->stream, " R%x, PC", |
| 141 (raw_code >> 8) & 0x7); |
| 142 break; |
| 143 case XG_INH: |
| 144 break; |
| 145 case XG_R_R_R: |
| 146 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI)) |
| 147 { |
| 148 (*info->fprintf_func)(info->stream, " R%x, R%x, R%x", |
| 149 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, |
| 150 (raw_code >> 2) & 0x7); |
| 151 } |
| 152 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR)) |
| 153 { |
| 154 if (raw_code & 0x01) |
| 155 { |
| 156 (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x+)", |
| 157 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, |
| 158 (raw_code >> 2) & 0x7); |
| 159 } |
| 160 else if (raw_code & 0x02) |
| 161 { |
| 162 (*info->fprintf_func)(info->stream, " R%x, (R%x, -R%x)", |
| 163 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, |
| 164 (raw_code >> 2) & 0x7); |
| 165 } |
| 166 else |
| 167 { |
| 168 (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x)", |
| 169 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, |
| 170 (raw_code >> 2) & 0x7); |
| 171 } |
| 172 } |
| 173 else |
| 174 { |
| 175 (*info->fprintf_func)(info->stream, " unhandled mode %s", |
| 176 decodePTR->opcodePTR->constraints); |
| 177 } |
| 178 break; |
| 179 case XG_R_R: |
| 180 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA)) |
| 181 { |
| 182 operandOne = ripBits (&operMaskReg, 3, opcodePTR, raw_code); |
| 183 operandTwo = ripBits (&operMaskReg, 3, opcodePTR, raw_code); |
| 184 (*info->fprintf_func)(info->stream, " R%x, R%x", operandOne, |
| 185 operandTwo); |
| 186 } |
| 187 else |
| 188 { |
| 189 (*info->fprintf_func)(info->stream, " unhandled mode %s", |
| 190 opcodePTR->constraints); |
| 191 } |
| 192 break; |
| 193 case XG_R_R_I: |
| 194 (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)", |
| 195 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f); |
| 196 break; |
| 197 case XG_R: |
| 198 operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR, |
| 199 raw_code); |
| 200 (*info->fprintf_func)(info->stream, " R%x", operandOne); |
| 201 break; |
| 202 case XG_I | XG_PCREL: |
| 203 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9)) |
| 204 { |
| 205 /* If address is negative handle it accordingly. */ |
| 206 if (raw_code & XGATE_NINE_SIGNBIT) |
| 207 { |
| 208 relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit. */ |
| 209 relAddr = ~relAddr; /* Make signed. */ |
| 210 relAddr |= (raw_code & 0xFF) + 1; /* Apply our value. */ |
| 211 relAddr <<= 1; /* Multiply by two as per processor docs. */ |
| 212 } |
| 213 else |
| 214 { |
| 215 relAddr = raw_code & 0xff; |
| 216 relAddr = (relAddr << 1) + 2; |
| 217 } |
| 218 (*info->fprintf_func)(info->stream, " *%d", relAddr); |
| 219 (*info->fprintf_func)(info->stream, " Abs* 0x"); |
| 220 (*info->print_address_func)(memaddr + relAddr, info); |
| 221 } |
| 222 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10)) |
| 223 { |
| 224 /* If address is negative handle it accordingly. */ |
| 225 if (raw_code & XGATE_TEN_SIGNBIT) |
| 226 { |
| 227 relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit. */ |
| 228 relAddr = ~relAddr; /* Make signed. */ |
| 229 relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value. */ |
| 230 relAddr <<= 1; /* Multiply by two as per processor docs. */ |
| 231 } |
| 232 else |
| 233 { |
| 234 relAddr = raw_code & 0x1FF; |
| 235 relAddr = (relAddr << 1) + 2; |
| 236 } |
| 237 (*info->fprintf_func)(info->stream, " *%d", relAddr); |
| 238 (*info->fprintf_func)(info->stream, " Abs* 0x"); |
| 239 (*info->print_address_func)(memaddr + relAddr, info); |
| 240 } |
| 241 else |
| 242 { |
| 243 (*info->fprintf_func)(info->stream, |
| 244 " Can't disassemble for mode) %s", |
| 245 decodePTR->opcodePTR->constraints); |
| 246 } |
| 247 break; |
| 248 case XG_R_I: |
| 249 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4)) |
| 250 { |
| 251 (*info->fprintf_func)(info->stream, " R%x, #0x%02x", |
| 252 (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF); |
| 253 } |
| 254 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8)) |
| 255 { |
| 256 if (macro_search (decodePTR->opcodePTR->name, previousOpName) && |
| 257 previousOpName[0]) |
| 258 { |
| 259 absAddress = (0xFF & raw_code) << 8; |
| 260 absAddress |= perviousBin & 0xFF; |
| 261 (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x", |
| 262 (raw_code >> 8) & 0x7, raw_code & 0xff); |
| 263 (*info->print_address_func)(absAddress, info); |
| 264 previousOpName[0] = 0; |
| 265 } |
| 266 else |
| 267 { |
| 268 strcpy (previousOpName, decodePTR->opcodePTR->name); |
| 269 (*info->fprintf_func)(info->stream, " R%x, #0x%02x", |
| 270 (raw_code >> 8) & 0x7, raw_code & 0xff); |
| 271 } |
| 272 } |
| 273 else |
| 274 { |
| 275 (*info->fprintf_func)(info->stream, |
| 276 " Can't disassemble for mode %s", |
| 277 decodePTR->opcodePTR->constraints); |
| 278 } |
| 279 break; |
| 280 case XG_I: |
| 281 (*info->fprintf_func)(info->stream, " #0x%x", |
| 282 (raw_code >> 8) & 0x7); |
| 283 break; |
| 284 default: |
| 285 (*info->fprintf_func)(info->stream, "address mode not found\t %x", |
| 286 opcodePTR->bin_opcode); |
| 287 break; |
| 288 } |
| 289 perviousBin = raw_code; |
| 290 } |
| 291 else |
| 292 { |
| 293 (*info->fprintf_func)(info->stream, |
| 294 " unable to find opcode match #0%x", raw_code); |
| 295 } |
| 296 } |
| 297 return bytesRead; |
| 298 } |
| 299 |
| 300 int |
| 301 print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info) |
| 302 { |
| 303 return print_insn (memaddr, info); |
| 304 } |
| 305 |
| 306 static int |
| 307 read_memory (bfd_vma memaddr, bfd_byte* buffer, int size, |
| 308 struct disassemble_info* info) |
| 309 { |
| 310 int status; |
| 311 status = (*info->read_memory_func) (memaddr, buffer, size, info); |
| 312 if (status != 0) |
| 313 { |
| 314 (*info->memory_error_func) (status, memaddr, info); |
| 315 return -1; |
| 316 } |
| 317 return 0; |
| 318 } |
| 319 |
| 320 static int |
| 321 ripBits (unsigned int *operandBitsRemaining, |
| 322 int numBitsRequested, |
| 323 struct xgate_opcode *opcodePTR, |
| 324 unsigned int memory) |
| 325 { |
| 326 unsigned int currentBit; |
| 327 int operand; |
| 328 int numBitsFound; |
| 329 |
| 330 for (operand = 0, numBitsFound = 0, currentBit = 1 |
| 331 << ((opcodePTR->size * 8) - 1); |
| 332 (numBitsFound < numBitsRequested) && currentBit; currentBit >>= 1) |
| 333 { |
| 334 if (currentBit & *operandBitsRemaining) |
| 335 { |
| 336 *operandBitsRemaining &= ~(currentBit); /* Consume the current bit. *
/ |
| 337 operand <<= 1; /* Make room for our next bit. */ |
| 338 numBitsFound++; |
| 339 operand |= (currentBit & memory) > 0; |
| 340 } |
| 341 } |
| 342 return operand; |
| 343 } |
| 344 |
| 345 static int |
| 346 macro_search (char *currentName, char *lastName) |
| 347 { |
| 348 int i; |
| 349 int length = 0; |
| 350 char *where; |
| 351 |
| 352 for (i = 0; i < xgate_num_opcodes; i++) |
| 353 { |
| 354 where = strstr (xgate_opcodes[i].constraints, lastName); |
| 355 |
| 356 if (where) |
| 357 { |
| 358 length = strlen (where); |
| 359 } |
| 360 if (length) |
| 361 { |
| 362 where = strstr (xgate_opcodes[i].constraints, currentName); |
| 363 if (where) |
| 364 { |
| 365 length = strlen (where); |
| 366 return 1; |
| 367 } |
| 368 } |
| 369 } |
| 370 return 0; |
| 371 } |
| 372 |
| 373 static struct decodeInfo * |
| 374 find_match (unsigned int raw_code) |
| 375 { |
| 376 struct decodeInfo *decodeTablePTR = 0; |
| 377 int i; |
| 378 |
| 379 for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes; |
| 380 i++, decodeTablePTR++) |
| 381 { |
| 382 if ((raw_code & decodeTablePTR->operMask) |
| 383 == decodeTablePTR->opcodePTR->bin_opcode) |
| 384 { |
| 385 /* Make sure we didn't run into a macro or alias. */ |
| 386 if (decodeTablePTR->opcodePTR->cycles_min != 0) |
| 387 { |
| 388 return decodeTablePTR; |
| 389 break; |
| 390 } |
| 391 else |
| 392 continue; |
| 393 } |
| 394 } |
| 395 return 0; |
| 396 } |
OLD | NEW |