Home | History | Annotate | Line # | Download | only in opcodes
xgate-dis.c revision 1.1
      1 /* xgate-dis.c -- Freescale XGATE disassembly
      2    Copyright 2009, 2010, 2011, 2012
      3    Free Software Foundation, Inc.
      4    Written by Sean Keys (skeys (at) 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