(root)/
binutils-2.41/
opcodes/
xgate-dis.c
       1  /* xgate-dis.c -- Freescale XGATE disassembly
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3     Written by Sean Keys (skeys@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 "disassemble.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, decodePTR->opcodePTR, raw_code);
     173          	  operandTwo = ripBits (&operMaskReg, 3, decodePTR->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 *= 2; /* Multiply by two as per processor docs.  */
     197                  }
     198                else
     199                  {
     200                    relAddr = raw_code & 0xff;
     201                    relAddr = relAddr * 2 + 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 *= 2; /* Multiply by two as per processor docs.  */
     216                  }
     217                else
     218                  {
     219                    relAddr = raw_code & 0x1FF;
     220                    relAddr = relAddr * 2 + 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            else
     259              {
     260                (*info->fprintf_func)(info->stream, " unhandled mode %s",
     261  				    decodePTR->opcodePTR->constraints);
     262              }
     263            perviousBin = raw_code;
     264          }
     265        else
     266          {
     267            (*info->fprintf_func)(info->stream,
     268  				" unable to find opcode match #0%x", raw_code);
     269          }
     270      }
     271    return bytesRead;
     272  }
     273  
     274  int
     275  print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
     276  {
     277    return print_insn (memaddr, info);
     278  }
     279  
     280  static int
     281  read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
     282      struct disassemble_info* info)
     283  {
     284    int status;
     285    status = (*info->read_memory_func) (memaddr, buffer, size, info);
     286    if (status != 0)
     287      {
     288        (*info->memory_error_func) (status, memaddr, info);
     289        return -1;
     290      }
     291    return 0;
     292  }
     293  
     294  static int
     295  ripBits (unsigned int *operandBitsRemaining,
     296  	 int numBitsRequested,
     297  	 struct xgate_opcode *opcodePTR,
     298  	 unsigned int memory)
     299  {
     300    unsigned int currentBit;
     301    unsigned int operand = 0;
     302    int numBitsFound;
     303  
     304    for (numBitsFound = 0, currentBit = 1u << ((opcodePTR->size * 8) - 1);
     305         numBitsFound < numBitsRequested && currentBit != 0;
     306         currentBit >>= 1)
     307      {
     308        if (currentBit & *operandBitsRemaining)
     309  	{
     310  	  *operandBitsRemaining &= ~(currentBit); /* Consume the current bit.  */
     311  	  operand <<= 1; /* Make room for our next bit.  */
     312  	  numBitsFound++;
     313  	  operand |= (currentBit & memory) > 0;
     314  	}
     315      }
     316    return operand;
     317  }
     318  
     319  static int
     320  macro_search (char *currentName, char *lastName)
     321  {
     322    int i;
     323    int length = 0;
     324    char *where;
     325  
     326    for (i = 0; i < xgate_num_opcodes; i++)
     327      {
     328        where = strstr (xgate_opcodes[i].constraints, lastName);
     329  
     330        if (where)
     331          {
     332            length = strlen (where);
     333          }
     334        if (length)
     335          {
     336            where = strstr (xgate_opcodes[i].constraints, currentName);
     337            if (where)
     338              {
     339                length = strlen (where);
     340                return 1;
     341              }
     342          }
     343      }
     344    return 0;
     345  }
     346  
     347  static struct decodeInfo *
     348  find_match (unsigned int raw_code)
     349  {
     350    struct decodeInfo *decodeTablePTR = 0;
     351    int i;
     352  
     353    for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
     354        i++, decodeTablePTR++)
     355      {
     356        if ((raw_code & decodeTablePTR->operMask)
     357            == decodeTablePTR->opcodePTR->bin_opcode)
     358          {
     359            /* Make sure we didn't run into a macro or alias.  */
     360            if (decodeTablePTR->opcodePTR->cycles_min != 0)
     361              {
     362                return decodeTablePTR;
     363                break;
     364              }
     365            else
     366  	    continue;
     367          }
     368      }
     369    return 0;
     370  }