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