xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/ft32-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Disassemble ft32 instructions.
2*e992f068Schristos    Copyright (C) 2013-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Contributed by FTDI (support@ftdichip.com)
475fd0b74Schristos 
575fd0b74Schristos    This file is part of the GNU opcodes library.
675fd0b74Schristos 
775fd0b74Schristos    This library is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
1075fd0b74Schristos    any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1375fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1475fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1575fd0b74Schristos    License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "sysdep.h"
2375fd0b74Schristos #include <stdio.h>
2475fd0b74Schristos #define STATIC_TABLE
2575fd0b74Schristos #define DEFINE_TABLE
2675fd0b74Schristos 
2775fd0b74Schristos #include "opcode/ft32.h"
28ede78133Schristos #include "disassemble.h"
2975fd0b74Schristos 
3075fd0b74Schristos extern const ft32_opc_info_t ft32_opc_info[128];
3175fd0b74Schristos 
3275fd0b74Schristos static fprintf_ftype fpr;
3375fd0b74Schristos static void *stream;
3475fd0b74Schristos 
35ede78133Schristos static int
sign_extend(int bit,int value)36ede78133Schristos sign_extend (int bit, int value)
3775fd0b74Schristos {
38ede78133Schristos   int onebit = (1 << bit);
39ede78133Schristos   return (value & (onebit - 1)) - (value & onebit);
40ede78133Schristos }
41ede78133Schristos 
42ede78133Schristos static void
ft32_opcode1(unsigned int iword,struct disassemble_info * info)43*e992f068Schristos ft32_opcode1 (unsigned int iword,
44ede78133Schristos 	      struct disassemble_info *info)
45ede78133Schristos {
4675fd0b74Schristos   const ft32_opc_info_t *oo;
4775fd0b74Schristos 
4875fd0b74Schristos   for (oo = ft32_opc_info; oo->name; oo++)
4975fd0b74Schristos     if ((iword & oo->mask) == oo->bits)
5075fd0b74Schristos       break;
5175fd0b74Schristos 
5275fd0b74Schristos   if (oo->name)
5375fd0b74Schristos     {
5475fd0b74Schristos       int f = oo->fields;
5575fd0b74Schristos       int imm;
5675fd0b74Schristos 
57ede78133Schristos       fpr (stream, "%s", oo->name);
5875fd0b74Schristos       if (oo->dw)
5975fd0b74Schristos 	fpr (stream, ".%c ", "bsl"[(iword >> FT32_FLD_DW_BIT) & 3]);
6075fd0b74Schristos       else
6175fd0b74Schristos 	fpr (stream, " ");
6275fd0b74Schristos 
6375fd0b74Schristos       while (f)
6475fd0b74Schristos 	{
6575fd0b74Schristos 	  int lobit = f & -f;
6675fd0b74Schristos 	  if (f & lobit)
6775fd0b74Schristos 	    {
6875fd0b74Schristos 	      switch (lobit)
6975fd0b74Schristos 		{
7075fd0b74Schristos 		case  FT32_FLD_CBCRCV:
71*e992f068Schristos 		  /* imm is {CB, CV}  */
7275fd0b74Schristos 		  imm = ((iword >> FT32_FLD_CB_BIT) & ((1 << FT32_FLD_CB_SIZ) - 1)) << 4;
7375fd0b74Schristos 		  imm |= ((iword >> FT32_FLD_CV_BIT) & ((1 << FT32_FLD_CV_SIZ) - 1));
7475fd0b74Schristos 		  switch (imm)
7575fd0b74Schristos 		    {
7675fd0b74Schristos 		    case 0x00: fpr (stream, "nz");  break;
7775fd0b74Schristos 		    case 0x01: fpr (stream, "z");   break;
7875fd0b74Schristos 		    case 0x10: fpr (stream, "ae");  break;
7975fd0b74Schristos 		    case 0x11: fpr (stream, "b");   break;
8075fd0b74Schristos 		    case 0x20: fpr (stream, "no");  break;
8175fd0b74Schristos 		    case 0x21: fpr (stream, "o");   break;
8275fd0b74Schristos 		    case 0x30: fpr (stream, "ns");  break;
8375fd0b74Schristos 		    case 0x31: fpr (stream, "s");   break;
8475fd0b74Schristos 		    case 0x40: fpr (stream, "lt");  break;
8575fd0b74Schristos 		    case 0x41: fpr (stream, "gte"); break;
8675fd0b74Schristos 		    case 0x50: fpr (stream, "lte"); break;
8775fd0b74Schristos 		    case 0x51: fpr (stream, "gt");  break;
8875fd0b74Schristos 		    case 0x60: fpr (stream, "be");  break;
8975fd0b74Schristos 		    case 0x61: fpr (stream, "a");   break;
90*e992f068Schristos 		    default:
91*e992f068Schristos 		      fpr (stream, "%d,$r30,%d", (imm >> 4), (imm & 1));
92*e992f068Schristos 		      break;
9375fd0b74Schristos 		    }
9475fd0b74Schristos 		  break;
9575fd0b74Schristos 		case  FT32_FLD_CB:
9675fd0b74Schristos 		  imm = (iword >> FT32_FLD_CB_BIT) & ((1 << FT32_FLD_CB_SIZ) - 1);
9775fd0b74Schristos 		  fpr (stream, "%d", imm);
9875fd0b74Schristos 		  break;
9975fd0b74Schristos 		case  FT32_FLD_R_D:
10075fd0b74Schristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_D_BIT) & 0x1f);
10175fd0b74Schristos 		  break;
10275fd0b74Schristos 		case  FT32_FLD_CR:
10375fd0b74Schristos 		  imm = (iword >> FT32_FLD_CR_BIT) & ((1 << FT32_FLD_CR_SIZ) - 1);
10475fd0b74Schristos 		  fpr (stream, "$r%d", 28 + imm);
10575fd0b74Schristos 		  break;
10675fd0b74Schristos 		case  FT32_FLD_CV:
10775fd0b74Schristos 		  imm = (iword >> FT32_FLD_CV_BIT) & ((1 << FT32_FLD_CV_SIZ) - 1);
10875fd0b74Schristos 		  fpr (stream, "%d", imm);
10975fd0b74Schristos 		  break;
11075fd0b74Schristos 		case  FT32_FLD_R_1:
11175fd0b74Schristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_1_BIT) & 0x1f);
11275fd0b74Schristos 		  break;
11375fd0b74Schristos 		case  FT32_FLD_RIMM:
11475fd0b74Schristos 		  imm = (iword >> FT32_FLD_RIMM_BIT) & ((1 << FT32_FLD_RIMM_SIZ) - 1);
11575fd0b74Schristos 		  if (imm & 0x400)
116ede78133Schristos 		    fpr (stream, "%d", sign_extend (9, imm));
11775fd0b74Schristos 		  else
11875fd0b74Schristos 		    fpr (stream, "$r%d", imm & 0x1f);
11975fd0b74Schristos 		  break;
12075fd0b74Schristos 		case  FT32_FLD_R_2:
12175fd0b74Schristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_2_BIT) & 0x1f);
12275fd0b74Schristos 		  break;
12375fd0b74Schristos 		case  FT32_FLD_K20:
12475fd0b74Schristos 		  imm = iword & ((1 << FT32_FLD_K20_SIZ) - 1);
125ede78133Schristos 		  fpr (stream, "%d", sign_extend (19, imm));
12675fd0b74Schristos 		  break;
12775fd0b74Schristos 		case  FT32_FLD_PA:
12875fd0b74Schristos 		  imm = (iword & ((1 << FT32_FLD_PA_SIZ) - 1)) << 2;
12975fd0b74Schristos 		  info->print_address_func ((bfd_vma) imm, info);
13075fd0b74Schristos 		  break;
13175fd0b74Schristos 		case  FT32_FLD_AA:
13275fd0b74Schristos 		  imm = iword & ((1 << FT32_FLD_AA_SIZ) - 1);
133ede78133Schristos 		  info->print_address_func ((1 << 23) | (bfd_vma) imm, info);
13475fd0b74Schristos 		  break;
13575fd0b74Schristos 		case  FT32_FLD_K16:
13675fd0b74Schristos 		  imm = iword & ((1 << FT32_FLD_K16_SIZ) - 1);
137ede78133Schristos 		  fpr (stream, "%d", imm);
13875fd0b74Schristos 		  break;
139ede78133Schristos 		case  FT32_FLD_K15:
140ede78133Schristos 		  imm = iword & ((1 << FT32_FLD_K15_SIZ) - 1);
141ede78133Schristos 		  fpr (stream, "%d", sign_extend (14, imm));
14275fd0b74Schristos 		  break;
14375fd0b74Schristos 		case  FT32_FLD_R_D_POST:
14475fd0b74Schristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_D_BIT) & 0x1f);
14575fd0b74Schristos 		  break;
14675fd0b74Schristos 		case  FT32_FLD_R_1_POST:
14775fd0b74Schristos 		  fpr (stream, "$r%d", (iword >> FT32_FLD_R_1_BIT) & 0x1f);
14875fd0b74Schristos 		  break;
14975fd0b74Schristos 		default:
15075fd0b74Schristos 		  break;
15175fd0b74Schristos 		}
15275fd0b74Schristos 	      f &= ~lobit;
15375fd0b74Schristos 	      if (f)
15475fd0b74Schristos 		fpr (stream, ",");
15575fd0b74Schristos 	    }
15675fd0b74Schristos 	}
15775fd0b74Schristos     }
15875fd0b74Schristos   else
159ede78133Schristos     fpr (stream, "!");
16075fd0b74Schristos }
161*e992f068Schristos 
162*e992f068Schristos static void
ft32_opcode(bfd_vma addr ATTRIBUTE_UNUSED,unsigned int iword,struct disassemble_info * info)163*e992f068Schristos ft32_opcode (bfd_vma addr ATTRIBUTE_UNUSED,
164*e992f068Schristos 	     unsigned int iword,
165*e992f068Schristos 	     struct disassemble_info *info)
166*e992f068Schristos {
167*e992f068Schristos   unsigned int sc[2];
168*e992f068Schristos   if (ft32_decode_shortcode ((unsigned int) addr, iword, sc))
169*e992f068Schristos     {
170*e992f068Schristos       ft32_opcode1 (sc[0], info);
171*e992f068Schristos       fpr (stream, " ; ");
172*e992f068Schristos       ft32_opcode1 (sc[1], info);
173*e992f068Schristos     }
174*e992f068Schristos   else
175*e992f068Schristos     ft32_opcode1 (iword, info);
176ede78133Schristos }
177ede78133Schristos 
178ede78133Schristos int
print_insn_ft32(bfd_vma addr,struct disassemble_info * info)179ede78133Schristos print_insn_ft32 (bfd_vma addr, struct disassemble_info *info)
180ede78133Schristos {
181ede78133Schristos   int status;
182ede78133Schristos   stream = info->stream;
183ede78133Schristos   bfd_byte buffer[4];
184ede78133Schristos   unsigned int iword;
185ede78133Schristos 
186ede78133Schristos   fpr = info->fprintf_func;
187ede78133Schristos 
188ede78133Schristos   if ((status = info->read_memory_func (addr, buffer, 4, info)))
189ede78133Schristos     goto fail;
190ede78133Schristos 
191ede78133Schristos   iword = bfd_getl32 (buffer);
192ede78133Schristos 
193ede78133Schristos   fpr (stream, "%08x ", iword);
194ede78133Schristos 
195ede78133Schristos   ft32_opcode (addr, iword, info);
19675fd0b74Schristos 
19775fd0b74Schristos   return 4;
19875fd0b74Schristos 
19975fd0b74Schristos  fail:
20075fd0b74Schristos   info->memory_error_func (status, addr, info);
20175fd0b74Schristos   return -1;
20275fd0b74Schristos }
203