]>
Commit | Line | Data |
---|---|---|
3f33e787 TS |
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 | ||
25 | static const char *sreg2str(unsigned int reg) | |
26 | { | |
27 | if (reg < TOTAL_PER_THREAD_REGS) { | |
28 | return hexagon_regnames[reg]; | |
29 | } else { | |
30 | return "???"; | |
31 | } | |
32 | } | |
33 | ||
34 | static const char *creg2str(unsigned int reg) | |
35 | { | |
36 | return sreg2str(reg + HEX_REG_SA0); | |
37 | } | |
38 | ||
39 | static void snprintinsn(GString *buf, Insn *insn) | |
40 | { | |
41 | switch (insn->opcode) { | |
42 | #define DEF_VECX_PRINTINFO(TAG, FMT, ...) DEF_PRINTINFO(TAG, FMT, __VA_ARGS__) | |
43 | #define DEF_PRINTINFO(TAG, FMT, ...) \ | |
44 | case TAG: \ | |
45 | g_string_append_printf(buf, FMT, __VA_ARGS__); \ | |
46 | break; | |
47 | #include "printinsn_generated.h.inc" | |
48 | #undef DEF_VECX_PRINTINFO | |
49 | #undef DEF_PRINTINFO | |
50 | } | |
51 | } | |
52 | ||
53 | void snprint_a_pkt_disas(GString *buf, Packet *pkt, uint32_t *words, | |
54 | target_ulong pc) | |
55 | { | |
56 | bool has_endloop0 = false; | |
57 | bool has_endloop1 = false; | |
58 | bool has_endloop01 = false; | |
59 | ||
60 | for (int i = 0; i < pkt->num_insns; i++) { | |
61 | if (pkt->insn[i].part1) { | |
62 | continue; | |
63 | } | |
64 | ||
65 | /* We'll print the endloop's at the end of the packet */ | |
66 | if (pkt->insn[i].opcode == J2_endloop0) { | |
67 | has_endloop0 = true; | |
68 | continue; | |
69 | } | |
70 | if (pkt->insn[i].opcode == J2_endloop1) { | |
71 | has_endloop1 = true; | |
72 | continue; | |
73 | } | |
74 | if (pkt->insn[i].opcode == J2_endloop01) { | |
75 | has_endloop01 = true; | |
76 | continue; | |
77 | } | |
78 | ||
79 | g_string_append_printf(buf, "0x" TARGET_FMT_lx "\t", words[i]); | |
80 | ||
81 | if (i == 0) { | |
82 | g_string_append(buf, "{"); | |
83 | } | |
84 | ||
85 | g_string_append(buf, "\t"); | |
86 | snprintinsn(buf, &(pkt->insn[i])); | |
87 | ||
88 | if (i < pkt->num_insns - 1) { | |
89 | /* | |
90 | * Subinstructions are two instructions encoded | |
91 | * in the same word. Print them on the same line. | |
92 | */ | |
93 | if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN)) { | |
94 | g_string_append(buf, "; "); | |
95 | snprintinsn(buf, &(pkt->insn[i + 1])); | |
96 | i++; | |
97 | } else if (pkt->insn[i + 1].opcode != J2_endloop0 && | |
98 | pkt->insn[i + 1].opcode != J2_endloop1 && | |
99 | pkt->insn[i + 1].opcode != J2_endloop01) { | |
100 | pc += 4; | |
101 | g_string_append_printf(buf, "\n0x" TARGET_FMT_lx ": ", pc); | |
102 | } | |
103 | } | |
104 | } | |
105 | g_string_append(buf, " }"); | |
106 | if (has_endloop0) { | |
107 | g_string_append(buf, " :endloop0"); | |
108 | } | |
109 | if (has_endloop1) { | |
110 | g_string_append(buf, " :endloop1"); | |
111 | } | |
112 | if (has_endloop01) { | |
113 | g_string_append(buf, " :endloop01"); | |
114 | } | |
115 | } | |
116 | ||
117 | void snprint_a_pkt_debug(GString *buf, Packet *pkt) | |
118 | { | |
119 | int slot, opcode; | |
120 | ||
121 | if (pkt->num_insns > 1) { | |
122 | g_string_append(buf, "\n{\n"); | |
123 | } | |
124 | ||
125 | for (int i = 0; i < pkt->num_insns; i++) { | |
126 | if (pkt->insn[i].part1) { | |
127 | continue; | |
128 | } | |
129 | g_string_append(buf, "\t"); | |
130 | snprintinsn(buf, &(pkt->insn[i])); | |
131 | ||
132 | if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN)) { | |
133 | g_string_append(buf, " //subinsn"); | |
134 | } | |
135 | if (pkt->insn[i].extension_valid) { | |
136 | g_string_append(buf, " //constant extended"); | |
137 | } | |
138 | slot = pkt->insn[i].slot; | |
139 | opcode = pkt->insn[i].opcode; | |
140 | g_string_append_printf(buf, " //slot=%d:tag=%s\n", | |
141 | slot, opcode_names[opcode]); | |
142 | } | |
143 | if (pkt->num_insns > 1) { | |
144 | g_string_append(buf, "}\n"); | |
145 | } | |
146 | } |