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