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