VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmInternal-armv8.h@ 106724

Last change on this file since 106724 was 106649, checked in by vboxsync, 4 weeks ago

Disassembler: Decode more branch instructions, change the opcode table format again to have the decoder steps set the appropriate parameter types instead of hardcoding them in the instruction class table (required for retaa/retab which don't take a register parameter as opposed to ret, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: DisasmInternal-armv8.h 106649 2024-10-24 09:28:23Z vboxsync $ */
2/** @file
3 * VBox disassembler - Internal header.
4 */
5
6/*
7 * Copyright (C) 2023-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#ifndef VBOX_INCLUDED_SRC_DisasmInternal_armv8_h
29#define VBOX_INCLUDED_SRC_DisasmInternal_armv8_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/types.h>
35#include <VBox/err.h>
36#include <VBox/dis.h>
37#include <VBox/log.h>
38
39#include <iprt/param.h>
40#include "DisasmInternal.h"
41
42
43/** @addtogroup grp_dis_int Internals.
44 * @ingroup grp_dis
45 * @{
46 */
47
48/** @name Index into g_apfnFullDisasm.
49 * @{ */
50typedef enum DISPARMPARSEIDX
51{
52 kDisParmParseNop = 0,
53 kDisParmParseSize,
54 kDisParmParseImm,
55 kDisParmParseImmRel,
56 kDisParmParseImmAdr,
57 kDisParmParseImmZero,
58 kDisParmParseGprZr,
59 kDisParmParseGprZr32,
60 kDisParmParseGprZr64,
61 kDisParmParseGprSp,
62 kDisParmParseGprOff,
63 kDisParmParseAddrGprSp,
64 kDisParmParseRegFixed31,
65 kDisParmParseImmsImmrN,
66 kDisParmParseHw,
67 kDisParmParseCond,
68 kDisParmParsePState,
69 kDisParmParseCRnCRm,
70 kDisParmParseSysReg,
71 kDisParmParseSh12,
72 kDisParmParseImmTbz,
73 kDisParmParseShift,
74 kDisParmParseShiftAmount,
75 kDisParmParseImmMemOff,
76 kDisParmParseSImmMemOff,
77 kDisParmParseSImmMemOffUnscaled,
78 kDisParmParseOption,
79 kDisParmParseS,
80 kDisParmParseSetPreIndexed,
81 kDisParmParseSetPostIndexed,
82 kDisParmParseFpType,
83 kDisParmParseFpReg,
84 kDisParmParseFpScale,
85 kDisParmParseFpFixupFCvt,
86 kDisParmParseSimdRegScalar,
87 kDisParmParseImmHImmB,
88 kDisParmParseSf,
89 kDisParmParseMax
90} DISPARMPARSEIDX;
91/** @} */
92
93
94/**
95 * Decoder step.
96 */
97typedef struct DISARMV8INSNPARAM
98{
99 /** The parser to use for the decode step. */
100 DISPARMPARSEIDX idxParse;
101 /** Bit index at which the field starts. */
102 uint8_t idxBitStart;
103 /** Size of the bit field. */
104 uint8_t cBits;
105 /** The parameter this decoder param contributes to. */
106 uint8_t idxParam;
107} DISARMV8INSNPARAM;
108typedef DISARMV8INSNPARAM *PDISARMV8INSNPARAM;
109typedef const DISARMV8INSNPARAM *PCDISARMV8INSNPARAM;
110
111#define DIS_ARMV8_INSN_DECODE_TERM { kDisParmParseNop, 0, 0, DIS_ARMV8_INSN_PARAM_UNSET }
112#define DIS_ARMV8_INSN_DECODE(a_idxParse, a_idxBitStart, a_cBits, a_idxParam) \
113 { a_idxParse, a_idxBitStart, a_cBits, a_idxParam }
114
115#define DIS_ARMV8_INSN_PARAM_UNSET UINT8_MAX
116
117
118/**
119 * Opcode structure.
120 */
121typedef struct DISARMV8OPCODE
122{
123 /** The value of the fixed bits of the instruction. */
124 uint32_t fValue;
125 /** Special flags for the opcode. */
126 uint32_t fFlags;
127 /** Pointer to an alternative decoder overriding the default one for the instruction class. */
128 PCDISARMV8INSNPARAM paDecode;
129 /** The generic opcode structure. */
130 DISOPCODE Opc;
131} DISARMV8OPCODE;
132/** Pointer to a const opcode. */
133typedef const DISARMV8OPCODE *PCDISARMV8OPCODE;
134
135
136/**
137 * Opcode decode index.
138 */
139typedef enum DISARMV8OPCDECODE
140{
141 kDisArmV8OpcDecodeNop = 0,
142 kDisArmV8OpcDecodeLookup,
143 kDisArmV8OpcDecodeCollate,
144 kDisArmV8OpcDecodeMax
145} DISARMV8OPCDECODE;
146
147
148/**
149 * Decoder stage type.
150 */
151typedef enum kDisArmV8DecodeType
152{
153 kDisArmV8DecodeType_Invalid = 0,
154 kDisArmV8DecodeType_Map,
155 kDisArmV8DecodeType_Table,
156 kDisArmV8DecodeType_InsnClass,
157 kDisArmV8DecodeType_32Bit_Hack = 0x7fffffff
158} kDisArmV8DecodeType;
159
160
161/**
162 * Decode header.
163 */
164typedef struct DISARMV8DECODEHDR
165{
166 /** Next stage decoding type. */
167 kDisArmV8DecodeType enmDecodeType;
168 /** Number of entries in the next decoder stage or
169 * opcodes in the instruction class. */
170 uint32_t cDecode;
171} DISARMV8DECODEHDR;
172/** Pointer to a decode header. */
173typedef DISARMV8DECODEHDR *PDISARMV8DECODEHDR;
174/** Pointer to a const decode header. */
175typedef const DISARMV8DECODEHDR *PCDISARMV8DECODEHDR;
176typedef const PCDISARMV8DECODEHDR *PPCDISARMV8DECODEHDR;
177
178
179/**
180 * Instruction class descriptor.
181 */
182typedef struct DISARMV8INSNCLASS
183{
184 /** Decoder header. */
185 DISARMV8DECODEHDR Hdr;
186 /** Pointer to the arry of opcodes. */
187 PCDISARMV8OPCODE paOpcodes;
188 /** The mask of fixed instruction bits. */
189 uint32_t fFixedInsn;
190 /** Opcode decoder function. */
191 DISARMV8OPCDECODE enmOpcDecode;
192 /** The mask of the bits relevant for decoding. */
193 uint32_t fMask;
194 /** Number of bits to shift to get an index. */
195 uint32_t cShift;
196 /** The array of decoding steps. */
197 PCDISARMV8INSNPARAM paParms;
198} DISARMV8INSNCLASS;
199/** Pointer to a constant instruction class descriptor. */
200typedef const DISARMV8INSNCLASS *PCDISARMV8INSNCLASS;
201
202/** The N bit in an N:ImmR:ImmS bit vector must be 1 for 64-bit instruction variants. */
203#define DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT RT_BIT_32(1)
204/** The instruction class is using the 64-bit register encoding only. */
205#define DISARMV8INSNCLASS_F_FORCED_64BIT RT_BIT_32(2)
206/** The instruction class is using the 32-bit register encoding only. */
207#define DISARMV8INSNCLASS_F_FORCED_32BIT RT_BIT_32(3)
208
209
210#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(a_Name) \
211 static const DISARMV8INSNPARAM g_aArmV8A64Insn ## a_Name ## Decode[] = {
212#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER_ALTERNATIVE(a_Name) \
213 DIS_ARMV8_INSN_DECODE_TERM \
214 }; \
215 static const DISARMV8INSNPARAM g_aArmV8A64Insn ## a_Name ## Decode[] = {
216#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(a_Name) \
217 DIS_ARMV8_INSN_DECODE_TERM \
218 }; \
219 static const DISARMV8OPCODE g_aArmV8A64Insn ## a_Name ## Opcodes[] = {
220#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END(a_Name, a_fFixedInsn, a_enmOpcDecode, a_fMask, a_cShift) \
221 }; \
222 static const DISARMV8INSNCLASS g_aArmV8A64Insn ## a_Name = { { kDisArmV8DecodeType_InsnClass, \
223 RT_ELEMENTS(g_aArmV8A64Insn ## a_Name ## Opcodes) }, \
224 & g_aArmV8A64Insn ## a_Name ## Opcodes[0], \
225 a_fFixedInsn, a_enmOpcDecode, a_fMask, a_cShift, \
226 & g_aArmV8A64Insn ## a_Name ## Decode[0] }
227
228/**
229 * Decoder lookup table entry.
230 */
231typedef struct DISARMV8DECODETBLENTRY
232{
233 /** The mask to apply to the instruction. */
234 uint32_t fMask;
235 /** The value the masked instruction must match for the entry to match. */
236 uint32_t fValue;
237 /** The next stage followed when there is a match. */
238 PCDISARMV8DECODEHDR pHdrNext;
239} DISARMV8DECODETBLENTRY;
240typedef struct DISARMV8DECODETBLENTRY *PDISARMV8DECODETBLENTRY;
241typedef const DISARMV8DECODETBLENTRY *PCDISARMV8DECODETBLENTRY;
242
243
244#define DIS_ARMV8_DECODE_TBL_ENTRY_INIT(a_fMask, a_fValue, a_pNext) \
245 { a_fMask, a_fValue, & g_aArmV8A64Insn ## a_pNext.Hdr }
246
247
248/**
249 * Decoder lookup table using masks and values.
250 */
251typedef struct DISARMV8DECODETBL
252{
253 /** The header for the decoder lookup table. */
254 DISARMV8DECODEHDR Hdr;
255 /** Pointer to the individual entries. */
256 PCDISARMV8DECODETBLENTRY paEntries;
257} DISARMV8DECODETBL;
258/** Pointer to a const decode table. */
259typedef const struct DISARMV8DECODETBL *PCDISARMV8DECODETBL;
260
261
262#define DIS_ARMV8_DECODE_TBL_DEFINE_BEGIN(a_Name) \
263 static const DISARMV8DECODETBLENTRY g_aArmV8A64Insn ## a_Name ## TblEnt[] = {
264
265#define DIS_ARMV8_DECODE_TBL_DEFINE_END(a_Name) \
266 }; \
267 static const DISARMV8DECODETBL g_aArmV8A64Insn ## a_Name = { { kDisArmV8DecodeType_Table, RT_ELEMENTS(g_aArmV8A64Insn ## a_Name ## TblEnt) }, \
268 & g_aArmV8A64Insn ## a_Name ## TblEnt[0] }
269
270
271/**
272 * Decoder map when direct indexing is possible.
273 */
274typedef struct DISARMV8DECODEMAP
275{
276 /** The header for the decoder map. */
277 DISARMV8DECODEHDR Hdr;
278 /** The bitmask used to decide where to go next. */
279 uint32_t fMask;
280 /** Amount to shift to get at the index. */
281 uint32_t cShift;
282 /** Pointer to the array of pointers to the next stage to index into. */
283 PPCDISARMV8DECODEHDR papNext;
284} DISARMV8DECODEMAP;
285/** Pointer to a const decode map. */
286typedef const struct DISARMV8DECODEMAP *PCDISARMV8DECODEMAP;
287
288#define DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(a_Name) \
289 static const PCDISARMV8DECODEHDR g_aArmV8A64Insn ## a_Name ## MapHdrs[] = {
290
291#define DIS_ARMV8_DECODE_MAP_DEFINE_END(a_Name, a_fMask, a_cShift) \
292 }; \
293 static const DISARMV8DECODEMAP g_aArmV8A64Insn ## a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(g_aArmV8A64Insn ## a_Name ## MapHdrs) }, \
294 a_fMask, a_cShift, & g_aArmV8A64Insn ## a_Name ## MapHdrs[0] }
295
296#define DIS_ARMV8_DECODE_MAP_DEFINE_END_SINGLE_BIT(a_Name, a_idxBit) \
297 }; \
298 static const DISARMV8DECODEMAP g_aArmV8A64Insn ## a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(g_aArmV8A64Insn ## a_Name ## MapHdrs) }, \
299 RT_BIT_32(a_idxBit), a_idxBit, & g_aArmV8A64Insn ## a_Name ## MapHdrs[0] }
300
301
302#define DIS_ARMV8_DECODE_MAP_DEFINE_END_NON_STATIC(a_Name, a_fMask, a_cShift) \
303 }; \
304 DECL_HIDDEN_CONST(DISARMV8DECODEMAP) g_aArmV8A64Insn ## a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(g_aArmV8A64Insn ## a_Name ## MapHdrs) }, \
305 a_fMask, a_cShift, & g_aArmV8A64Insn ## a_Name ## MapHdrs[0] }
306
307#define DIS_ARMV8_DECODE_MAP_INVALID_ENTRY NULL
308#define DIS_ARMV8_DECODE_MAP_ENTRY(a_Next) & g_aArmV8A64Insn ## a_Next.Hdr
309
310
311/** @name Decoder maps.
312 * @{ */
313extern DECL_HIDDEN_DATA(DISOPCODE) g_ArmV8A64InvalidOpcode[1];
314
315extern DECL_HIDDEN_DATA(DISARMV8DECODEMAP) g_aArmV8A64InsnDecodeL0;
316/** @} */
317
318
319/** @} */
320#endif /* !VBOX_INCLUDED_SRC_DisasmInternal_armv8_h */
321
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