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