master
c 212 lines 8.49 KB
Raw
1 /*
2 * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "qemu/osdep.h"
19 #include "attribs.h"
20 #include "printinsn.h"
21 #include "insn.h"
22 #include "reg_fields.h"
23 #include "internal.h"
24 #include "decode.h"
25
26 /*
27 * Used when there is some sort of error and we can't figure out the real
28 * system register name
29 */
30 static const char *const generic_sreg_names[256] = {
31 "S000", "S001", "S002", "S003", "S004", "S005", "S006", "S007",
32 "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015",
33 "S016", "S017", "S018", "S019", "S020", "S021", "S022", "S023",
34 "S024", "S025", "S026", "S027", "S028", "S029", "S030", "S031",
35 "S032", "S033", "S034", "S035", "S036", "S037", "S038", "S039",
36 "S040", "S041", "S042", "S043", "S044", "S045", "S046", "S047",
37 "S048", "S049", "S050", "S051", "S052", "S053", "S054", "S055",
38 "S056", "S057", "S058", "S059", "S060", "S061", "S062", "S063",
39 "S064", "S065", "S066", "S067", "S068", "S069", "S070", "S071",
40 "S072", "S073", "S074", "S075", "S076", "S077", "S078", "S079",
41 "S080", "S081", "S082", "S083", "S084", "S085", "S086", "S087",
42 "S088", "S089", "S090", "S091", "S092", "S093", "S094", "S095",
43 "S096", "S097", "S098", "S099", "S100", "S101", "S102", "S103",
44 "S104", "S105", "S106", "S107", "S108", "S109", "S110", "S111",
45 "S112", "S113", "S114", "S115", "S116", "S117", "S118", "S119",
46 "S120", "S121", "S122", "S123", "S124", "S125", "S126", "S127",
47 "S128", "S129", "S130", "S131", "S132", "S133", "S134", "S135",
48 "S136", "S137", "S138", "S139", "S140", "S141", "S142", "S143",
49 "S144", "S145", "S146", "S147", "S148", "S149", "S150", "S151",
50 "S152", "S153", "S154", "S155", "S156", "S157", "S158", "S159",
51 "S160", "S161", "S162", "S163", "S164", "S165", "S166", "S167",
52 "S168", "S169", "S170", "S171", "S172", "S173", "S174", "S175",
53 "S176", "S177", "S178", "S179", "S180", "S181", "S182", "S183",
54 "S184", "S185", "S186", "S187", "S188", "S189", "S190", "S191",
55 "S192", "S193", "S194", "S195", "S196", "S197", "S198", "S199",
56 "S200", "S201", "S202", "S203", "S204", "S205", "S206", "S207",
57 "S208", "S209", "S210", "S211", "S212", "S213", "S214", "S215",
58 "S216", "S217", "S218", "S219", "S220", "S221", "S222", "S223",
59 "S224", "S225", "S226", "S227", "S228", "S229", "S230", "S231",
60 "S232", "S233", "S234", "S235", "S236", "S237", "S238", "S239",
61 "S240", "S241", "S242", "S243", "S244", "S245", "S246", "S247",
62 "S248", "S249", "S250", "S251", "S252", "S253", "S254", "S255",
63 };
64
65 static const char *sreg2str(uint8_t reg)
66 {
67 #ifndef CONFIG_USER_ONLY
68 if (reg < NUM_SREGS) {
69 return hexagon_sregnames[reg];
70 } else {
71 return generic_sreg_names[reg];
72 }
73 #else
74 return generic_sreg_names[reg];
75 #endif
76 }
77
78 /*
79 * Used when there is some sort of error and we can't figure out the real
80 * control register name
81 */
82 static const char *const generic_creg_names[256] = {
83 "C000", "C001", "C002", "C003", "C004", "C005", "C006", "C007",
84 "C008", "C009", "C010", "C011", "C012", "C013", "C014", "C015",
85 "C016", "C017", "C018", "C019", "C020", "C021", "C022", "C023",
86 "C024", "C025", "C026", "C027", "C028", "C029", "C030", "C031",
87 "C032", "C033", "C034", "C035", "C036", "C037", "C038", "C039",
88 "C040", "C041", "C042", "C043", "C044", "C045", "C046", "C047",
89 "C048", "C049", "C050", "C051", "C052", "C053", "C054", "C055",
90 "C056", "C057", "C058", "C059", "C060", "C061", "C062", "C063",
91 "C064", "C065", "C066", "C067", "C068", "C069", "C070", "C071",
92 "C072", "C073", "C074", "C075", "C076", "C077", "C078", "C079",
93 "C080", "C081", "C082", "C083", "C084", "C085", "C086", "C087",
94 "C088", "C089", "C090", "C091", "C092", "C093", "C094", "C095",
95 "C096", "C097", "C098", "C099", "C100", "C101", "C102", "C103",
96 "C104", "C105", "C106", "C107", "C108", "C109", "C110", "C111",
97 "C112", "C113", "C114", "C115", "C116", "C117", "C118", "C119",
98 "C120", "C121", "C122", "C123", "C124", "C125", "C126", "C127",
99 "C128", "C129", "C130", "C131", "C132", "C133", "C134", "C135",
100 "C136", "C137", "C138", "C139", "C140", "C141", "C142", "C143",
101 "C144", "C145", "C146", "C147", "C148", "C149", "C150", "C151",
102 "C152", "C153", "C154", "C155", "C156", "C157", "C158", "C159",
103 "C160", "C161", "C162", "C163", "C164", "C165", "C166", "C167",
104 "C168", "C169", "C170", "C171", "C172", "C173", "C174", "C175",
105 "C176", "C177", "C178", "C179", "C180", "C181", "C182", "C183",
106 "C184", "C185", "C186", "C187", "C188", "C189", "C190", "C191",
107 "C192", "C193", "C194", "C195", "C196", "C197", "C198", "C199",
108 "C200", "C201", "C202", "C203", "C204", "C205", "C206", "C207",
109 "C208", "C209", "C210", "C211", "C212", "C213", "C214", "C215",
110 "C216", "C217", "C218", "C219", "C220", "C221", "C222", "C223",
111 "C224", "C225", "C226", "C227", "C228", "C229", "C230", "C231",
112 "C232", "C233", "C234", "C235", "C236", "C237", "C238", "C239",
113 "C240", "C241", "C242", "C243", "C244", "C245", "C246", "C247",
114 "C248", "C249", "C250", "C251", "C252", "C253", "C254", "C255",
115 };
116
117 static const char *creg2str(uint8_t reg)
118 {
119 uint8_t gpr = reg + HEX_REG_SA0;
120 if (gpr < TOTAL_PER_THREAD_REGS) {
121 return hexagon_regnames[gpr];
122 } else {
123 return generic_creg_names[reg];
124 }
125 }
126
127 static void snprintinsn(GString *buf, Insn *insn)
128 {
129 switch (insn->opcode) {
130 #define DEF_VECX_PRINTINFO(TAG, FMT, ...) DEF_PRINTINFO(TAG, FMT, __VA_ARGS__)
131 #define DEF_PRINTINFO(TAG, FMT, ...) \
132 case TAG: \
133 g_string_append_printf(buf, FMT, __VA_ARGS__); \
134 break;
135 #include "printinsn_generated.h.inc"
136 #undef DEF_VECX_PRINTINFO
137 #undef DEF_PRINTINFO
138 }
139 }
140
141 void snprint_a_pkt_disas(GString *buf, Packet *pkt, uint32_t *words,
142 target_ulong pc, const HexagonCPUConfig *cfg)
143 {
144 bool has_endloop0 = false;
145 bool has_endloop1 = false;
146 bool has_endloop01 = false;
147
148 for (int i = 0; i < pkt->num_insns; i++) {
149 if (pkt->insn[i].part1) {
150 continue;
151 }
152
153 /* We'll print the endloop's at the end of the packet */
154 if (pkt->insn[i].opcode == J2_endloop0) {
155 has_endloop0 = true;
156 continue;
157 }
158 if (pkt->insn[i].opcode == J2_endloop1) {
159 has_endloop1 = true;
160 continue;
161 }
162 if (pkt->insn[i].opcode == J2_endloop01) {
163 has_endloop01 = true;
164 continue;
165 }
166
167 g_string_append_printf(buf, "0x" TARGET_FMT_lx "\t", words[i]);
168
169 if (i == 0) {
170 g_string_append(buf, "{");
171 }
172
173 g_string_append(buf, "\t");
174 if (opcode_supported(pkt->insn[i].opcode, cfg->hex_def)) {
175 snprintinsn(buf, &(pkt->insn[i]));
176 } else {
177 g_string_append(buf, "<invalid>");
178 }
179
180 if (!cfg->ieee_fp_extension &&
181 GET_ATTRIB(pkt->insn[i].opcode, A_HVX_IEEE_FP)) {
182 g_string_append(buf, " (disabled: no ieee_fp)");
183 }
184
185 if (i < pkt->num_insns - 1) {
186 /*
187 * Subinstructions are two instructions encoded
188 * in the same word. Print them on the same line.
189 */
190 if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN)) {
191 g_string_append(buf, "; ");
192 snprintinsn(buf, &(pkt->insn[i + 1]));
193 i++;
194 } else if (pkt->insn[i + 1].opcode != J2_endloop0 &&
195 pkt->insn[i + 1].opcode != J2_endloop1 &&
196 pkt->insn[i + 1].opcode != J2_endloop01) {
197 pc += 4;
198 g_string_append_printf(buf, "\n0x" TARGET_FMT_lx ": ", pc);
199 }
200 }
201 }
202 g_string_append(buf, " }");
203 if (has_endloop0) {
204 g_string_append(buf, " :endloop0");
205 }
206 if (has_endloop1) {
207 g_string_append(buf, " :endloop1");
208 }
209 if (has_endloop01) {
210 g_string_append(buf, " :endloop01");
211 }
212 }