Home | History | Annotate | Download | only in opcodes
      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