VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmFormatArmV8.cpp@ 106783

Last change on this file since 106783 was 106760, checked in by vboxsync, 3 months ago

Disassembler: Decode Add/Subtract (extended register) instructions, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.0 KB
Line 
1/* $Id: DisasmFormatArmV8.cpp 106760 2024-10-28 18:00:32Z vboxsync $ */
2/** @file
3 * VBox Disassembler - ARMv8 Style Formatter.
4 */
5
6/*
7 * Copyright (C) 2008-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/dis.h>
33#include "DisasmInternal.h"
34#include "DisasmInternal-armv8.h"
35#include <iprt/armv8.h>
36#include <iprt/assert.h>
37#include <iprt/ctype.h>
38#include <iprt/errcore.h>
39#include <iprt/string.h>
40
41
42/*********************************************************************************************************************************
43* Global Variables *
44*********************************************************************************************************************************/
45static const char g_szSpaces[] =
46" ";
47static const char g_aszArmV8RegGen32[32][4] =
48{
49 "w0\0", "w1\0", "w2\0", "w3\0", "w4\0", "w5\0", "w6\0", "w7\0", "w8\0", "w9\0", "w10", "w11", "w12", "w13", "w14", "w15",
50 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr"
51};
52static const char g_aszArmV8RegGen64[32][4] =
53{
54 "x0\0", "x1\0", "x2\0", "x3\0", "x4\0", "x5\0", "x6\0", "x7\0", "x8\0", "x9\0", "x10", "x11", "x12", "x13", "x14", "x15",
55 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "xzr"
56};
57static const char g_aszArmV8RegFpSingle[32][4] =
58{
59 "s0\0", "s1\0", "s2\0", "s3\0", "s4\0", "s5\0", "s6\0", "s7\0", "s8\0", "s9\0", "s10", "s11", "s12", "s13", "s14", "s15",
60 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"
61};
62static const char g_aszArmV8RegFpDouble[32][4] =
63{
64 "d0\0", "d1\0", "d2\0", "d3\0", "d4\0", "d5\0", "d6\0", "d7\0", "d8\0", "d9\0", "d10", "d11", "d12", "d13", "d14", "d15",
65 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
66};
67static const char g_aszArmV8RegFpHalf[32][4] =
68{
69 "h0\0", "h1\0", "h2\0", "h3\0", "h4\0", "h5\0", "h6\0", "h7\0", "h8\0", "h9\0", "h10", "h11", "h12", "h13", "h14", "h15",
70 "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23", "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31"
71};
72static const char g_aszArmV8RegSimdScalar8Bit[32][4] =
73{
74 "b0\0", "b1\0", "b2\0", "b3\0", "b4\0", "b5\0", "b6\0", "b7\0", "b8\0", "b9\0", "b10", "b11", "b12", "b13", "b14", "b15",
75 "b16", "b17", "b18", "b19", "b20", "b21", "b22", "b23", "b24", "b25", "b26", "b27", "b28", "b29", "b30", "b31"
76};
77static const char g_aszArmV8RegSimdScalar128Bit[32][4] =
78{
79 "q0\0", "q1\0", "q2\0", "q3\0", "q4\0", "q5\0", "q6\0", "q7\0", "q8\0", "q9\0", "q10", "q11", "q12", "q13", "q14", "q15",
80 "q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23", "q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31"
81};
82static const char g_aszArmV8Cond[16][3] =
83{
84 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "al"
85};
86static const char *g_apszArmV8PState[] =
87{
88 /* kDisArmv8InstrPState_SPSel */ "spsel",
89 /* kDisArmv8InstrPState_DAIFSet */ "daifset",
90 /* kDisArmv8InstrPState_DAIFClr */ "daifclr",
91 /* kDisArmv8InstrPState_UAO */ "uao",
92 /* kDisArmv8InstrPState_PAN */ "pan",
93 /* kDisArmv8InstrPState_ALLINT */ "allint",
94 /* kDisArmv8InstrPState_PM */ "pm",
95 /* kDisArmv8InstrPState_SSBS */ "ssbs",
96 /* kDisArmv8InstrPState_DIT */ "dit",
97 /* kDisArmv8InstrPState_SVCRSM */ "svcrsm",
98 /* kDisArmv8InstrPState_SVCRZA */ "svcrza",
99 /* kDisArmv8InstrPState_SVCRSMZA */ "svcrsmza",
100 /* kDisArmv8InstrPState_TCO */ "tco"
101};
102
103
104/**
105 * List of known system registers.
106 *
107 * The list MUST be in ascending order of the system register ID!
108 */
109static const struct
110{
111 /** IPRT system register ID. */
112 uint32_t idSysReg;
113 /** Name of the system register. */
114 const char *pszSysReg;
115 /** Character count of the system register name. */
116 size_t cchSysReg;
117} g_aArmV8SysReg64[] =
118{
119#define DIS_ARMV8_SYSREG(a_idSysReg) { (ARMV8_AARCH64_SYSREG_ ## a_idSysReg), #a_idSysReg, sizeof(#a_idSysReg) - 1 }
120 DIS_ARMV8_SYSREG(OSDTRRX_EL1),
121 DIS_ARMV8_SYSREG(MDSCR_EL1),
122 //DIS_ARMV8_SYSREG(DBGBVRn_EL1(a_Id)),
123 //DIS_ARMV8_SYSREG(DBGBCRn_EL1(a_Id)),
124 //DIS_ARMV8_SYSREG(DBGWVRn_EL1(a_Id)),
125 //DIS_ARMV8_SYSREG(DBGWCRn_EL1(a_Id)),
126 DIS_ARMV8_SYSREG(MDCCINT_EL1),
127 DIS_ARMV8_SYSREG(OSDTRTX_EL1),
128 DIS_ARMV8_SYSREG(OSECCR_EL1),
129 DIS_ARMV8_SYSREG(MDRAR_EL1),
130 DIS_ARMV8_SYSREG(OSLAR_EL1),
131 DIS_ARMV8_SYSREG(OSLSR_EL1),
132 DIS_ARMV8_SYSREG(OSDLR_EL1),
133 DIS_ARMV8_SYSREG(MIDR_EL1),
134 DIS_ARMV8_SYSREG(MPIDR_EL1),
135 DIS_ARMV8_SYSREG(REVIDR_EL1),
136 DIS_ARMV8_SYSREG(ID_PFR0_EL1),
137 DIS_ARMV8_SYSREG(ID_PFR1_EL1),
138 DIS_ARMV8_SYSREG(ID_DFR0_EL1),
139 DIS_ARMV8_SYSREG(ID_AFR0_EL1),
140 DIS_ARMV8_SYSREG(ID_MMFR0_EL1),
141 DIS_ARMV8_SYSREG(ID_MMFR1_EL1),
142 DIS_ARMV8_SYSREG(ID_MMFR2_EL1),
143 DIS_ARMV8_SYSREG(ID_MMFR3_EL1),
144 DIS_ARMV8_SYSREG(ID_ISAR0_EL1),
145 DIS_ARMV8_SYSREG(ID_ISAR1_EL1),
146 DIS_ARMV8_SYSREG(ID_ISAR2_EL1),
147 DIS_ARMV8_SYSREG(ID_ISAR3_EL1),
148 DIS_ARMV8_SYSREG(ID_ISAR4_EL1),
149 DIS_ARMV8_SYSREG(ID_ISAR5_EL1),
150 DIS_ARMV8_SYSREG(ID_MMFR4_EL1),
151 DIS_ARMV8_SYSREG(ID_ISAR6_EL1),
152 DIS_ARMV8_SYSREG(MVFR0_EL1),
153 DIS_ARMV8_SYSREG(MVFR1_EL1),
154 DIS_ARMV8_SYSREG(MVFR2_EL1),
155 DIS_ARMV8_SYSREG(ID_PFR2_EL1),
156 DIS_ARMV8_SYSREG(ID_DFR1_EL1),
157 DIS_ARMV8_SYSREG(ID_MMFR5_EL1),
158 DIS_ARMV8_SYSREG(ID_AA64PFR0_EL1),
159 DIS_ARMV8_SYSREG(ID_AA64PFR1_EL1),
160 DIS_ARMV8_SYSREG(ID_AA64ZFR0_EL1),
161 DIS_ARMV8_SYSREG(ID_AA64SMFR0_EL1),
162 DIS_ARMV8_SYSREG(ID_AA64DFR0_EL1),
163 DIS_ARMV8_SYSREG(ID_AA64DFR1_EL1),
164 DIS_ARMV8_SYSREG(ID_AA64AFR0_EL1),
165 DIS_ARMV8_SYSREG(ID_AA64AFR1_EL1),
166 DIS_ARMV8_SYSREG(ID_AA64ISAR0_EL1),
167 DIS_ARMV8_SYSREG(ID_AA64ISAR1_EL1),
168 DIS_ARMV8_SYSREG(ID_AA64ISAR2_EL1),
169 DIS_ARMV8_SYSREG(ID_AA64MMFR0_EL1),
170 DIS_ARMV8_SYSREG(ID_AA64MMFR1_EL1),
171 DIS_ARMV8_SYSREG(ID_AA64MMFR2_EL1),
172 DIS_ARMV8_SYSREG(SCTRL_EL1),
173 DIS_ARMV8_SYSREG(ACTRL_EL1),
174 DIS_ARMV8_SYSREG(CPACR_EL1),
175 DIS_ARMV8_SYSREG(RGSR_EL1),
176 DIS_ARMV8_SYSREG(GCR_EL1),
177 DIS_ARMV8_SYSREG(ZCR_EL1),
178 DIS_ARMV8_SYSREG(TRFCR_EL1),
179 DIS_ARMV8_SYSREG(SMPRI_EL1),
180 DIS_ARMV8_SYSREG(SMCR_EL1),
181 DIS_ARMV8_SYSREG(TTBR0_EL1),
182 DIS_ARMV8_SYSREG(TTBR1_EL1),
183 DIS_ARMV8_SYSREG(TCR_EL1),
184 DIS_ARMV8_SYSREG(APIAKeyLo_EL1),
185 DIS_ARMV8_SYSREG(APIAKeyHi_EL1),
186 DIS_ARMV8_SYSREG(APIBKeyLo_EL1),
187 DIS_ARMV8_SYSREG(APIBKeyHi_EL1),
188 DIS_ARMV8_SYSREG(APDAKeyLo_EL1),
189 DIS_ARMV8_SYSREG(APDAKeyHi_EL1),
190 DIS_ARMV8_SYSREG(APDBKeyLo_EL1),
191 DIS_ARMV8_SYSREG(APDBKeyHi_EL1),
192 DIS_ARMV8_SYSREG(APGAKeyLo_EL1),
193 DIS_ARMV8_SYSREG(APGAKeyHi_EL1),
194 DIS_ARMV8_SYSREG(SPSR_EL1),
195 DIS_ARMV8_SYSREG(ELR_EL1),
196 DIS_ARMV8_SYSREG(SP_EL0),
197 DIS_ARMV8_SYSREG(SPSEL),
198 DIS_ARMV8_SYSREG(CURRENTEL),
199 DIS_ARMV8_SYSREG(PAN),
200 DIS_ARMV8_SYSREG(UAO),
201 DIS_ARMV8_SYSREG(ALLINT),
202 DIS_ARMV8_SYSREG(ICC_PMR_EL1),
203 DIS_ARMV8_SYSREG(AFSR0_EL1),
204 DIS_ARMV8_SYSREG(AFSR1_EL1),
205 DIS_ARMV8_SYSREG(ESR_EL1),
206 DIS_ARMV8_SYSREG(ERRIDR_EL1),
207 DIS_ARMV8_SYSREG(ERRSELR_EL1),
208 DIS_ARMV8_SYSREG(FAR_EL1),
209 DIS_ARMV8_SYSREG(PAR_EL1),
210 DIS_ARMV8_SYSREG(MAIR_EL1),
211 DIS_ARMV8_SYSREG(AMAIR_EL1),
212 DIS_ARMV8_SYSREG(VBAR_EL1),
213 DIS_ARMV8_SYSREG(ICC_IAR0_EL1),
214 DIS_ARMV8_SYSREG(ICC_EOIR0_EL1),
215 DIS_ARMV8_SYSREG(ICC_HPPIR0_EL1),
216 DIS_ARMV8_SYSREG(ICC_BPR0_EL1),
217 DIS_ARMV8_SYSREG(ICC_AP0R0_EL1),
218 DIS_ARMV8_SYSREG(ICC_AP0R1_EL1),
219 DIS_ARMV8_SYSREG(ICC_AP0R2_EL1),
220 DIS_ARMV8_SYSREG(ICC_AP0R3_EL1),
221 DIS_ARMV8_SYSREG(ICC_AP1R0_EL1),
222 DIS_ARMV8_SYSREG(ICC_AP1R1_EL1),
223 DIS_ARMV8_SYSREG(ICC_AP1R2_EL1),
224 DIS_ARMV8_SYSREG(ICC_AP1R3_EL1),
225 DIS_ARMV8_SYSREG(ICC_NMIAR1_EL1),
226 DIS_ARMV8_SYSREG(ICC_DIR_EL1),
227 DIS_ARMV8_SYSREG(ICC_RPR_EL1),
228 DIS_ARMV8_SYSREG(ICC_SGI1R_EL1),
229 DIS_ARMV8_SYSREG(ICC_ASGI1R_EL1),
230 DIS_ARMV8_SYSREG(ICC_SGI0R_EL1),
231 DIS_ARMV8_SYSREG(ICC_IAR1_EL1),
232 DIS_ARMV8_SYSREG(ICC_EOIR1_EL1),
233 DIS_ARMV8_SYSREG(ICC_HPPIR1_EL1),
234 DIS_ARMV8_SYSREG(ICC_BPR1_EL1),
235 DIS_ARMV8_SYSREG(ICC_CTLR_EL1),
236 DIS_ARMV8_SYSREG(ICC_SRE_EL1),
237 DIS_ARMV8_SYSREG(ICC_IGRPEN0_EL1),
238 DIS_ARMV8_SYSREG(ICC_IGRPEN1_EL1),
239 DIS_ARMV8_SYSREG(CONTEXTIDR_EL1),
240 DIS_ARMV8_SYSREG(TPIDR_EL1),
241 DIS_ARMV8_SYSREG(CNTKCTL_EL1),
242 DIS_ARMV8_SYSREG(CSSELR_EL1),
243 DIS_ARMV8_SYSREG(NZCV),
244 DIS_ARMV8_SYSREG(DAIF),
245 DIS_ARMV8_SYSREG(SVCR),
246 DIS_ARMV8_SYSREG(DIT),
247 DIS_ARMV8_SYSREG(SSBS),
248 DIS_ARMV8_SYSREG(TCO),
249 DIS_ARMV8_SYSREG(FPCR),
250 DIS_ARMV8_SYSREG(FPSR),
251 DIS_ARMV8_SYSREG(ICC_SRE_EL2),
252 DIS_ARMV8_SYSREG(TPIDR_EL0),
253 DIS_ARMV8_SYSREG(TPIDRRO_EL0),
254 DIS_ARMV8_SYSREG(CNTFRQ_EL0),
255 DIS_ARMV8_SYSREG(CNTVCT_EL0),
256 DIS_ARMV8_SYSREG(CNTP_TVAL_EL0),
257 DIS_ARMV8_SYSREG(CNTP_CTL_EL0),
258 DIS_ARMV8_SYSREG(CNTP_CVAL_EL0),
259 DIS_ARMV8_SYSREG(CNTV_CTL_EL0),
260 DIS_ARMV8_SYSREG(VPIDR_EL2),
261 DIS_ARMV8_SYSREG(VMPIDR_EL2),
262 DIS_ARMV8_SYSREG(SCTLR_EL2),
263 DIS_ARMV8_SYSREG(ACTLR_EL2),
264 DIS_ARMV8_SYSREG(HCR_EL2),
265 DIS_ARMV8_SYSREG(MDCR_EL2),
266 DIS_ARMV8_SYSREG(CPTR_EL2),
267 DIS_ARMV8_SYSREG(HSTR_EL2),
268 DIS_ARMV8_SYSREG(HFGRTR_EL2),
269 DIS_ARMV8_SYSREG(HFGWTR_EL2),
270 DIS_ARMV8_SYSREG(HFGITR_EL2),
271 DIS_ARMV8_SYSREG(HACR_EL2),
272 DIS_ARMV8_SYSREG(ZCR_EL2),
273 DIS_ARMV8_SYSREG(TRFCR_EL2),
274 DIS_ARMV8_SYSREG(HCRX_EL2),
275 DIS_ARMV8_SYSREG(SDER32_EL2),
276 DIS_ARMV8_SYSREG(TTBR0_EL2),
277 DIS_ARMV8_SYSREG(TTBR1_EL2),
278 DIS_ARMV8_SYSREG(TCR_EL2),
279 DIS_ARMV8_SYSREG(VTTBR_EL2),
280 DIS_ARMV8_SYSREG(VTCR_EL2),
281 DIS_ARMV8_SYSREG(VNCR_EL2),
282 DIS_ARMV8_SYSREG(VSTTBR_EL2),
283 DIS_ARMV8_SYSREG(VSTCR_EL2),
284 DIS_ARMV8_SYSREG(DACR32_EL2),
285 DIS_ARMV8_SYSREG(HDFGRTR_EL2),
286 DIS_ARMV8_SYSREG(HDFGWTR_EL2),
287 DIS_ARMV8_SYSREG(HAFGRTR_EL2),
288 DIS_ARMV8_SYSREG(SPSR_EL2),
289 DIS_ARMV8_SYSREG(ELR_EL2),
290 DIS_ARMV8_SYSREG(SP_EL1),
291 DIS_ARMV8_SYSREG(IFSR32_EL2),
292 DIS_ARMV8_SYSREG(AFSR0_EL2),
293 DIS_ARMV8_SYSREG(AFSR1_EL2),
294 DIS_ARMV8_SYSREG(ESR_EL2),
295 DIS_ARMV8_SYSREG(VSESR_EL2),
296 DIS_ARMV8_SYSREG(FPEXC32_EL2),
297 DIS_ARMV8_SYSREG(TFSR_EL2),
298 DIS_ARMV8_SYSREG(FAR_EL2),
299 DIS_ARMV8_SYSREG(HPFAR_EL2),
300 DIS_ARMV8_SYSREG(PMSCR_EL2),
301 DIS_ARMV8_SYSREG(MAIR_EL2),
302 DIS_ARMV8_SYSREG(AMAIR_EL2),
303 DIS_ARMV8_SYSREG(MPAMHCR_EL2),
304 DIS_ARMV8_SYSREG(MPAMVPMV_EL2),
305 DIS_ARMV8_SYSREG(MPAM2_EL2),
306 DIS_ARMV8_SYSREG(MPAMVPM0_EL2),
307 DIS_ARMV8_SYSREG(MPAMVPM1_EL2),
308 DIS_ARMV8_SYSREG(MPAMVPM2_EL2),
309 DIS_ARMV8_SYSREG(MPAMVPM3_EL2),
310 DIS_ARMV8_SYSREG(MPAMVPM4_EL2),
311 DIS_ARMV8_SYSREG(MPAMVPM5_EL2),
312 DIS_ARMV8_SYSREG(MPAMVPM6_EL2),
313 DIS_ARMV8_SYSREG(MPAMVPM7_EL2),
314 DIS_ARMV8_SYSREG(VBAR_EL2),
315 DIS_ARMV8_SYSREG(RVBAR_EL2),
316 DIS_ARMV8_SYSREG(RMR_EL2),
317 DIS_ARMV8_SYSREG(VDISR_EL2),
318 DIS_ARMV8_SYSREG(CONTEXTIDR_EL2),
319 DIS_ARMV8_SYSREG(TPIDR_EL2),
320 DIS_ARMV8_SYSREG(SCXTNUM_EL2),
321 DIS_ARMV8_SYSREG(CNTVOFF_EL2),
322 DIS_ARMV8_SYSREG(CNTPOFF_EL2),
323 DIS_ARMV8_SYSREG(CNTHCTL_EL2),
324 DIS_ARMV8_SYSREG(CNTHP_TVAL_EL2),
325 DIS_ARMV8_SYSREG(CNTHP_CTL_EL2),
326 DIS_ARMV8_SYSREG(CNTHP_CVAL_EL2),
327 DIS_ARMV8_SYSREG(CNTHV_TVAL_EL2),
328 DIS_ARMV8_SYSREG(CNTHV_CTL_EL2),
329 DIS_ARMV8_SYSREG(CNTHV_CVAL_EL2),
330 DIS_ARMV8_SYSREG(CNTHVS_TVAL_EL2),
331 DIS_ARMV8_SYSREG(CNTHVS_CTL_EL2),
332 DIS_ARMV8_SYSREG(CNTHVS_CVAL_EL2),
333 DIS_ARMV8_SYSREG(CNTHPS_TVAL_EL2),
334 DIS_ARMV8_SYSREG(CNTHPS_CTL_EL2),
335 DIS_ARMV8_SYSREG(CNTHPS_CVAL_EL2),
336 DIS_ARMV8_SYSREG(SP_EL2)
337#undef DIS_ARMV8_SYSREG
338};
339
340
341/**
342 * Gets the base register name for the given parameter.
343 *
344 * @returns Pointer to the register name.
345 * @param pDis The disassembler state.
346 * @param pParam The parameter.
347 * @param pcchReg Where to store the length of the name.
348 */
349DECLINLINE(const char *) disasmFormatArmV8Reg(PCDISSTATE pDis, PCDISOPPARAMARMV8REG pReg, size_t *pcchReg)
350{
351 RT_NOREF_PV(pDis);
352
353 switch (pReg->enmRegType)
354 {
355 case kDisOpParamArmV8RegType_Gpr_32Bit:
356 {
357 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegGen32));
358 const char *psz = g_aszArmV8RegGen32[pReg->idReg];
359 *pcchReg = 2 + !!psz[2];
360 return psz;
361 }
362 case kDisOpParamArmV8RegType_Gpr_64Bit:
363 {
364 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegGen64));
365 const char *psz = g_aszArmV8RegGen64[pReg->idReg];
366 *pcchReg = 2 + !!psz[2];
367 return psz;
368 }
369 case kDisOpParamArmV8RegType_FpReg_Single:
370 {
371 Assert(pDis->armv8.enmFpType != kDisArmv8InstrFpType_Invalid);
372 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegFpSingle));
373 const char *psz = g_aszArmV8RegFpSingle[pReg->idReg];
374 *pcchReg = 2 + !!psz[2];
375 return psz;
376 }
377 case kDisOpParamArmV8RegType_FpReg_Double:
378 {
379 Assert(pDis->armv8.enmFpType != kDisArmv8InstrFpType_Invalid);
380 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegFpDouble));
381 const char *psz = g_aszArmV8RegFpDouble[pReg->idReg];
382 *pcchReg = 2 + !!psz[2];
383 return psz;
384 }
385 case kDisOpParamArmV8RegType_FpReg_Half:
386 {
387 Assert(pDis->armv8.enmFpType != kDisArmv8InstrFpType_Invalid);
388 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegFpHalf));
389 const char *psz = g_aszArmV8RegFpHalf[pReg->idReg];
390 *pcchReg = 2 + !!psz[2];
391 return psz;
392 }
393 case kDisOpParamArmV8RegType_Simd_Scalar_8Bit:
394 {
395 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegSimdScalar8Bit));
396 const char *psz = g_aszArmV8RegSimdScalar8Bit[pReg->idReg];
397 *pcchReg = 2 + !!psz[2];
398 return psz;
399 }
400 case kDisOpParamArmV8RegType_Simd_Scalar_16Bit:
401 {
402 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegFpHalf));
403 const char *psz = g_aszArmV8RegFpHalf[pReg->idReg];
404 *pcchReg = 2 + !!psz[2];
405 return psz;
406 }
407 case kDisOpParamArmV8RegType_Simd_Scalar_32Bit:
408 {
409 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegFpSingle));
410 const char *psz = g_aszArmV8RegFpSingle[pReg->idReg];
411 *pcchReg = 2 + !!psz[2];
412 return psz;
413 }
414 case kDisOpParamArmV8RegType_Simd_Scalar_64Bit:
415 {
416 /* Using the floating point double register names here. */
417 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegFpDouble));
418 const char *psz = g_aszArmV8RegFpDouble[pReg->idReg];
419 *pcchReg = 2 + !!psz[2];
420 return psz;
421 }
422 case kDisOpParamArmV8RegType_Simd_Scalar_128Bit:
423 {
424 Assert(pReg->idReg < RT_ELEMENTS(g_aszArmV8RegSimdScalar128Bit));
425 const char *psz = g_aszArmV8RegSimdScalar128Bit[pReg->idReg];
426 *pcchReg = 2 + !!psz[2];
427 return psz;
428 }
429 case kDisOpParamArmV8RegType_Sp:
430 {
431 *pcchReg = 2;
432 return "sp";
433 }
434 default:
435 AssertFailed();
436 *pcchReg = 0;
437 return NULL;
438 }
439}
440
441
442/**
443 * Gets the base register name for the given parameter.
444 *
445 * @returns Pointer to the register name.
446 * @param pDis The disassembler state.
447 * @param pParam The parameter.
448 * @param pachTmp Pointer to temporary string storage when building
449 * the register name.
450 * @param pcchReg Where to store the length of the name.
451 */
452static const char *disasmFormatArmV8SysReg(PCDISSTATE pDis, PCDISOPPARAM pParam, char *pachTmp, size_t *pcchReg)
453{
454 RT_NOREF_PV(pDis);
455
456 /* Try to find the system register ID in the table. */
457 /** @todo Binary search (lazy). */
458 for (uint32_t i = 0; i < RT_ELEMENTS(g_aArmV8SysReg64); i++)
459 {
460 if (g_aArmV8SysReg64[i].idSysReg == pParam->armv8.Op.idSysReg)
461 {
462 *pcchReg = g_aArmV8SysReg64[i].cchSysReg;
463 return g_aArmV8SysReg64[i].pszSysReg;
464 }
465 }
466
467 /* Generate S<op0>_<op1>_<Cn>_<Cm>_<op2> identifier. */
468 uint32_t const idSysReg = pParam->armv8.Op.idSysReg;
469 uint8_t idx = 0;
470 pachTmp[idx++] = 'S';
471 pachTmp[idx++] = '2' + ((idSysReg >> 14) & 0x1);
472 pachTmp[idx++] = '_';
473 pachTmp[idx++] = '0' + ((idSysReg >> 11) & 0x7);
474 pachTmp[idx++] = '_';
475
476 uint8_t bTmp = (idSysReg >> 7) & 0xf;
477 if (bTmp >= 10)
478 {
479 pachTmp[idx++] = '1' + (bTmp - 10);
480 bTmp -= 10;
481 }
482 pachTmp[idx++] = '0' + bTmp;
483 pachTmp[idx++] = '_';
484
485 bTmp = (idSysReg >> 3) & 0xf;
486 if (bTmp >= 10)
487 {
488 pachTmp[idx++] = '1' + (bTmp - 10);
489 bTmp -= 10;
490 }
491 pachTmp[idx++] = '0' + bTmp;
492
493 pachTmp[idx++] = '_';
494 pachTmp[idx++] = '0' + (idSysReg & 0x7);
495 pachTmp[idx] = '\0';
496 *pcchReg = idx;
497 return pachTmp;
498}
499
500
501/**
502 * Formats the current instruction in ARMv8 style.
503 *
504 *
505 * @returns The number of output characters. If this is >= cchBuf, then the content
506 * of pszBuf will be truncated.
507 * @param pDis Pointer to the disassembler state.
508 * @param pszBuf The output buffer.
509 * @param cchBuf The size of the output buffer.
510 * @param fFlags Format flags, see DIS_FORMAT_FLAGS_*.
511 * @param pfnGetSymbol Get symbol name for a jmp or call target address. Optional.
512 * @param pvUser User argument for pfnGetSymbol.
513 */
514DISDECL(size_t) DISFormatArmV8Ex(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags,
515 PFNDISGETSYMBOL pfnGetSymbol, void *pvUser)
516{
517 /*
518 * Input validation and massaging.
519 */
520 AssertPtr(pDis);
521 AssertPtrNull(pszBuf);
522 Assert(pszBuf || !cchBuf);
523 AssertPtrNull(pfnGetSymbol);
524 AssertMsg(DIS_FMT_FLAGS_IS_VALID(fFlags), ("%#x\n", fFlags));
525 if (fFlags & DIS_FMT_FLAGS_ADDR_COMMENT)
526 fFlags = (fFlags & ~DIS_FMT_FLAGS_ADDR_LEFT) | DIS_FMT_FLAGS_ADDR_RIGHT;
527 if (fFlags & DIS_FMT_FLAGS_BYTES_COMMENT)
528 fFlags = (fFlags & ~DIS_FMT_FLAGS_BYTES_LEFT) | DIS_FMT_FLAGS_BYTES_RIGHT;
529
530 PCDISOPCODE const pOp = pDis->pCurInstr;
531
532 /*
533 * Output macros
534 */
535 char *pszDst = pszBuf;
536 size_t cchDst = cchBuf;
537 size_t cchOutput = 0;
538#define PUT_C(ch) \
539 do { \
540 cchOutput++; \
541 if (cchDst > 1) \
542 { \
543 cchDst--; \
544 *pszDst++ = (ch); \
545 } \
546 } while (0)
547#define PUT_STR(pszSrc, cchSrc) \
548 do { \
549 cchOutput += (cchSrc); \
550 if (cchDst > (cchSrc)) \
551 { \
552 memcpy(pszDst, (pszSrc), (cchSrc)); \
553 pszDst += (cchSrc); \
554 cchDst -= (cchSrc); \
555 } \
556 else if (cchDst > 1) \
557 { \
558 memcpy(pszDst, (pszSrc), cchDst - 1); \
559 pszDst += cchDst - 1; \
560 cchDst = 1; \
561 } \
562 } while (0)
563#define PUT_SZ(sz) \
564 PUT_STR((sz), sizeof(sz) - 1)
565#define PUT_SZ_STRICT(szStrict, szRelaxed) \
566 do { if (fFlags & DIS_FMT_FLAGS_STRICT) PUT_SZ(szStrict); else PUT_SZ(szRelaxed); } while (0)
567#define PUT_PSZ(psz) \
568 do { const size_t cchTmp = strlen(psz); PUT_STR((psz), cchTmp); } while (0)
569#define PUT_NUM(cch, fmt, num) \
570 do { \
571 cchOutput += (cch); \
572 if (cchDst > 1) \
573 { \
574 const size_t cchTmp = RTStrPrintf(pszDst, cchDst, fmt, (num)); \
575 pszDst += cchTmp; \
576 cchDst -= cchTmp; \
577 Assert(cchTmp == (cch) || cchDst == 1); \
578 } \
579 } while (0)
580/** @todo add two flags for choosing between %X / %x and h / 0x. */
581#define PUT_NUM_8(num) PUT_NUM(4, "0x%02x", (uint8_t)(num))
582#define PUT_NUM_16(num) PUT_NUM(6, "0x%04x", (uint16_t)(num))
583#define PUT_NUM_32(num) PUT_NUM(10, "0x%08x", (uint32_t)(num))
584#define PUT_NUM_64(num) PUT_NUM(18, "0x%016RX64", (uint64_t)(num))
585
586#define PUT_NUM_SIGN(cch, fmt, num, stype, utype) \
587 do { \
588 if ((stype)(num) >= 0) \
589 { \
590 PUT_C('+'); \
591 PUT_NUM(cch, fmt, (utype)(num)); \
592 } \
593 else \
594 { \
595 PUT_C('-'); \
596 PUT_NUM(cch, fmt, (utype)-(stype)(num)); \
597 } \
598 } while (0)
599#define PUT_NUM_S8(num) PUT_NUM_SIGN(4, "0x%02x", num, int8_t, uint8_t)
600#define PUT_NUM_S16(num) PUT_NUM_SIGN(6, "0x%04x", num, int16_t, uint16_t)
601#define PUT_NUM_S32(num) PUT_NUM_SIGN(10, "0x%08x", num, int32_t, uint32_t)
602#define PUT_NUM_S64(num) PUT_NUM_SIGN(18, "0x%016RX64", num, int64_t, uint64_t)
603
604#define PUT_SYMBOL_TWO(a_rcSym, a_szStart, a_chEnd) \
605 do { \
606 if (RT_SUCCESS(a_rcSym)) \
607 { \
608 PUT_SZ(a_szStart); \
609 PUT_PSZ(szSymbol); \
610 if (off != 0) \
611 { \
612 if ((int8_t)off == off) \
613 PUT_NUM_S8(off); \
614 else if ((int16_t)off == off) \
615 PUT_NUM_S16(off); \
616 else if ((int32_t)off == off) \
617 PUT_NUM_S32(off); \
618 else \
619 PUT_NUM_S64(off); \
620 } \
621 PUT_C(a_chEnd); \
622 } \
623 } while (0)
624
625#define PUT_SYMBOL(a_uSeg, a_uAddr, a_szStart, a_chEnd) \
626 do { \
627 if (pfnGetSymbol) \
628 { \
629 int rcSym = pfnGetSymbol(pDis, a_uSeg, a_uAddr, szSymbol, sizeof(szSymbol), &off, pvUser); \
630 PUT_SYMBOL_TWO(rcSym, a_szStart, a_chEnd); \
631 } \
632 } while (0)
633
634
635 /*
636 * The address?
637 */
638 if (fFlags & DIS_FMT_FLAGS_ADDR_LEFT)
639 {
640#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
641 if (pDis->uInstrAddr >= _4G)
642 PUT_NUM(9, "%08x`", (uint32_t)(pDis->uInstrAddr >> 32));
643#endif
644 PUT_NUM(8, "%08x", (uint32_t)pDis->uInstrAddr);
645 PUT_C(' ');
646 }
647
648 /*
649 * The opcode bytes?
650 */
651 if (fFlags & DIS_FMT_FLAGS_BYTES_LEFT)
652 {
653 size_t cchTmp = disFormatBytes(pDis, pszDst, cchDst, fFlags);
654 cchOutput += cchTmp;
655 if (cchDst > 1)
656 {
657 if (cchTmp <= cchDst)
658 {
659 cchDst -= cchTmp;
660 pszDst += cchTmp;
661 }
662 else
663 {
664 pszDst += cchDst - 1;
665 cchDst = 1;
666 }
667 }
668
669 /* Some padding to align the instruction. */
670 size_t cchPadding = (7 * (2 + !!(fFlags & DIS_FMT_FLAGS_BYTES_SPACED)))
671 + !!(fFlags & DIS_FMT_FLAGS_BYTES_BRACKETS) * 2
672 + 2;
673 cchPadding = cchTmp + 1 >= cchPadding ? 1 : cchPadding - cchTmp;
674 PUT_STR(g_szSpaces, cchPadding);
675 }
676
677
678 /*
679 * Filter out invalid opcodes first as they need special
680 * treatment. UDF is an exception and should be handled normally.
681 */
682 size_t const offInstruction = cchOutput;
683 if (pOp->uOpcode == OP_INVALID)
684 PUT_SZ("Illegal opcode");
685 else
686 {
687 /* Start with the instruction. */
688 PUT_PSZ(pOp->pszOpcode);
689
690 /* Add any conditionals. */
691 if (pDis->armv8.enmCond != kDisArmv8InstrCond_Al)
692 {
693 PUT_C('.');
694 Assert((uint16_t)pDis->armv8.enmCond < RT_ELEMENTS(g_aszArmV8Cond));
695 PUT_STR(g_aszArmV8Cond[pDis->armv8.enmCond], sizeof(g_aszArmV8Cond[0]) - 1);
696 }
697
698 /*
699 * Format the parameters.
700 */
701 RTINTPTR off;
702 char szSymbol[128];
703 for (uint32_t i = 0; i < RT_ELEMENTS(pDis->aParams); i++)
704 {
705 PCDISOPPARAM pParam = &pDis->aParams[i];
706
707 /* First None parameter marks end of parameters. */
708 if (pParam->armv8.enmType == kDisArmv8OpParmNone)
709 break;
710
711 if (i > 0)
712 PUT_C(',');
713 PUT_C(' '); /** @todo Make the indenting configurable. */
714
715 switch (pParam->armv8.enmType)
716 {
717 case kDisArmv8OpParmImm:
718 {
719 PUT_C('#');
720 switch (pParam->fUse & ( DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE64
721 | DISUSE_IMMEDIATE16_SX8 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE64_SX8))
722 {
723 case DISUSE_IMMEDIATE8:
724 PUT_NUM_8(pParam->uValue);
725 break;
726 case DISUSE_IMMEDIATE16:
727 PUT_NUM_16(pParam->uValue);
728 break;
729 case DISUSE_IMMEDIATE16_SX8:
730 PUT_NUM_16(pParam->uValue);
731 break;
732 case DISUSE_IMMEDIATE32:
733 PUT_NUM_32(pParam->uValue);
734 /** @todo Symbols */
735 break;
736 case DISUSE_IMMEDIATE32_SX8:
737 PUT_NUM_32(pParam->uValue);
738 break;
739 case DISUSE_IMMEDIATE64_SX8:
740 PUT_NUM_64(pParam->uValue);
741 break;
742 case DISUSE_IMMEDIATE64:
743 PUT_NUM_64(pParam->uValue);
744 /** @todo Symbols */
745 break;
746 default:
747 AssertFailed();
748 break;
749 }
750 break;
751 }
752 case kDisArmv8OpParmImmRel:
753 /*case kDisParmParseImmAdr:*/
754 {
755 int32_t offDisplacement;
756
757 PUT_C('#');
758 if (pParam->fUse & DISUSE_IMMEDIATE8_REL)
759 {
760 offDisplacement = (int8_t)pParam->uValue;
761 if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
762 PUT_NUM_S8(offDisplacement);
763 }
764 else if (pParam->fUse & DISUSE_IMMEDIATE16_REL)
765 {
766 offDisplacement = (int16_t)pParam->uValue;
767 if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
768 PUT_NUM_S16(offDisplacement);
769 }
770 else
771 {
772 offDisplacement = (int32_t)pParam->uValue;
773 if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
774 PUT_NUM_S32(offDisplacement);
775 }
776 if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
777 PUT_SZ(" ; (");
778
779 RTUINTPTR uTrgAddr = pDis->uInstrAddr + offDisplacement;
780 if ( pDis->uCpuMode == DISCPUMODE_ARMV8_A32
781 || pDis->uCpuMode == DISCPUMODE_ARMV8_T32)
782 PUT_NUM_32(uTrgAddr);
783 else if (pDis->uCpuMode == DISCPUMODE_ARMV8_A64)
784 PUT_NUM_64(uTrgAddr);
785 else
786 AssertReleaseFailed();
787
788 if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
789 {
790 PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, " = ", ' ');
791 PUT_C(')');
792 }
793 else
794 PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, " (", ')');
795 break;
796 }
797 case kDisArmv8OpParmReg:
798 {
799 Assert(!(pParam->fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32)));
800
801 size_t cchReg;
802 const char *pszReg = disasmFormatArmV8Reg(pDis, &pParam->armv8.Op.Reg, &cchReg);
803 PUT_STR(pszReg, cchReg);
804 break;
805 }
806 case kDisArmv8OpParmSysReg:
807 {
808 Assert(pParam->fUse == DISUSE_REG_SYSTEM);
809
810 size_t cchReg;
811 char achTmp[32];
812 const char *pszReg = disasmFormatArmV8SysReg(pDis, pParam, &achTmp[0], &cchReg);
813 PUT_STR(pszReg, cchReg);
814 break;
815 }
816 case kDisArmv8OpParmAddrInGpr:
817 {
818 Assert( (pParam->fUse & (DISUSE_PRE_INDEXED | DISUSE_POST_INDEXED))
819 != (DISUSE_PRE_INDEXED | DISUSE_POST_INDEXED));
820 Assert( ( RT_BOOL(pParam->fUse & (DISUSE_PRE_INDEXED | DISUSE_POST_INDEXED))
821 != RT_BOOL(pParam->fUse & DISUSE_INDEX))
822 || !(pParam->fUse & (DISUSE_PRE_INDEXED | DISUSE_POST_INDEXED | DISUSE_INDEX)));
823
824 PUT_C('[');
825
826 size_t cchReg;
827 const char *pszReg = disasmFormatArmV8Reg(pDis, &pParam->armv8.Op.Reg, &cchReg);
828 PUT_STR(pszReg, cchReg);
829
830 if (pParam->fUse & DISUSE_POST_INDEXED)
831 {
832 Assert(pParam->armv8.enmExtend == kDisArmv8OpParmExtendNone);
833 PUT_SZ("], #");
834 PUT_NUM_S16(pParam->armv8.u.offBase);
835 }
836 else
837 {
838 if (pParam->fUse & DISUSE_INDEX)
839 {
840 PUT_SZ(", ");
841
842 pszReg = disasmFormatArmV8Reg(pDis, &pParam->armv8.GprIndex, &cchReg);
843 PUT_STR(pszReg, cchReg);
844 }
845 else if ( pParam->armv8.u.offBase
846 || (pParam->fUse & (DISUSE_POST_INDEXED | DISUSE_PRE_INDEXED)))
847 {
848 PUT_SZ(", #");
849 if ( pParam->armv8.u.offBase >= INT16_MIN
850 && pParam->armv8.u.offBase <= INT16_MAX)
851 PUT_NUM_S16(pParam->armv8.u.offBase);
852 else
853 PUT_NUM_S32(pParam->armv8.u.offBase);
854 }
855
856 if (pParam->armv8.enmExtend != kDisArmv8OpParmExtendNone)
857 {
858 PUT_SZ(", ");
859 switch (pParam->armv8.enmExtend)
860 {
861 case kDisArmv8OpParmExtendUxtX: /* UXTX is same as LSL which is preferred by most disassemblers/assemblers. */
862 case kDisArmv8OpParmExtendLsl:
863 PUT_SZ("LSL #");
864 break;
865 case kDisArmv8OpParmExtendUxtB: PUT_SZ("UXTB #"); break;
866 case kDisArmv8OpParmExtendUxtH: PUT_SZ("UXTH #"); break;
867 case kDisArmv8OpParmExtendUxtW: PUT_SZ("UXTW #"); break;
868 case kDisArmv8OpParmExtendSxtB: PUT_SZ("SXTB #"); break;
869 case kDisArmv8OpParmExtendSxtH: PUT_SZ("SXTH #"); break;
870 case kDisArmv8OpParmExtendSxtW: PUT_SZ("SXTW #"); break;
871 case kDisArmv8OpParmExtendSxtX: PUT_SZ("SXTX #"); break;
872 default:
873 AssertFailed();
874 }
875 PUT_NUM_8(pParam->armv8.u.cExtend);
876 }
877
878 PUT_C(']');
879
880 if (pParam->fUse & DISUSE_PRE_INDEXED)
881 PUT_C('!');
882 }
883
884 break;
885 }
886 case kDisArmv8OpParmCond:
887 {
888 Assert((uint16_t)pParam->armv8.Op.enmCond < RT_ELEMENTS(g_aszArmV8Cond));
889 PUT_STR(g_aszArmV8Cond[pParam->armv8.Op.enmCond], sizeof(g_aszArmV8Cond[0]) - 1);
890 break;
891 }
892 case kDisArmv8OpParmPState:
893 {
894 Assert((uint16_t)pParam->armv8.Op.enmPState < RT_ELEMENTS(g_apszArmV8PState));
895 PUT_PSZ(g_apszArmV8PState[pParam->armv8.Op.enmPState]);
896 break;
897 }
898 default:
899 AssertFailed();
900 }
901
902 if ( pParam->armv8.enmType != kDisArmv8OpParmAddrInGpr
903 && pParam->armv8.enmExtend != kDisArmv8OpParmExtendNone)
904 {
905 Assert( pParam->armv8.enmType == kDisArmv8OpParmImm
906 || pParam->armv8.enmType == kDisArmv8OpParmReg);
907 PUT_SZ(", ");
908 switch (pParam->armv8.enmExtend)
909 {
910 case kDisArmv8OpParmExtendLsl:
911 PUT_SZ("LSL #");
912 break;
913 case kDisArmv8OpParmExtendLsr:
914 PUT_SZ("LSR #");
915 break;
916 case kDisArmv8OpParmExtendAsr:
917 PUT_SZ("ASR #");
918 break;
919 case kDisArmv8OpParmExtendRor:
920 PUT_SZ("ROR #");
921 break;
922 case kDisArmv8OpParmExtendUxtB:
923 PUT_SZ("UXTB #");
924 break;
925 case kDisArmv8OpParmExtendUxtH:
926 PUT_SZ("UXTH #");
927 break;
928 case kDisArmv8OpParmExtendUxtW:
929 PUT_SZ("UXTW #");
930 break;
931 case kDisArmv8OpParmExtendUxtX:
932 PUT_SZ("UXTX #");
933 break;
934 case kDisArmv8OpParmExtendSxtB:
935 PUT_SZ("SXTB #");
936 break;
937 case kDisArmv8OpParmExtendSxtH:
938 PUT_SZ("SXTH #");
939 break;
940 case kDisArmv8OpParmExtendSxtW:
941 PUT_SZ("SXTW #");
942 break;
943 case kDisArmv8OpParmExtendSxtX:
944 PUT_SZ("SXTX #");
945 break;
946 default:
947 AssertFailed();
948 }
949 PUT_NUM_8(pParam->armv8.u.cExtend);
950 }
951 }
952 }
953
954 /*
955 * Any additional output to the right of the instruction?
956 */
957 if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
958 {
959 /* some up front padding. */
960 size_t cchPadding = cchOutput - offInstruction;
961 cchPadding = cchPadding + 1 >= 42 ? 1 : 42 - cchPadding;
962 PUT_STR(g_szSpaces, cchPadding);
963
964 /* comment? */
965 if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
966 PUT_SZ(";");
967
968 /*
969 * The address?
970 */
971 if (fFlags & DIS_FMT_FLAGS_ADDR_RIGHT)
972 {
973 PUT_C(' ');
974#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
975 if (pDis->uInstrAddr >= _4G)
976 PUT_NUM(9, "%08x`", (uint32_t)(pDis->uInstrAddr >> 32));
977#endif
978 PUT_NUM(8, "%08x", (uint32_t)pDis->uInstrAddr);
979 }
980
981 /*
982 * Opcode bytes?
983 */
984 if (fFlags & DIS_FMT_FLAGS_BYTES_RIGHT)
985 {
986 PUT_C(' ');
987 size_t cchTmp = disFormatBytes(pDis, pszDst, cchDst, fFlags);
988 cchOutput += cchTmp;
989 if (cchTmp >= cchDst)
990 cchTmp = cchDst - (cchDst != 0);
991 cchDst -= cchTmp;
992 pszDst += cchTmp;
993 }
994 }
995
996 /*
997 * Terminate it - on overflow we'll have reserved one byte for this.
998 */
999 if (cchDst > 0)
1000 *pszDst = '\0';
1001 else
1002 Assert(!cchBuf);
1003
1004 /* clean up macros */
1005#undef PUT_PSZ
1006#undef PUT_SZ
1007#undef PUT_STR
1008#undef PUT_C
1009 return cchOutput;
1010}
1011
1012
1013/**
1014 * Formats the current instruction in ARMv8 style.
1015 *
1016 * This is a simplified version of DISFormatArmV8Ex() provided for your convenience.
1017 *
1018 *
1019 * @returns The number of output characters. If this is >= cchBuf, then the content
1020 * of pszBuf will be truncated.
1021 * @param pDis Pointer to the disassembler state.
1022 * @param pszBuf The output buffer.
1023 * @param cchBuf The size of the output buffer.
1024 */
1025DISDECL(size_t) DISFormatArmV8(PCDISSTATE pDis, char *pszBuf, size_t cchBuf)
1026{
1027 return DISFormatArmV8Ex(pDis, pszBuf, cchBuf, 0 /* fFlags */, NULL /* pfnGetSymbol */, NULL /* pvUser */);
1028}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette