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