xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/ft32-dis.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
19573673dSchristos /* Disassemble ft32 instructions.
2*cb63e24eSchristos    Copyright (C) 2013-2024 Free Software Foundation, Inc.
39573673dSchristos    Contributed by FTDI (support@ftdichip.com)
49573673dSchristos 
59573673dSchristos    This file is part of the GNU opcodes library.
69573673dSchristos 
79573673dSchristos    This library is free software; you can redistribute it and/or modify
89573673dSchristos    it under the terms of the GNU General Public License as published by
99573673dSchristos    the Free Software Foundation; either version 3, or (at your option)
109573673dSchristos    any later version.
119573673dSchristos 
129573673dSchristos    It is distributed in the hope that it will be useful, but WITHOUT
139573673dSchristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
149573673dSchristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
159573673dSchristos    License for more details.
169573673dSchristos 
179573673dSchristos    You should have received a copy of the GNU General Public License
189573673dSchristos    along with this program; if not, write to the Free Software
199573673dSchristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
209573673dSchristos    MA 02110-1301, USA.  */
219573673dSchristos 
229573673dSchristos #include "sysdep.h"
239573673dSchristos #include <stdio.h>
249573673dSchristos #define STATIC_TABLE
259573673dSchristos #define DEFINE_TABLE
269573673dSchristos 
279573673dSchristos #include "opcode/ft32.h"
28fc4f4269Schristos #include "disassemble.h"
299573673dSchristos 
30*cb63e24eSchristos extern const ft32_opc_info_t ft32_opc_info[];
319573673dSchristos 
329573673dSchristos static fprintf_ftype fpr;
339573673dSchristos static void *stream;
349573673dSchristos 
35fc4f4269Schristos static int
sign_extend(int bit,int value)36fc4f4269Schristos sign_extend (int bit, int value)
379573673dSchristos {
38fc4f4269Schristos   int onebit = (1 << bit);
39fc4f4269Schristos   return (value & (onebit - 1)) - (value & onebit);
40fc4f4269Schristos }
41fc4f4269Schristos 
42fc4f4269Schristos static void
ft32_opcode1(unsigned int iword,struct disassemble_info * info)434f645668Schristos ft32_opcode1 (unsigned int iword,
44fc4f4269Schristos 	      struct disassemble_info *info)
45fc4f4269Schristos {
469573673dSchristos   const ft32_opc_info_t *oo;
479573673dSchristos 
489573673dSchristos   for (oo = ft32_opc_info; oo->name; oo++)
499573673dSchristos     if ((iword & oo->mask) == oo->bits)
509573673dSchristos       break;
519573673dSchristos 
529573673dSchristos   if (oo->name)
539573673dSchristos     {
549573673dSchristos       int f = oo->fields;
559573673dSchristos       int imm;
569573673dSchristos 
57fc4f4269Schristos       fpr (stream, "%s", oo->name);
589573673dSchristos       if (oo->dw)
599573673dSchristos 	fpr (stream, ".%c ", "bsl"[(iword >> FT32_FLD_DW_BIT) & 3]);
609573673dSchristos       else
619573673dSchristos 	fpr (stream, " ");
629573673dSchristos 
639573673dSchristos       while (f)
649573673dSchristos 	{
659573673dSchristos 	  int lobit = f & -f;
669573673dSchristos 	  if (f & lobit)
679573673dSchristos 	    {
689573673dSchristos 	      switch (lobit)
699573673dSchristos 		{
709573673dSchristos 		case  FT32_FLD_CBCRCV:
714f645668Schristos 		  /* imm is {CB, CV}  */
729573673dSchristos 		  imm = ((iword >> FT32_FLD_CB_BIT) & ((1 << FT32_FLD_CB_SIZ) - 1)) << 4;
739573673dSchristos 		  imm |= ((iword >> FT32_FLD_CV_BIT) & ((1 << FT32_FLD_CV_SIZ) - 1));
749573673dSchristos 		  switch (imm)
759573673dSchristos 		    {
769573673dSchristos 		    case 0x00: fpr (stream, "nz");  break;
779573673dSchristos 		    case 0x01: fpr (stream, "z");   break;
789573673dSchristos 		    case 0x10: fpr (stream, "ae");  break;
799573673dSchristos 		    case 0x11: fpr (stream, "b");   break;
809573673dSchristos 		    case 0x20: fpr (stream, "no");  break;
819573673dSchristos 		    case 0x21: fpr (stream, "o");   break;
829573673dSchristos 		    case 0x30: fpr (stream, "ns");  break;
839573673dSchristos 		    case 0x31: fpr (stream, "s");   break;
849573673dSchristos 		    case 0x40: fpr (stream, "lt");  break;
859573673dSchristos 		    case 0x41: fpr (stream, "gte"); break;
869573673dSchristos 		    case 0x50: fpr (stream, "lte"); break;
879573673dSchristos 		    case 0x51: fpr (stream, "gt");  break;
889573673dSchristos 		    case 0x60: fpr (stream, "be");  break;
899573673dSchristos 		    case 0x61: fpr (stream, "a");   break;
904f645668Schristos 		    default:
914f645668Schristos 		      fpr (stream, "%d,$r30,%d", (imm >> 4), (imm & 1));
924f645668Schristos 		      break;
939573673dSchristos 		    }
949573673dSchristos 		  break;
959573673dSchristos 		case  FT32_FLD_CB:
969573673dSchristos 		  imm = (iword >> FT32_FLD_CB_BIT) & ((1 << FT32_FLD_CB_SIZ) - 1);
979573673dSchristos 		  fpr (stream, "%d", imm);
989573673dSchristos 		  break;
999573673dSchristos 		case  FT32_FLD_R_D:
1009573673dSchristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_D_BIT) & 0x1f);
1019573673dSchristos 		  break;
1029573673dSchristos 		case  FT32_FLD_CR:
1039573673dSchristos 		  imm = (iword >> FT32_FLD_CR_BIT) & ((1 << FT32_FLD_CR_SIZ) - 1);
1049573673dSchristos 		  fpr (stream, "$r%d", 28 + imm);
1059573673dSchristos 		  break;
1069573673dSchristos 		case  FT32_FLD_CV:
1079573673dSchristos 		  imm = (iword >> FT32_FLD_CV_BIT) & ((1 << FT32_FLD_CV_SIZ) - 1);
1089573673dSchristos 		  fpr (stream, "%d", imm);
1099573673dSchristos 		  break;
1109573673dSchristos 		case  FT32_FLD_R_1:
1119573673dSchristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_1_BIT) & 0x1f);
1129573673dSchristos 		  break;
1139573673dSchristos 		case  FT32_FLD_RIMM:
1149573673dSchristos 		  imm = (iword >> FT32_FLD_RIMM_BIT) & ((1 << FT32_FLD_RIMM_SIZ) - 1);
1159573673dSchristos 		  if (imm & 0x400)
116fc4f4269Schristos 		    fpr (stream, "%d", sign_extend (9, imm));
1179573673dSchristos 		  else
1189573673dSchristos 		    fpr (stream, "$r%d", imm & 0x1f);
1199573673dSchristos 		  break;
1209573673dSchristos 		case  FT32_FLD_R_2:
1219573673dSchristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_2_BIT) & 0x1f);
1229573673dSchristos 		  break;
1239573673dSchristos 		case  FT32_FLD_K20:
1249573673dSchristos 		  imm = iword & ((1 << FT32_FLD_K20_SIZ) - 1);
125fc4f4269Schristos 		  fpr (stream, "%d", sign_extend (19, imm));
1269573673dSchristos 		  break;
1279573673dSchristos 		case  FT32_FLD_PA:
1289573673dSchristos 		  imm = (iword & ((1 << FT32_FLD_PA_SIZ) - 1)) << 2;
1299573673dSchristos 		  info->print_address_func ((bfd_vma) imm, info);
1309573673dSchristos 		  break;
1319573673dSchristos 		case  FT32_FLD_AA:
1329573673dSchristos 		  imm = iword & ((1 << FT32_FLD_AA_SIZ) - 1);
133fc4f4269Schristos 		  info->print_address_func ((1 << 23) | (bfd_vma) imm, info);
1349573673dSchristos 		  break;
1359573673dSchristos 		case  FT32_FLD_K16:
1369573673dSchristos 		  imm = iword & ((1 << FT32_FLD_K16_SIZ) - 1);
137fc4f4269Schristos 		  fpr (stream, "%d", imm);
1389573673dSchristos 		  break;
139fc4f4269Schristos 		case  FT32_FLD_K15:
140fc4f4269Schristos 		  imm = iword & ((1 << FT32_FLD_K15_SIZ) - 1);
141fc4f4269Schristos 		  fpr (stream, "%d", sign_extend (14, imm));
1429573673dSchristos 		  break;
1439573673dSchristos 		case  FT32_FLD_R_D_POST:
1449573673dSchristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_D_BIT) & 0x1f);
1459573673dSchristos 		  break;
1469573673dSchristos 		case  FT32_FLD_R_1_POST:
1479573673dSchristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_1_BIT) & 0x1f);
1489573673dSchristos 		  break;
1499573673dSchristos 		default:
1509573673dSchristos 		  break;
1519573673dSchristos 		}
1529573673dSchristos 	      f &= ~lobit;
1539573673dSchristos 	      if (f)
1549573673dSchristos 		fpr (stream, ",");
1559573673dSchristos 	    }
1569573673dSchristos 	}
1579573673dSchristos     }
1589573673dSchristos   else
159fc4f4269Schristos     fpr (stream, "!");
1609573673dSchristos }
1614f645668Schristos 
1624f645668Schristos static void
ft32_opcode(bfd_vma addr ATTRIBUTE_UNUSED,unsigned int iword,struct disassemble_info * info)1634f645668Schristos ft32_opcode (bfd_vma addr ATTRIBUTE_UNUSED,
1644f645668Schristos 	     unsigned int iword,
1654f645668Schristos 	     struct disassemble_info *info)
1664f645668Schristos {
1674f645668Schristos   unsigned int sc[2];
1684f645668Schristos   if (ft32_decode_shortcode ((unsigned int) addr, iword, sc))
1694f645668Schristos     {
1704f645668Schristos       ft32_opcode1 (sc[0], info);
1714f645668Schristos       fpr (stream, " ; ");
1724f645668Schristos       ft32_opcode1 (sc[1], info);
1734f645668Schristos     }
1744f645668Schristos   else
1754f645668Schristos     ft32_opcode1 (iword, info);
176fc4f4269Schristos }
177fc4f4269Schristos 
178fc4f4269Schristos int
print_insn_ft32(bfd_vma addr,struct disassemble_info * info)179fc4f4269Schristos print_insn_ft32 (bfd_vma addr, struct disassemble_info *info)
180fc4f4269Schristos {
181fc4f4269Schristos   int status;
182fc4f4269Schristos   stream = info->stream;
183fc4f4269Schristos   bfd_byte buffer[4];
184fc4f4269Schristos   unsigned int iword;
185fc4f4269Schristos 
186fc4f4269Schristos   fpr = info->fprintf_func;
187fc4f4269Schristos 
188fc4f4269Schristos   if ((status = info->read_memory_func (addr, buffer, 4, info)))
189fc4f4269Schristos     goto fail;
190fc4f4269Schristos 
191fc4f4269Schristos   iword = bfd_getl32 (buffer);
192fc4f4269Schristos 
193fc4f4269Schristos   fpr (stream, "%08x ", iword);
194fc4f4269Schristos 
195fc4f4269Schristos   ft32_opcode (addr, iword, info);
1969573673dSchristos 
1979573673dSchristos   return 4;
1989573673dSchristos 
1999573673dSchristos  fail:
2009573673dSchristos   info->memory_error_func (status, addr, info);
2019573673dSchristos   return -1;
2029573673dSchristos }
203