VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmTables-armv8.cpp@ 99332

Last change on this file since 99332 was 99319, checked in by vboxsync, 21 months ago

Disassember: Continue work on the ARMv8 disassember, defining the instruction table layout and intermediate structures for decoding, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1/* $Id: DisasmTables-armv8.cpp 99319 2023-04-06 19:28:23Z vboxsync $ */
2/** @file
3 * VBox disassembler - Tables for ARMv8 A64.
4 */
5
6/*
7 * Copyright (C) 2023 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 <VBox/disopcode-armv8.h>
34#include "DisasmInternal-armv8.h"
35
36
37/*********************************************************************************************************************************
38* Global Variables *
39*********************************************************************************************************************************/
40
41#define DIS_ARMV8_OP(a_szOpcode, a_uOpcode, a_fOpType) \
42 OP(a_szOpcode, 0, 0, 0, a_uOpcode, OP_ARMV8_PARM_NONE, OP_ARMV8_PARM_NONE, OP_ARMV8_PARM_NONE, a_fOpType)
43
44#ifndef DIS_CORE_ONLY
45static char g_szInvalidOpcode[] = "Invalid Opcode";
46#endif
47
48#define INVALID_OPCODE \
49 DIS_ARMV8_OP(g_szInvalidOpcode, OP_ARMV8_INVALID, DISOPTYPE_INVALID)
50
51
52/* Invalid opcode */
53DECL_HIDDEN_CONST(DISOPCODE) g_ArmV8A64InvalidOpcode[1] =
54{
55 INVALID_OPCODE
56};
57
58
59/* UDF */
60DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_aArmV8A64InsnRsvd)
61 DIS_ARMV8_OP("udf %I" , OP_ARMV8_A64_UDF, DISOPTYPE_INVALID)
62DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_aArmV8A64InsnRsvd, 0 /*fClass*/, kDisArmV8OpcDecodeNop, 0xffff0000, 16)
63 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImm, 0, 16),
64 DIS_ARMV8_INSN_PARAM_NONE,
65 DIS_ARMV8_INSN_PARAM_NONE,
66 DIS_ARMV8_INSN_PARAM_NONE
67DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
68
69
70/* ADR/ADRP */
71DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_ArmV8A64Adr)
72 DIS_ARMV8_OP("adr %X,%I" , OP_ARMV8_A64_ADR, DISOPTYPE_HARMLESS),
73 DIS_ARMV8_OP("adrp %X,%I" , OP_ARMV8_A64_ADRP, DISOPTYPE_HARMLESS)
74DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_ArmV8A64Adr, DISARMV8INSNCLASS_F_FORCED_64BIT, kDisArmV8OpcDecodeNop, RT_BIT_32(31), 31)
75 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 0, 5),
76 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImmAdr, 0, 0),
77 DIS_ARMV8_INSN_PARAM_NONE,
78 DIS_ARMV8_INSN_PARAM_NONE
79DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
80
81
82/* ADD/ADDS/SUB/SUBS */
83DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_ArmV8A64AddSubImm)
84 DIS_ARMV8_OP("add %X,%X,%I" , OP_ARMV8_A64_ADD, DISOPTYPE_HARMLESS),
85 DIS_ARMV8_OP("adds %X,%X,%I" , OP_ARMV8_A64_ADDS, DISOPTYPE_HARMLESS),
86 DIS_ARMV8_OP("sub %X,%X,%I" , OP_ARMV8_A64_SUB, DISOPTYPE_HARMLESS),
87 DIS_ARMV8_OP("subs %X,%X,%I" , OP_ARMV8_A64_SUBS, DISOPTYPE_HARMLESS),
88DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_ArmV8A64AddSubImm, DISARMV8INSNCLASS_F_SF, kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29)
89 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 0, 5),
90 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 5, 5),
91 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImm, 10, 12),
92 DIS_ARMV8_INSN_PARAM_NONE
93DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
94
95
96/* AND/ORR/EOR/ANDS */
97DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_ArmV8A64LogicalImm)
98 DIS_ARMV8_OP("and %X,%X,%I" , OP_ARMV8_A64_AND, DISOPTYPE_HARMLESS),
99 DIS_ARMV8_OP("orr %X,%X,%I" , OP_ARMV8_A64_ORR, DISOPTYPE_HARMLESS),
100 DIS_ARMV8_OP("eor %X,%X,%I" , OP_ARMV8_A64_EOR, DISOPTYPE_HARMLESS),
101 DIS_ARMV8_OP("ands %X,%X,%I" , OP_ARMV8_A64_ANDS, DISOPTYPE_HARMLESS),
102DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_ArmV8A64LogicalImm, DISARMV8INSNCLASS_F_SF, kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29)
103 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 0, 5),
104 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 5, 6),
105 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImmsImmrN, 10, 13),
106 DIS_ARMV8_INSN_PARAM_NONE
107DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
108
109
110/* MOVN/MOVZ/MOVK */
111DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_ArmV8A64MoveWide)
112 DIS_ARMV8_OP("movn %X,%I LSL %I", OP_ARMV8_A64_MOVN, DISOPTYPE_HARMLESS),
113 INVALID_OPCODE,
114 DIS_ARMV8_OP("movz %X,%I LSL %I" , OP_ARMV8_A64_MOVZ, DISOPTYPE_HARMLESS),
115 DIS_ARMV8_OP("movk %X,%I LSL %I" , OP_ARMV8_A64_MOVK, DISOPTYPE_HARMLESS),
116DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_ArmV8A64MoveWide, DISARMV8INSNCLASS_F_SF, kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29)
117 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 0, 5),
118 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImm, 5, 16),
119 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseHw, 21, 2),
120 DIS_ARMV8_INSN_PARAM_NONE
121DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
122
123
124/* SBFM/BFM/UBFM */
125DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_ArmV8A64Bitfield)
126 DIS_ARMV8_OP("sbfm %X,%X,%I", OP_ARMV8_A64_SBFM, DISOPTYPE_HARMLESS),
127 DIS_ARMV8_OP("bfm %X,%X,%I" , OP_ARMV8_A64_BFM, DISOPTYPE_HARMLESS),
128 DIS_ARMV8_OP("ubfm %X,%X,%I" , OP_ARMV8_A64_UBFM, DISOPTYPE_HARMLESS),
129 INVALID_OPCODE,
130DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_ArmV8A64Bitfield, DISARMV8INSNCLASS_F_SF | DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT,
131 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29)
132 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 0, 5),
133 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseReg, 5, 5),
134 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImmsImmrN, 10, 13),
135 DIS_ARMV8_INSN_PARAM_NONE
136DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
137
138
139/*
140 * C4.1.65 of the ARMv8 architecture reference manual has the following table for the
141 * data processing (immediate) instruction classes:
142 *
143 * Bit 25 24 23
144 * +-------------------------------------------
145 * 0 0 x PC-rel. addressing.
146 * 0 1 0 Add/subtract (immediate)
147 * 0 1 1 Add/subtract (immediate, with tags)
148 * 1 0 0 Logical (immediate)
149 * 1 0 1 Move wide (immediate)
150 * 1 1 0 Bitfield
151 * 1 1 1 Extract
152 */
153DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(g_aArmV8A64InsnDataProcessingImm)
154 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64Adr),
155 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64Adr),
156 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64AddSubImm),
157 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Add/subtract immediate with tags. */
158 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64LogicalImm),
159 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64MoveWide),
160 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64Bitfield),
161 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY /** @todo Extract */
162DIS_ARMV8_DECODE_MAP_DEFINE_END(g_aArmV8A64InsnDataProcessingImm, RT_BIT_32(23) | RT_BIT_32(24) | RT_BIT_32(25), 23);
163
164
165/* B.cond/BC.cond */
166DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(g_ArmV8A64CondBr)
167 DIS_ARMV8_OP("b.%C %J", OP_ARMV8_A64_B, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW),
168 DIS_ARMV8_OP("bc.%C %J" , OP_ARMV8_A64_BC, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW),
169DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(g_ArmV8A64CondBr, 0 /*fClass*/,
170 kDisArmV8OpcDecodeNop, RT_BIT_32(4), 4)
171 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseCond, 0, 4),
172 DIS_ARMV8_INSN_PARAM_CREATE(kDisParmParseImmRel, 5, 19),
173 DIS_ARMV8_INSN_PARAM_NONE,
174 DIS_ARMV8_INSN_PARAM_NONE
175DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END;
176
177
178DIS_ARMV8_DECODE_TBL_DEFINE_BEGIN(g_ArmV8A64BrExcpSys)
179 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xff000000, RT_BIT_32(26) | RT_BIT_32(28) | RT_BIT_32(30), g_ArmV8A64CondBr) /* op0: 010, op1: 0xxxxxxxxxxxxx, op2: - (including o1 from the conditional branch (immediate) class to save us one layer). */
180DIS_ARMV8_DECODE_TBL_DEFINE_END(g_ArmV8A64BrExcpSys);
181
182
183/*
184 * C4.1 of the ARMv8 architecture reference manual has the following table for the
185 * topmost decoding level (Level 0 in our terms), x means don't care:
186 *
187 * Bit 28 27 26 25
188 * +-------------------------------------------
189 * 0 0 0 0 Reserved or SME encoding (depends on bit 31).
190 * 0 0 0 1 UNALLOC
191 * 0 0 1 0 SVE encodings
192 * 0 0 1 1 UNALLOC
193 * 1 0 0 x Data processing immediate
194 * 1 0 1 x Branch, exception generation and system instructions
195 * x 1 x 0 Loads and stores
196 * x 1 0 1 Data processing - register
197 * x 1 1 1 Data processing - SIMD and floating point
198 *
199 * In order to save us some fiddling with the don't care bits we blow up the lookup table
200 * which gives us 16 possible values (4 bits) we can use as an index into the decoder
201 * lookup table for the next level:
202 * Bit 28 27 26 25
203 * +-------------------------------------------
204 * 0 0 0 0 0 Reserved or SME encoding (depends on bit 31).
205 * 1 0 0 0 1 UNALLOC
206 * 2 0 0 1 0 SVE encodings
207 * 3 0 0 1 1 UNALLOC
208 * 4 0 1 0 0 Loads and stores
209 * 5 0 1 0 1 Data processing - register
210 * 6 0 1 1 0 Loads and stores
211 * 7 0 1 1 1 Data processing - SIMD and floating point
212 * 8 1 0 0 0 Data processing immediate
213 * 9 1 0 0 1 Data processing immediate
214 * 10 1 0 1 0 Branch, exception generation and system instructions
215 * 11 1 0 1 1 Branch, exception generation and system instructions
216 * 12 1 1 0 0 Loads and stores
217 * 13 1 1 0 1 Data processing - register
218 * 14 1 1 1 0 Loads and stores
219 * 15 1 1 1 1 Data processing - SIMD and floating point
220 */
221DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(g_ArmV8A64DecodeL0)
222 DIS_ARMV8_DECODE_MAP_ENTRY(g_aArmV8A64InsnRsvd), /* Reserved class or SME encoding (@todo). */
223 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Unallocated */
224 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo SVE */
225 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Unallocated */
226 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Load/Stores */
227 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Data processing (register). */
228 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Lod/Stores */
229 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Data processing (SIMD & FP) */
230 DIS_ARMV8_DECODE_MAP_ENTRY(g_aArmV8A64InsnDataProcessingImm), /* Data processing (immediate). */
231 DIS_ARMV8_DECODE_MAP_ENTRY(g_aArmV8A64InsnDataProcessingImm), /* Data processing (immediate). */
232 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64BrExcpSys), /* Branches / Exception generation and system instructions. */
233 DIS_ARMV8_DECODE_MAP_ENTRY(g_ArmV8A64BrExcpSys), /* Branches / Exception generation and system instructions. */
234 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Load/Stores. */
235 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Data processing (register). */
236 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Load/Stores. */
237 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY /* Data processing (SIMD & FP). */
238DIS_ARMV8_DECODE_MAP_DEFINE_END_NON_STATIC(g_ArmV8A64DecodeL0, RT_BIT_32(25) | RT_BIT_32(26) | RT_BIT_32(27) | RT_BIT_32(28), 25);
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