]>
Commit | Line | Data |
---|---|---|
3f8107ab | 1 | /* Disassemble ft32 instructions. |
a2c58332 | 2 | Copyright (C) 2013-2022 Free Software Foundation, Inc. |
3f8107ab AM |
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" | |
88c1242d | 28 | #include "disassemble.h" |
3f8107ab AM |
29 | |
30 | extern const ft32_opc_info_t ft32_opc_info[128]; | |
31 | ||
32 | static fprintf_ftype fpr; | |
33 | static void *stream; | |
34 | ||
59e8523b | 35 | static int |
ee077885 | 36 | sign_extend (int bit, int value) |
59e8523b JB |
37 | { |
38 | int onebit = (1 << bit); | |
39 | return (value & (onebit - 1)) - (value & onebit); | |
40 | } | |
41 | ||
3b4b0a62 | 42 | static void |
ee077885 JBFU |
43 | ft32_opcode1 (unsigned int iword, |
44 | struct disassemble_info *info) | |
3f8107ab | 45 | { |
3f8107ab AM |
46 | const ft32_opc_info_t *oo; |
47 | ||
3f8107ab AM |
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 | ||
3b4b0a62 | 57 | fpr (stream, "%s", oo->name); |
3f8107ab | 58 | if (oo->dw) |
ee077885 | 59 | fpr (stream, ".%c ", "bsl"[(iword >> FT32_FLD_DW_BIT) & 3]); |
3f8107ab | 60 | else |
ee077885 | 61 | fpr (stream, " "); |
3f8107ab AM |
62 | |
63 | while (f) | |
ee077885 JBFU |
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 | } | |
3f8107ab | 157 | } |
ee077885 JBFU |
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)) | |
3f8107ab | 169 | { |
ee077885 JBFU |
170 | ft32_opcode1 (sc[0], info); |
171 | fpr (stream, " ; "); | |
172 | ft32_opcode1 (sc[1], info); | |
3f8107ab | 173 | } |
ee077885 JBFU |
174 | else |
175 | ft32_opcode1 (iword, info); | |
3b4b0a62 JB |
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 | ||
ee077885 | 195 | ft32_opcode (addr, iword, info); |
3f8107ab AM |
196 | |
197 | return 4; | |
198 | ||
199 | fail: | |
200 | info->memory_error_func (status, addr, info); | |
201 | return -1; | |
202 | } |