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 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_C)) 130 { 131 (*info->fprintf_func)(info->stream, " R%x, CCR", 132 (raw_code >> 8) & 0x7); 133 } 134 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_C_R)) 135 { 136 (*info->fprintf_func)(info->stream, " CCR, R%x", 137 (raw_code >> 8) & 0x7); 138 } 139 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_P)) 140 { 141 (*info->fprintf_func)(info->stream, " R%x, PC", 142 (raw_code >> 8) & 0x7); 143 } 144 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI)) 145 { 146 (*info->fprintf_func)(info->stream, " R%x, R%x, R%x", 147 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, 148 (raw_code >> 2) & 0x7); 149 } 150 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR)) 151 { 152 if (raw_code & 0x01) 153 { 154 (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x+)", 155 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, 156 (raw_code >> 2) & 0x7); 157 } 158 else if (raw_code & 0x02) 159 { 160 (*info->fprintf_func)(info->stream, " R%x, (R%x, -R%x)", 161 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, 162 (raw_code >> 2) & 0x7); 163 } 164 else 165 { 166 (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x)", 167 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, 168 (raw_code >> 2) & 0x7); 169 } 170 } 171 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA)) 172 { 173 operandOne = ripBits (&operMaskReg, 3, opcodePTR, raw_code); 174 operandTwo = ripBits (&operMaskReg, 3, opcodePTR, raw_code); 175 ( *info->fprintf_func)(info->stream, " R%x, R%x", operandOne, 176 operandTwo); 177 } 178 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDO5)) 179 { 180 (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)", 181 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f); 182 } 183 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON)) 184 { 185 operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR, 186 raw_code); 187 (*info->fprintf_func)(info->stream, " R%x", operandOne); 188 } 189 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9)) 190 { 191 /* If address is negative handle it accordingly. */ 192 if (raw_code & XGATE_NINE_SIGNBIT) 193 { 194 relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit. */ 195 relAddr = ~relAddr; /* Make signed. */ 196 relAddr |= (raw_code & 0xFF) + 1; /* Apply our value. */ 197 relAddr <<= 1; /* Multiply by two as per processor docs. */ 198 } 199 else 200 { 201 relAddr = raw_code & 0xff; 202 relAddr = (relAddr << 1) + 2; 203 } 204 (*info->fprintf_func)(info->stream, " *%d", relAddr); 205 (*info->fprintf_func)(info->stream, " Abs* 0x"); 206 (*info->print_address_func)(memaddr + relAddr, info); 207 } 208 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10)) 209 { 210 /* If address is negative handle it accordingly. */ 211 if (raw_code & XGATE_TEN_SIGNBIT) 212 { 213 relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit. */ 214 relAddr = ~relAddr; /* Make signed. */ 215 relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value. */ 216 relAddr <<= 1; /* Multiply by two as per processor docs. */ 217 } 218 else 219 { 220 relAddr = raw_code & 0x1FF; 221 relAddr = (relAddr << 1) + 2; 222 } 223 (*info->fprintf_func)(info->stream, " *%d", relAddr); 224 (*info->fprintf_func)(info->stream, " Abs* 0x"); 225 (*info->print_address_func)(memaddr + relAddr, info); 226 } 227 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4)) 228 { 229 (*info->fprintf_func)(info->stream, " R%x, #0x%02x", 230 (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF); 231 } 232 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8)) 233 { 234 if (macro_search (decodePTR->opcodePTR->name, previousOpName) && 235 previousOpName[0]) 236 { 237 absAddress = (0xFF & raw_code) << 8; 238 absAddress |= perviousBin & 0xFF; 239 (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x", 240 (raw_code >> 8) & 0x7, raw_code & 0xff); 241 (*info->print_address_func)(absAddress, info); 242 previousOpName[0] = 0; 243 } 244 else 245 { 246 strcpy (previousOpName, decodePTR->opcodePTR->name); 247 (*info->fprintf_func)(info->stream, " R%x, #0x%02x", 248 (raw_code >> 8) & 0x7, raw_code & 0xff); 249 } 250 } 251 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM3)) 252 { 253 (*info->fprintf_func)(info->stream, " #0x%x", 254 (raw_code >> 8) & 0x7); 255 } 256 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_INH)) 257 { 258 // 259 } 260 else 261 { 262 (*info->fprintf_func)(info->stream, " unhandled mode %s", 263 opcodePTR->constraints); 264 } 265 perviousBin = raw_code; 266 } 267 else 268 { 269 (*info->fprintf_func)(info->stream, 270 " unable to find opcode match #0%x", raw_code); 271 } 272 } 273 return bytesRead; 274 } 275 276 int 277 print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info) 278 { 279 return print_insn (memaddr, info); 280 } 281 282 static int 283 read_memory (bfd_vma memaddr, bfd_byte* buffer, int size, 284 struct disassemble_info* info) 285 { 286 int status; 287 status = (*info->read_memory_func) (memaddr, buffer, size, info); 288 if (status != 0) 289 { 290 (*info->memory_error_func) (status, memaddr, info); 291 return -1; 292 } 293 return 0; 294 } 295 296 static int 297 ripBits (unsigned int *operandBitsRemaining, 298 int numBitsRequested, 299 struct xgate_opcode *opcodePTR, 300 unsigned int memory) 301 { 302 unsigned int currentBit; 303 int operand; 304 int numBitsFound; 305 306 for (operand = 0, numBitsFound = 0, currentBit = 1 307 << ((opcodePTR->size * 8) - 1); 308 (numBitsFound < numBitsRequested) && currentBit; currentBit >>= 1) 309 { 310 if (currentBit & *operandBitsRemaining) 311 { 312 *operandBitsRemaining &= ~(currentBit); /* Consume the current bit. */ 313 operand <<= 1; /* Make room for our next bit. */ 314 numBitsFound++; 315 operand |= (currentBit & memory) > 0; 316 } 317 } 318 return operand; 319 } 320 321 static int 322 macro_search (char *currentName, char *lastName) 323 { 324 int i; 325 int length = 0; 326 char *where; 327 328 for (i = 0; i < xgate_num_opcodes; i++) 329 { 330 where = strstr (xgate_opcodes[i].constraints, lastName); 331 332 if (where) 333 { 334 length = strlen (where); 335 } 336 if (length) 337 { 338 where = strstr (xgate_opcodes[i].constraints, currentName); 339 if (where) 340 { 341 length = strlen (where); 342 return 1; 343 } 344 } 345 } 346 return 0; 347 } 348 349 static struct decodeInfo * 350 find_match (unsigned int raw_code) 351 { 352 struct decodeInfo *decodeTablePTR = 0; 353 int i; 354 355 for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes; 356 i++, decodeTablePTR++) 357 { 358 if ((raw_code & decodeTablePTR->operMask) 359 == decodeTablePTR->opcodePTR->bin_opcode) 360 { 361 /* Make sure we didn't run into a macro or alias. */ 362 if (decodeTablePTR->opcodePTR->cycles_min != 0) 363 { 364 return decodeTablePTR; 365 break; 366 } 367 else 368 continue; 369 } 370 } 371 return 0; 372 } 373