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 } 397