VirtualBox

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

Last change on this file since 106432 was 106004, checked in by vboxsync, 6 months ago

Disassembler/ArmV8: Updates and start on floating point and SIMD instructions, bugref:10394

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