1 /* Disassemble ft32 instructions. 2 Copyright (C) 2013-2024 Free Software Foundation, Inc. 3 Contributed by FTDI (support@ftdichip.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 <stdio.h> 24 #define STATIC_TABLE 25 #define DEFINE_TABLE 26 27 #include "opcode/ft32.h" 28 #include "disassemble.h" 29 30 extern const ft32_opc_info_t ft32_opc_info[]; 31 32 static fprintf_ftype fpr; 33 static void *stream; 34 35 static int 36 sign_extend (int bit, int value) 37 { 38 int onebit = (1 << bit); 39 return (value & (onebit - 1)) - (value & onebit); 40 } 41 42 static void 43 ft32_opcode1 (unsigned int iword, 44 struct disassemble_info *info) 45 { 46 const ft32_opc_info_t *oo; 47 48 for (oo = ft32_opc_info; oo->name; oo++) 49 if ((iword & oo->mask) == oo->bits) 50 break; 51 52 if (oo->name) 53 { 54 int f = oo->fields; 55 int imm; 56 57 fpr (stream, "%s", oo->name); 58 if (oo->dw) 59 fpr (stream, ".%c ", "bsl"[(iword >> FT32_FLD_DW_BIT) & 3]); 60 else 61 fpr (stream, " "); 62 63 while (f) 64 { 65 int lobit = f & -f; 66 if (f & lobit) 67 { 68 switch (lobit) 69 { 70 case FT32_FLD_CBCRCV: 71 /* imm is {CB, CV} */ 72 imm = ((iword >> FT32_FLD_CB_BIT) & ((1 << FT32_FLD_CB_SIZ) - 1)) << 4; 73 imm |= ((iword >> FT32_FLD_CV_BIT) & ((1 << FT32_FLD_CV_SIZ) - 1)); 74 switch (imm) 75 { 76 case 0x00: fpr (stream, "nz"); break; 77 case 0x01: fpr (stream, "z"); break; 78 case 0x10: fpr (stream, "ae"); break; 79 case 0x11: fpr (stream, "b"); break; 80 case 0x20: fpr (stream, "no"); break; 81 case 0x21: fpr (stream, "o"); break; 82 case 0x30: fpr (stream, "ns"); break; 83 case 0x31: fpr (stream, "s"); break; 84 case 0x40: fpr (stream, "lt"); break; 85 case 0x41: fpr (stream, "gte"); break; 86 case 0x50: fpr (stream, "lte"); break; 87 case 0x51: fpr (stream, "gt"); break; 88 case 0x60: fpr (stream, "be"); break; 89 case 0x61: fpr (stream, "a"); break; 90 default: 91 fpr (stream, "%d,$r30,%d", (imm >> 4), (imm & 1)); 92 break; 93 } 94 break; 95 case FT32_FLD_CB: 96 imm = (iword >> FT32_FLD_CB_BIT) & ((1 << FT32_FLD_CB_SIZ) - 1); 97 fpr (stream, "%d", imm); 98 break; 99 case FT32_FLD_R_D: 100 fpr (stream, "$r%d", (iword >> FT32_FLD_R_D_BIT) & 0x1f); 101 break; 102 case FT32_FLD_CR: 103 imm = (iword >> FT32_FLD_CR_BIT) & ((1 << FT32_FLD_CR_SIZ) - 1); 104 fpr (stream, "$r%d", 28 + imm); 105 break; 106 case FT32_FLD_CV: 107 imm = (iword >> FT32_FLD_CV_BIT) & ((1 << FT32_FLD_CV_SIZ) - 1); 108 fpr (stream, "%d", imm); 109 break; 110 case FT32_FLD_R_1: 111 fpr (stream, "$r%d", (iword >> FT32_FLD_R_1_BIT) & 0x1f); 112 break; 113 case FT32_FLD_RIMM: 114 imm = (iword >> FT32_FLD_RIMM_BIT) & ((1 << FT32_FLD_RIMM_SIZ) - 1); 115 if (imm & 0x400) 116 fpr (stream, "%d", sign_extend (9, imm)); 117 else 118 fpr (stream, "$r%d", imm & 0x1f); 119 break; 120 case FT32_FLD_R_2: 121 fpr (stream, "$r%d", (iword >> FT32_FLD_R_2_BIT) & 0x1f); 122 break; 123 case FT32_FLD_K20: 124 imm = iword & ((1 << FT32_FLD_K20_SIZ) - 1); 125 fpr (stream, "%d", sign_extend (19, imm)); 126 break; 127 case FT32_FLD_PA: 128 imm = (iword & ((1 << FT32_FLD_PA_SIZ) - 1)) << 2; 129 info->print_address_func ((bfd_vma) imm, info); 130 break; 131 case FT32_FLD_AA: 132 imm = iword & ((1 << FT32_FLD_AA_SIZ) - 1); 133 info->print_address_func ((1 << 23) | (bfd_vma) imm, info); 134 break; 135 case FT32_FLD_K16: 136 imm = iword & ((1 << FT32_FLD_K16_SIZ) - 1); 137 fpr (stream, "%d", imm); 138 break; 139 case FT32_FLD_K15: 140 imm = iword & ((1 << FT32_FLD_K15_SIZ) - 1); 141 fpr (stream, "%d", sign_extend (14, imm)); 142 break; 143 case FT32_FLD_R_D_POST: 144 fpr (stream, "$r%d", (iword >> FT32_FLD_R_D_BIT) & 0x1f); 145 break; 146 case FT32_FLD_R_1_POST: 147 fpr (stream, "$r%d", (iword >> FT32_FLD_R_1_BIT) & 0x1f); 148 break; 149 default: 150 break; 151 } 152 f &= ~lobit; 153 if (f) 154 fpr (stream, ","); 155 } 156 } 157 } 158 else 159 fpr (stream, "!"); 160 } 161 162 static void 163 ft32_opcode (bfd_vma addr ATTRIBUTE_UNUSED, 164 unsigned int iword, 165 struct disassemble_info *info) 166 { 167 unsigned int sc[2]; 168 if (ft32_decode_shortcode ((unsigned int) addr, iword, sc)) 169 { 170 ft32_opcode1 (sc[0], info); 171 fpr (stream, " ; "); 172 ft32_opcode1 (sc[1], info); 173 } 174 else 175 ft32_opcode1 (iword, info); 176 } 177 178 int 179 print_insn_ft32 (bfd_vma addr, struct disassemble_info *info) 180 { 181 int status; 182 stream = info->stream; 183 bfd_byte buffer[4]; 184 unsigned int iword; 185 186 fpr = info->fprintf_func; 187 188 if ((status = info->read_memory_func (addr, buffer, 4, info))) 189 goto fail; 190 191 iword = bfd_getl32 (buffer); 192 193 fpr (stream, "%08x ", iword); 194 195 ft32_opcode (addr, iword, info); 196 197 return 4; 198 199 fail: 200 info->memory_error_func (status, addr, info); 201 return -1; 202 } 203