VirtualBox

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

Last change on this file since 106387 was 106387, checked in by vboxsync, 6 weeks ago

Disassembler: Disassemble dsb instruction, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 56.8 KB
Line 
1/* $Id: DisasmTables-armv8-a64.cpp 106387 2024-10-16 14:15:57Z vboxsync $ */
2/** @file
3 * VBox disassembler - Tables for ARMv8 A64.
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
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_fValue, a_szOpcode, a_uOpcode, a_fOpType) \
42 { a_fValue, 0, OP(a_szOpcode, 0, 0, 0, a_uOpcode, 0, 0, 0, a_fOpType) }
43#define DIS_ARMV8_OP_EX(a_fValue, a_szOpcode, a_uOpcode, a_fOpType, a_fFlags) \
44 { a_fValue, a_fFlags, OP(a_szOpcode, 0, 0, 0, a_uOpcode, 0, 0, 0, a_fOpType) }
45
46#ifndef DIS_CORE_ONLY
47static char g_szInvalidOpcode[] = "Invalid Opcode";
48#endif
49
50#define INVALID_OPCODE \
51 DIS_ARMV8_OP(0, g_szInvalidOpcode, OP_ARMV8_INVALID, DISOPTYPE_INVALID)
52
53
54/* Invalid opcode */
55DECL_HIDDEN_CONST(DISOPCODE) g_ArmV8A64InvalidOpcode[1] =
56{
57 OP(g_szInvalidOpcode, 0, 0, 0, 0, 0, 0, 0, DISOPTYPE_INVALID)
58};
59
60
61/* Include the secondary tables. */
62#include "DisasmTables-armv8-a64-simd-fp.cpp.h"
63
64/* UDF */
65DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Rsvd)
66 DIS_ARMV8_OP(0x00000000, "udf" , OP_ARMV8_A64_UDF, DISOPTYPE_INVALID)
67DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Rsvd)
68 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 0, 16, 0 /*idxParam*/),
69DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(Rsvd, 0xffff0000 /*fFixedInsn*/, 0 /*fClass*/,
70 kDisArmV8OpcDecodeNop, 0xffff0000, 16,
71 kDisArmv8OpParmImm);
72
73/* ADR/ADRP */
74DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Adr)
75 DIS_ARMV8_OP(0x10000000, "adr" , OP_ARMV8_A64_ADR, DISOPTYPE_HARMLESS),
76 DIS_ARMV8_OP(0x90000000, "adrp" , OP_ARMV8_A64_ADRP, DISOPTYPE_HARMLESS)
77DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Adr)
78 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
79 DIS_ARMV8_INSN_DECODE(kDisParmParseImmAdr, 0, 0, 1 /*idxParam*/),
80DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(Adr, 0x9f000000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
81 kDisArmV8OpcDecodeNop, RT_BIT_32(31), 31,
82 kDisArmv8OpParmReg, kDisArmv8OpParmImmRel);
83
84
85/* ADD/ADDS/SUB/SUBS - shifted immediate variant */
86DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(AddSubImm)
87 DIS_ARMV8_OP(0x11000000, "add" , OP_ARMV8_A64_ADD, DISOPTYPE_HARMLESS),
88 DIS_ARMV8_OP(0x31000000, "adds" , OP_ARMV8_A64_ADDS, DISOPTYPE_HARMLESS),
89 DIS_ARMV8_OP(0x51000000, "sub" , OP_ARMV8_A64_SUB, DISOPTYPE_HARMLESS),
90 DIS_ARMV8_OP(0x71000000, "subs" , OP_ARMV8_A64_SUBS, DISOPTYPE_HARMLESS),
91DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(AddSubImm)
92 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
93 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
94 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 10, 12, 2 /*idxParam*/),
95 DIS_ARMV8_INSN_DECODE(kDisParmParseSh12, 22, 1, 2 /*idxParam*/),
96DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(AddSubImm, 0x7f800000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
97 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
98 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmImm);
99
100
101/* ADD/ADDS/SUB/SUBS - shifted register variant */
102DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(AddSubShiftReg)
103 DIS_ARMV8_OP(0x0b000000, "add" , OP_ARMV8_A64_ADD, DISOPTYPE_HARMLESS),
104 DIS_ARMV8_OP(0x2b000000, "adds" , OP_ARMV8_A64_ADDS, DISOPTYPE_HARMLESS),
105 DIS_ARMV8_OP(0x4b000000, "sub" , OP_ARMV8_A64_SUB, DISOPTYPE_HARMLESS),
106 DIS_ARMV8_OP(0x6b000000, "subs" , OP_ARMV8_A64_SUBS, DISOPTYPE_HARMLESS),
107DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(AddSubShiftReg)
108 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
109 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
110 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 16, 5, 2 /*idxParam*/),
111 DIS_ARMV8_INSN_DECODE(kDisParmParseShift, 22, 2, 2 /*idxParam*/),
112 DIS_ARMV8_INSN_DECODE(kDisParmParseShiftAmount, 10, 6, 2 /*idxParam*/),
113DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(AddSubShiftReg, 0x7f200000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
114 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
115 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmReg);
116
117
118/* AND/ORR/EOR/ANDS */
119DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LogicalImm)
120 DIS_ARMV8_OP(0x12000000, "and" , OP_ARMV8_A64_AND, DISOPTYPE_HARMLESS),
121 DIS_ARMV8_OP(0x32000000, "orr" , OP_ARMV8_A64_ORR, DISOPTYPE_HARMLESS),
122 DIS_ARMV8_OP(0x52000000, "eor" , OP_ARMV8_A64_EOR, DISOPTYPE_HARMLESS),
123 DIS_ARMV8_OP(0x72000000, "ands" , OP_ARMV8_A64_ANDS, DISOPTYPE_HARMLESS),
124DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LogicalImm)
125 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
126 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
127 DIS_ARMV8_INSN_DECODE(kDisParmParseImmsImmrN, 10, 13, 2 /*idxParam*/),
128DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(LogicalImm, 0x7f800000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
129 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
130 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmImm);
131
132
133/* MOVN/MOVZ/MOVK */
134DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(MoveWide)
135 DIS_ARMV8_OP(0x12800000, "movn", OP_ARMV8_A64_MOVN, DISOPTYPE_HARMLESS),
136 INVALID_OPCODE,
137 DIS_ARMV8_OP(0x52800000, "movz" , OP_ARMV8_A64_MOVZ, DISOPTYPE_HARMLESS),
138 DIS_ARMV8_OP(0x72800000, "movk" , OP_ARMV8_A64_MOVK, DISOPTYPE_HARMLESS),
139DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(MoveWide)
140 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
141 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 5, 16, 1 /*idxParam*/),
142 DIS_ARMV8_INSN_DECODE(kDisParmParseHw, 21, 2, 1 /*idxParam*/),
143DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(MoveWide, 0x7f800000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
144 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
145 kDisArmv8OpParmReg, kDisArmv8OpParmImm);
146
147
148/* SBFM/BFM/UBFM */
149DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Bitfield)
150 DIS_ARMV8_OP(0x13000000, "sbfm", OP_ARMV8_A64_SBFM, DISOPTYPE_HARMLESS),
151 DIS_ARMV8_OP(0x33000000, "bfm", OP_ARMV8_A64_BFM, DISOPTYPE_HARMLESS),
152 DIS_ARMV8_OP(0x53000000, "ubfm", OP_ARMV8_A64_UBFM, DISOPTYPE_HARMLESS),
153 INVALID_OPCODE,
154DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Bitfield)
155 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
156 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
157 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 16, 6, 2 /*idxParam*/),
158 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 10, 6, 3 /*idxParam*/),
159DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_4(Bitfield, 0x7f800000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF | DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT,
160 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
161 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmImm, kDisArmv8OpParmImm);
162
163
164/*
165 * C4.1.65 of the ARMv8 architecture reference manual has the following table for the
166 * data processing (immediate) instruction classes:
167 *
168 * Bit 25 24 23
169 * +-------------------------------------------
170 * 0 0 x PC-rel. addressing.
171 * 0 1 0 Add/subtract (immediate)
172 * 0 1 1 Add/subtract (immediate, with tags)
173 * 1 0 0 Logical (immediate)
174 * 1 0 1 Move wide (immediate)
175 * 1 1 0 Bitfield
176 * 1 1 1 Extract
177 */
178DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(DataProcessingImm)
179 DIS_ARMV8_DECODE_MAP_ENTRY(Adr),
180 DIS_ARMV8_DECODE_MAP_ENTRY(Adr),
181 DIS_ARMV8_DECODE_MAP_ENTRY(AddSubImm),
182 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Add/subtract immediate with tags. */
183 DIS_ARMV8_DECODE_MAP_ENTRY(LogicalImm),
184 DIS_ARMV8_DECODE_MAP_ENTRY(MoveWide),
185 DIS_ARMV8_DECODE_MAP_ENTRY(Bitfield),
186 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY /** @todo Extract */
187DIS_ARMV8_DECODE_MAP_DEFINE_END(DataProcessingImm, RT_BIT_32(23) | RT_BIT_32(24) | RT_BIT_32(25), 23);
188
189
190/* B.cond/BC.cond */
191DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(CondBr)
192 DIS_ARMV8_OP(0x54000000, "b", OP_ARMV8_A64_B, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW),
193 DIS_ARMV8_OP(0x54000010, "bc" , OP_ARMV8_A64_BC, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW),
194DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(CondBr)
195 DIS_ARMV8_INSN_DECODE(kDisParmParseCond, 0, 4, DIS_ARMV8_INSN_PARAM_UNSET),
196 DIS_ARMV8_INSN_DECODE(kDisParmParseImmRel, 5, 19, 0 /*idxParam*/),
197DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(CondBr, 0xff000010 /*fFixedInsn*/, 0 /*fClass*/,
198 kDisArmV8OpcDecodeNop, RT_BIT_32(4), 4,
199 kDisArmv8OpParmImmRel);
200
201
202/* SVC/HVC/SMC/BRK/HLT/TCANCEL/DCPS1/DCPS2/DCPS3 */
203DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Excp)
204 DIS_ARMV8_OP(0xd4000001, "svc", OP_ARMV8_A64_SVC, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT),
205 DIS_ARMV8_OP(0xd4000002, "hvc", OP_ARMV8_A64_HVC, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT | DISOPTYPE_PRIVILEGED),
206 DIS_ARMV8_OP(0xd4000003, "smc", OP_ARMV8_A64_SMC, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT | DISOPTYPE_PRIVILEGED),
207 DIS_ARMV8_OP(0xd4200000, "brk", OP_ARMV8_A64_BRK, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT),
208 DIS_ARMV8_OP(0xd4400000, "hlt", OP_ARMV8_A64_HLT, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT),
209 DIS_ARMV8_OP(0xd4600000, "tcancel", OP_ARMV8_A64_TCANCEL, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT), /* FEAT_TME */
210 DIS_ARMV8_OP(0xd4a00001, "dcps1", OP_ARMV8_A64_DCPS1, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT),
211 DIS_ARMV8_OP(0xd4a00002, "dcps2", OP_ARMV8_A64_DCPS2, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT),
212 DIS_ARMV8_OP(0xd4a00003, "dcps3", OP_ARMV8_A64_DCPS3, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INTERRUPT),
213DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Excp)
214 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 5, 16, 0 /*idxParam*/),
215DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(Excp, 0xffe0001f /*fFixedInsn*/, 0 /*fClass*/,
216 kDisArmV8OpcDecodeLookup, 0xffe0001f, 0,
217 kDisArmv8OpParmImm);
218
219
220/* WFET/WFIT */
221DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(SysReg)
222 DIS_ARMV8_OP(0xd5031000, "wfet", OP_ARMV8_A64_WFET, DISOPTYPE_HARMLESS), /* FEAT_WFxT */
223 DIS_ARMV8_OP(0x54000010, "wfit" , OP_ARMV8_A64_WFIT, DISOPTYPE_HARMLESS), /* FEAT_WFxT */
224DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(SysReg)
225 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
226DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(SysReg, 0xffffffe0 /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
227 kDisArmV8OpcDecodeNop, 0xfe0, 5,
228 kDisArmv8OpParmReg);
229
230
231/* Various hint instructions */
232DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Hints)
233 DIS_ARMV8_OP(0xd503201f, "nop", OP_ARMV8_A64_NOP, DISOPTYPE_HARMLESS),
234 DIS_ARMV8_OP(0xd503203f, "yield", OP_ARMV8_A64_YIELD, DISOPTYPE_HARMLESS),
235 DIS_ARMV8_OP(0xd503205f, "wfe", OP_ARMV8_A64_WFE, DISOPTYPE_HARMLESS),
236 DIS_ARMV8_OP(0xd503207f, "wfi", OP_ARMV8_A64_WFI, DISOPTYPE_HARMLESS),
237 DIS_ARMV8_OP(0xd503209f, "sev", OP_ARMV8_A64_SEV, DISOPTYPE_HARMLESS),
238 DIS_ARMV8_OP(0xd50320bf, "sevl", OP_ARMV8_A64_SEVL, DISOPTYPE_HARMLESS),
239 DIS_ARMV8_OP(0xd50320df, "dgh", OP_ARMV8_A64_DGH, DISOPTYPE_HARMLESS), /* FEAT_DGH */
240 DIS_ARMV8_OP(0xd50320ff, "xpaclri", OP_ARMV8_A64_XPACLRI, DISOPTYPE_HARMLESS), /* FEAT_PAuth */
241 /** @todo */
242DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Hints)
243DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_0(Hints, 0xffffffff /*fFixedInsn*/, 0 /*fClass*/,
244 kDisArmV8OpcDecodeNop, 0xfe0, 5);
245
246
247/* CLREX */
248DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(DecBarriers)
249 INVALID_OPCODE,
250 INVALID_OPCODE,
251 DIS_ARMV8_OP(0xd503304f, "clrex", OP_ARMV8_A64_CLREX, DISOPTYPE_HARMLESS),
252 INVALID_OPCODE,
253 DIS_ARMV8_OP(0xD503309f, "dsb", OP_ARMV8_A64_DSB, DISOPTYPE_HARMLESS),
254 DIS_ARMV8_OP(0xd50330bf, "dmb", OP_ARMV8_A64_DMB, DISOPTYPE_HARMLESS),
255DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(DecBarriers)
256 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 8, 4, 0 /*idxParam*/),
257DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(DecBarriers, 0xfffff0ff /*fFixedInsn*/, 0 /*fClass*/,
258 kDisArmV8OpcDecodeNop, RT_BIT_32(5) | RT_BIT_32(6) | RT_BIT_32(7), 5,
259 kDisArmv8OpParmImm);
260
261
262/* Barrier instructions, we divide these instructions further based on the op2 field. */
263DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(DecodeBarriers)
264 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
265 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo DSB - Encoding */
266 DIS_ARMV8_DECODE_MAP_ENTRY(DecBarriers), /* CLREX */
267 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo TCOMMIT */
268 DIS_ARMV8_DECODE_MAP_ENTRY(DecBarriers), /* DSB - Encoding */
269 DIS_ARMV8_DECODE_MAP_ENTRY(DecBarriers), /* DMB */
270 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo ISB */
271 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY /** @todo SB */
272DIS_ARMV8_DECODE_MAP_DEFINE_END(DecodeBarriers, RT_BIT_32(5) | RT_BIT_32(6) | RT_BIT_32(7), 5);
273
274
275/* MSR (and potentially CFINV,XAFLAG,AXFLAG) */
276DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(PState)
277 DIS_ARMV8_OP(0xd500401f, "msr", OP_ARMV8_A64_MSR, DISOPTYPE_HARMLESS),
278DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(PState)
279 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 8, 4, 1 /*idxParam*/), /* CRm field encodes the immediate value, gets validated by the next decoder stage. */
280 DIS_ARMV8_INSN_DECODE(kDisParmParsePState, 0, 0, 0 /*idxParam*/), /* This is special for the MSR instruction. */
281DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(PState, 0xfff8f01f /*fFixedInsn*/, 0 /*fClass*/,
282 kDisArmV8OpcDecodeNop, 0, 0,
283 kDisArmv8OpParmPState, kDisArmv8OpParmImm);
284
285
286/* TSTART/TTEST */
287DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(SysResult)
288 DIS_ARMV8_OP(0xd5233060, "tstart", OP_ARMV8_A64_TSTART, DISOPTYPE_HARMLESS | DISOPTYPE_PRIVILEGED), /* FEAT_TME */
289 DIS_ARMV8_OP(0xd5233160, "ttest", OP_ARMV8_A64_TTEST, DISOPTYPE_HARMLESS), /* FEAT_TME */
290DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(SysResult)
291 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
292DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(SysResult, 0xfffffffe /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
293 kDisArmV8OpcDecodeNop, RT_BIT_32(8) | RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11), 8,
294 kDisArmv8OpParmReg);
295
296
297/* SYS */
298DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Sys)
299 DIS_ARMV8_OP(0xd5080000, "sys", OP_ARMV8_A64_SYS, DISOPTYPE_HARMLESS),
300DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Sys)
301 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 16, 3, 0 /*idxParam*/),
302 DIS_ARMV8_INSN_DECODE(kDisParmParseCRnCRm, 8, 8, 1 /*idxParam*/),
303 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 5, 3, 2 /*idxParam*/),
304 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 3 /*idxParam*/),
305DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_0(Sys, 0xfff80000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
306 kDisArmV8OpcDecodeNop, 0, 0); /** @todo */
307
308
309/* SYSL */
310DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(SysL)
311 DIS_ARMV8_OP(0xd5280000, "sysl", OP_ARMV8_A64_SYSL, DISOPTYPE_HARMLESS),
312DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(SysL)
313 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
314 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 16, 3, 1 /*idxParam*/),
315 DIS_ARMV8_INSN_DECODE(kDisParmParseCRnCRm, 8, 8, 2 /*idxParam*/),
316 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 5, 3, 3 /*idxParam*/),
317DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_0(SysL, 0xfff80000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
318 kDisArmV8OpcDecodeNop, 0, 0); /** @todo */
319
320
321/* MSR */
322DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Msr)
323 DIS_ARMV8_OP(0xd5100000, "msr", OP_ARMV8_A64_MSR, DISOPTYPE_HARMLESS | DISOPTYPE_PRIVILEGED),
324DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Msr)
325 DIS_ARMV8_INSN_DECODE(kDisParmParseSysReg, 5, 15, 0 /*idxParam*/),
326 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 1 /*idxParam*/),
327DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(Msr, 0xfff00000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
328 kDisArmV8OpcDecodeNop, 0, 0,
329 kDisArmv8OpParmSysReg, kDisArmv8OpParmReg);
330
331
332/* MRS */
333DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(Mrs)
334 DIS_ARMV8_OP(0xd5300000, "mrs", OP_ARMV8_A64_MRS, DISOPTYPE_HARMLESS | DISOPTYPE_PRIVILEGED),
335DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(Mrs)
336 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
337 DIS_ARMV8_INSN_DECODE(kDisParmParseSysReg, 5, 15, 1 /*idxParam*/),
338DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(Mrs, 0xfff00000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
339 kDisArmV8OpcDecodeNop, 0, 0,
340 kDisArmv8OpParmReg, kDisArmv8OpParmSysReg);
341
342
343/* BR/BRAA/BRAAZ/BRAB/BRABZ/BLR/BLRAA/BLRAAZ/BLRAB/BLRABZ/RET/RETAA/RETAB */
344DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(BrBlrRet)
345 DIS_ARMV8_OP(0xd61f0000, "br", OP_ARMV8_A64_BR, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
346 DIS_ARMV8_OP(0xd63f0000, "blr", OP_ARMV8_A64_BLR, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
347 /** @todo All the FEAT_PAuth related branch instructions. */
348 DIS_ARMV8_OP(0xd65f0000, "ret", OP_ARMV8_A64_RET, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
349 DIS_ARMV8_OP(0xd65f0800, "retaa", OP_ARMV8_A64_RETAA, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
350 DIS_ARMV8_OP(0xd65f0c00, "retab", OP_ARMV8_A64_RETAB, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
351DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(BrBlrRet)
352 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 0 /*idxParam*/),
353DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(BrBlrRet, 0xfffffc1f /*fFixedInsn*/, DISARMV8INSNCLASS_F_FORCED_64BIT,
354 kDisArmV8OpcDecodeLookup, 0xfffffc1f, 0,
355 kDisArmv8OpParmReg);
356
357
358/* Unconditional branch (register) instructions, we divide these instructions further based on the opc field. */
359DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(UncondBrReg)
360 DIS_ARMV8_DECODE_MAP_ENTRY(BrBlrRet), /* BR/BRAA/BRAAZ/BRAB/BRABZ */
361 DIS_ARMV8_DECODE_MAP_ENTRY(BrBlrRet), /* BLR/BLRAA/BLRAAZ/BLRAB/BLRABZ */
362 DIS_ARMV8_DECODE_MAP_ENTRY(BrBlrRet), /* RET/RETAA/RETAB */
363 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
364 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
365 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
366 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
367 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
368 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
369 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
370 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
371 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
372 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
373 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
374 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
375 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY
376DIS_ARMV8_DECODE_MAP_DEFINE_END(UncondBrReg, RT_BIT_32(21) | RT_BIT_32(22) | RT_BIT_32(23) | RT_BIT_32(24), 21);
377
378
379/* B/BL */
380DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(UncondBrImm)
381 DIS_ARMV8_OP(0x14000000, "b", OP_ARMV8_A64_B, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
382 DIS_ARMV8_OP(0x94000000, "bl", OP_ARMV8_A64_BL, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
383DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(UncondBrImm)
384 DIS_ARMV8_INSN_DECODE(kDisParmParseImmRel, 0, 26, 0 /*idxParam*/),
385DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_1(UncondBrImm, 0xfc000000 /*fFixedInsn*/, 0 /*fClass*/,
386 kDisArmV8OpcDecodeNop, RT_BIT_32(31), 31,
387 kDisArmv8OpParmImmRel);
388
389
390/* CBZ/CBNZ */
391DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(CmpBrImm)
392 DIS_ARMV8_OP(0x34000000, "cbz", OP_ARMV8_A64_CBZ, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
393 DIS_ARMV8_OP(0x35000000, "cbnz", OP_ARMV8_A64_CBNZ, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
394DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(CmpBrImm)
395 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
396 DIS_ARMV8_INSN_DECODE(kDisParmParseImmRel, 5, 19, 1 /*idxParam*/),
397DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(CmpBrImm, 0x7f000000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
398 kDisArmV8OpcDecodeNop, RT_BIT_32(24), 24,
399 kDisArmv8OpParmReg, kDisArmv8OpParmImmRel);
400
401
402/* TBZ/TBNZ */
403DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(TestBrImm)
404 DIS_ARMV8_OP(0x36000000, "tbz", OP_ARMV8_A64_TBZ, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
405 DIS_ARMV8_OP(0x37000000, "tbnz", OP_ARMV8_A64_TBNZ, DISOPTYPE_HARMLESS | DISOPTYPE_CONTROLFLOW),
406DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(TestBrImm)
407 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
408 DIS_ARMV8_INSN_DECODE(kDisParmParseImmTbz, 0, 0, 1 /*idxParam*/), /* Hardcoded bit offsets in parser. */
409 DIS_ARMV8_INSN_DECODE(kDisParmParseImmRel, 5, 14, 2 /*idxParam*/),
410DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(TestBrImm, 0x7f000000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF, /* Not an SF bit but has the same meaning. */
411 kDisArmV8OpcDecodeNop, RT_BIT_32(24), 24,
412 kDisArmv8OpParmReg, kDisArmv8OpParmImm, kDisArmv8OpParmImmRel);
413
414
415DIS_ARMV8_DECODE_TBL_DEFINE_BEGIN(BrExcpSys)
416 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfe000000, RT_BIT_32(26) | RT_BIT_32(28) | RT_BIT_32(30), CondBr), /* op0: 010, op1: 0xxxxxxxxxxxxx, op2: - (including o1 from the conditional branch (immediate) class to save us one layer). */
417 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xff000000, RT_BIT_32(26) | RT_BIT_32(28) | RT_BIT_32(30) | RT_BIT_32(31), Excp), /* op0: 110, op1: 00xxxxxxxxxxxx, op2: -. */
418 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfffff000, 0xd5031000, SysReg), /* op0: 110, op1: 01000000110001, op2: -. */
419 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfffff01f, 0xd503201f, Hints), /* op0: 110, op1: 01000000110010, op2: 11111. */
420 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfffff01f, 0xd503301f, DecodeBarriers), /* op0: 110, op1: 01000000110011, op2: - (we include Rt: 11111 from the next stage here). */
421 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfff8f01f, 0xd500401f, PState), /* op0: 110, op1: 0100000xxx0100, op2: - (we include Rt: 11111 from the next stage here). */
422 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfffff0e0, 0xd5233060, SysResult), /* op0: 110, op1: 0100100xxxxxxx, op2: - (we include op1, CRn and op2 from the next stage here). */
423 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfff80000, 0xd5080000, Sys), /* op0: 110, op1: 0100x01xxxxxxx, op2: - (we include the L field of the next stage here to differentiate between SYS/SYSL as they have a different string representation). */
424 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfff80000, 0xd5280000, SysL), /* op0: 110, op1: 0100x01xxxxxxx, op2: - (we include the L field of the next stage here to differentiate between SYS/SYSL as they have a different string representation). */
425 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfff00000, 0xd5100000, Msr), /* op0: 110, op1: 0100x1xxxxxxxx, op2: - (we include the L field of the next stage here to differentiate between MSR/MRS as they have a different string representation). */
426 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfff00000, 0xd5300000, Mrs), /* op0: 110, op1: 0100x1xxxxxxxx, op2: - (we include the L field of the next stage here to differentiate between MSR/MRS as they have a different string representation). */
427 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0xfe1f0000, 0xd61f0000, UncondBrReg), /* op0: 110, op1: 1xxxxxxxxxxxxx, op2: - (we include the op2 field from the next stage here as it should be always 11111). */
428 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0x7c000000, 0x14000000, UncondBrImm), /* op0: x00, op1: xxxxxxxxxxxxxx, op2: -. */
429 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0x7e000000, 0x34000000, CmpBrImm), /* op0: x01, op1: 0xxxxxxxxxxxxx, op2: -. */
430 DIS_ARMV8_DECODE_TBL_ENTRY_INIT(0x7e000000, 0x36000000, TestBrImm), /* op0: x01, op1: 1xxxxxxxxxxxxx, op2: -. */
431DIS_ARMV8_DECODE_TBL_DEFINE_END(BrExcpSys);
432
433
434/* AND/ORR/EOR/ANDS */
435DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LogShiftRegN0)
436 DIS_ARMV8_OP(0x0a000000, "and", OP_ARMV8_A64_AND, DISOPTYPE_HARMLESS),
437 DIS_ARMV8_OP(0x2a000000, "orr", OP_ARMV8_A64_ORR, DISOPTYPE_HARMLESS),
438 DIS_ARMV8_OP(0x4a000000, "eor", OP_ARMV8_A64_EOR, DISOPTYPE_HARMLESS),
439 DIS_ARMV8_OP(0x6a000000, "ands", OP_ARMV8_A64_ANDS, DISOPTYPE_HARMLESS)
440DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LogShiftRegN0)
441 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
442 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
443 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 16, 5, 2 /*idxParam*/),
444 DIS_ARMV8_INSN_DECODE(kDisParmParseShift, 22, 2, 2 /*idxParam*/),
445 DIS_ARMV8_INSN_DECODE(kDisParmParseShiftAmount, 10, 6, 2 /*idxParam*/),
446DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(LogShiftRegN0, 0x7f200000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
447 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
448 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmReg);
449
450
451/* AND/ORR/EOR/ANDS */
452DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LogShiftRegN1)
453 DIS_ARMV8_OP(0x0a200000, "bic", OP_ARMV8_A64_BIC, DISOPTYPE_HARMLESS),
454 DIS_ARMV8_OP(0x2a200000, "orn", OP_ARMV8_A64_ORN, DISOPTYPE_HARMLESS),
455 DIS_ARMV8_OP(0x4a200000, "eon", OP_ARMV8_A64_EON, DISOPTYPE_HARMLESS),
456 DIS_ARMV8_OP(0x6a200000, "bics", OP_ARMV8_A64_BICS, DISOPTYPE_HARMLESS)
457DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LogShiftRegN1)
458 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
459 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
460 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 16, 5, 2 /*idxParam*/),
461 DIS_ARMV8_INSN_DECODE(kDisParmParseShift, 22, 2, 2 /*idxParam*/),
462 DIS_ARMV8_INSN_DECODE(kDisParmParseShiftAmount, 10, 6, 2 /*idxParam*/),
463DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(LogShiftRegN1, 0x7f200000 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
464 kDisArmV8OpcDecodeNop, RT_BIT_32(29) | RT_BIT_32(30), 29,
465 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmReg);
466
467
468DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LogShiftRegN)
469 DIS_ARMV8_DECODE_MAP_ENTRY(LogShiftRegN0), /* Logical (shifted register) - N = 0 */
470 DIS_ARMV8_DECODE_MAP_ENTRY(LogShiftRegN1), /* Logical (shifted register) - N = 1 */
471DIS_ARMV8_DECODE_MAP_DEFINE_END(LogShiftRegN, RT_BIT_32(21), 21);
472
473
474DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(AddSubExtReg)
475 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
476DIS_ARMV8_DECODE_MAP_DEFINE_END(AddSubExtReg, RT_BIT_32(24), 24);
477
478
479DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(AddSubShiftExtReg)
480 DIS_ARMV8_DECODE_MAP_ENTRY(AddSubShiftReg), /* Add/Subtract (shifted register) */
481 DIS_ARMV8_DECODE_MAP_ENTRY(AddSubExtReg), /* Add/Subtract (extended register) */
482DIS_ARMV8_DECODE_MAP_DEFINE_END(AddSubShiftExtReg, RT_BIT_32(21), 21);
483
484
485DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LogicalAddSubReg)
486 DIS_ARMV8_DECODE_MAP_ENTRY(LogShiftRegN), /* Logical (shifted register) */
487 DIS_ARMV8_DECODE_MAP_ENTRY(AddSubShiftExtReg), /* Add/subtract (shifted/extended register) */
488DIS_ARMV8_DECODE_MAP_DEFINE_END(LogicalAddSubReg, RT_BIT_32(24), 24);
489
490
491/* CCMN/CCMP */
492DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(CondCmpReg)
493 DIS_ARMV8_OP(0x3a400000, "ccmn", OP_ARMV8_A64_CCMN, DISOPTYPE_HARMLESS),
494 DIS_ARMV8_OP(0x7a400000, "ccmp", OP_ARMV8_A64_CCMP, DISOPTYPE_HARMLESS)
495DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(CondCmpReg)
496 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 0 /*idxParam*/),
497 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 16, 5, 1 /*idxParam*/),
498 DIS_ARMV8_INSN_DECODE(kDisParmParseImm, 0, 4, 2 /*idxParam*/),
499 DIS_ARMV8_INSN_DECODE(kDisParmParseCond, 12, 4, 3 /*idxParam*/),
500DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_4(CondCmpReg, 0x7fe00c10 /*fFixedInsn*/, DISARMV8INSNCLASS_F_SF,
501 kDisArmV8OpcDecodeNop, RT_BIT_32(30), 30,
502 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmImm, kDisArmv8OpParmCond);
503
504
505/**
506 * C4.1.95 - Data Processing - Register
507 *
508 * The conditional compare instructions differentiate between register and immediate
509 * variant based on the 11th bit (part of op3).
510 */
511DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(CondCmp)
512 DIS_ARMV8_DECODE_MAP_ENTRY(CondCmpReg), /* Conditional compare register */
513 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Conditional compare immediate */
514DIS_ARMV8_DECODE_MAP_DEFINE_END(CondCmp, RT_BIT_32(11), 11);
515
516
517/*
518 * C4.1.95 - Data Processing - Register
519 *
520 * The op1 field is already decoded in the previous step and is 1 when being here,
521 * leaving us with the following possible values:
522 *
523 * Bit 24 23 22 21
524 * +-------------------------------------------
525 * 0 0 0 0 Add/subtract with carry / Rotate right into flags / Evaluate into flags (depending on op3)
526 * 0 0 0 1 UNALLOC
527 * 0 0 1 0 Conditional compare (register / immediate)
528 * 0 0 1 1 UNALLOC
529 * 0 1 0 0 Conditional select
530 * 0 1 0 1 UNALLOC
531 * 0 1 1 0 Data processing (2-source or 1-source depending on op0).
532 * 0 1 1 1 UNALLOC
533 * 1 x x x Data processing 3-source
534 */
535DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(DataProcReg)
536 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Add/subtract with carry. */
537 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
538 DIS_ARMV8_DECODE_MAP_ENTRY(CondCmp), /** @todo Conditional compare. */
539 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
540 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Conditional select. */
541 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
542 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 2-source/1-source. */
543 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY,
544 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
545 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
546 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
547 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
548 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
549 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
550 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
551 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo Data Processing 3-source. */
552DIS_ARMV8_DECODE_MAP_DEFINE_END(DataProcReg, RT_BIT_32(21) | RT_BIT_32(22) | RT_BIT_32(23) | RT_BIT_32(24), 21);
553
554
555/* STRB/LDRB/LDRSB/STR/LDR/STRH/LDRH/LDRSH/LDRSW/PRFM
556 *
557 * Note: The size,opc bitfields are concatenated to form an index.
558 */
559DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LdStRegUImmGpr)
560 DIS_ARMV8_OP(0x39000000, "strb", OP_ARMV8_A64_STRB, DISOPTYPE_HARMLESS),
561 DIS_ARMV8_OP(0x39400000, "ldrb", OP_ARMV8_A64_LDRB, DISOPTYPE_HARMLESS),
562 DIS_ARMV8_OP_EX(0x39800000, "ldrsb", OP_ARMV8_A64_LDRSB, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
563 DIS_ARMV8_OP(0x39c00000, "ldrsb", OP_ARMV8_A64_LDRSB, DISOPTYPE_HARMLESS),
564 DIS_ARMV8_OP(0x79000000, "strh", OP_ARMV8_A64_STRH, DISOPTYPE_HARMLESS),
565 DIS_ARMV8_OP(0x79400000, "ldrh", OP_ARMV8_A64_LDRH, DISOPTYPE_HARMLESS),
566 DIS_ARMV8_OP_EX(0x79800000, "ldrsh", OP_ARMV8_A64_LDRSH, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
567 DIS_ARMV8_OP(0x79c00000, "ldrsh", OP_ARMV8_A64_LDRSH, DISOPTYPE_HARMLESS),
568 DIS_ARMV8_OP(0xb9000000, "str", OP_ARMV8_A64_STR, DISOPTYPE_HARMLESS),
569 DIS_ARMV8_OP(0xb9400000, "ldr", OP_ARMV8_A64_LDR, DISOPTYPE_HARMLESS),
570 DIS_ARMV8_OP_EX(0xb9800000, "ldrsw", OP_ARMV8_A64_LDRSW, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
571 INVALID_OPCODE,
572 DIS_ARMV8_OP(0xf9000000, "str", OP_ARMV8_A64_STR, DISOPTYPE_HARMLESS),
573 DIS_ARMV8_OP(0xf9400000, "ldr", OP_ARMV8_A64_LDR, DISOPTYPE_HARMLESS),
574 INVALID_OPCODE, /** @todo PRFM */
575 INVALID_OPCODE,
576DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LdStRegUImmGpr)
577 DIS_ARMV8_INSN_DECODE(kDisParmParseSize, 30, 2, DIS_ARMV8_INSN_PARAM_UNSET),
578 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
579 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
580 DIS_ARMV8_INSN_DECODE(kDisParmParseImmMemOff, 10, 12, 1 /*idxParam*/),
581DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(LdStRegUImmGpr, 0xffc00000 /*fFixedInsn*/, 0 /*fClass*/,
582 kDisArmV8OpcDecodeCollate,
583 RT_BIT_32(22) | RT_BIT_32(23) | RT_BIT_32(30) | RT_BIT_32(31), 22,
584 kDisArmv8OpParmReg, kDisArmv8OpParmAddrInGpr);
585
586
587/*
588 * C4.1.94 - Loads and Stores - Load/Store register variants
589 *
590 * Differentiate further based on the VR field.
591 *
592 * Bit 26
593 * +-------------------------------------------
594 * 0 GPR variants.
595 * 1 SIMD/FP variants
596 */
597DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegUImm)
598 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegUImmGpr),
599 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
600DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegUImm, RT_BIT_32(26), 26);
601
602
603/*
604 * STRB/LDRB/LDRSB/STR/LDR/STRH/LDRH/LDRSH/LDRSW/PRFM
605 *
606 * Note: The size,opc bitfields are concatenated to form an index.
607 */
608DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LdStRegOffGpr)
609 DIS_ARMV8_OP(0x38200800, "strb", OP_ARMV8_A64_STRB, DISOPTYPE_HARMLESS),
610 DIS_ARMV8_OP(0x38600800, "ldrb", OP_ARMV8_A64_LDRB, DISOPTYPE_HARMLESS),
611 DIS_ARMV8_OP_EX(0x38a00800, "ldrsb", OP_ARMV8_A64_LDRSB, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
612 DIS_ARMV8_OP(0x38e00800, "ldrsb", OP_ARMV8_A64_LDRSB, DISOPTYPE_HARMLESS),
613 DIS_ARMV8_OP(0x78200800, "strh", OP_ARMV8_A64_STRH, DISOPTYPE_HARMLESS),
614 DIS_ARMV8_OP(0x78600800, "ldrh", OP_ARMV8_A64_LDRH, DISOPTYPE_HARMLESS),
615 DIS_ARMV8_OP_EX(0x78a00800, "ldrsh", OP_ARMV8_A64_LDRSH, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
616 DIS_ARMV8_OP(0x78e00800, "ldrsh", OP_ARMV8_A64_LDRSH, DISOPTYPE_HARMLESS),
617 DIS_ARMV8_OP(0xb8200800, "str", OP_ARMV8_A64_STR, DISOPTYPE_HARMLESS),
618 DIS_ARMV8_OP(0xb8600800, "ldr", OP_ARMV8_A64_LDR, DISOPTYPE_HARMLESS),
619 DIS_ARMV8_OP_EX(0xb8a00800, "ldrsw", OP_ARMV8_A64_LDRSW, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
620 INVALID_OPCODE,
621 DIS_ARMV8_OP(0xf8200800, "str", OP_ARMV8_A64_STR, DISOPTYPE_HARMLESS),
622 DIS_ARMV8_OP(0xf8600800, "ldr", OP_ARMV8_A64_LDR, DISOPTYPE_HARMLESS),
623 INVALID_OPCODE, /** @todo PRFM */
624 INVALID_OPCODE,
625DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LdStRegOffGpr)
626 DIS_ARMV8_INSN_DECODE(kDisParmParseSize, 30, 2, DIS_ARMV8_INSN_PARAM_UNSET),
627 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
628 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
629 DIS_ARMV8_INSN_DECODE(kDisParmParseRegOff, 16, 5, 1 /*idxParam*/),
630 DIS_ARMV8_INSN_DECODE(kDisParmParseOption, 13, 3, 1 /*idxParam*/),
631 DIS_ARMV8_INSN_DECODE(kDisParmParseS, 12, 1, 1 /*idxParam*/),
632DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(LdStRegOffGpr, 0xffe00c00 /*fFixedInsn*/, 0 /*fClass*/,
633 kDisArmV8OpcDecodeCollate,
634 RT_BIT_32(22) | RT_BIT_32(23) | RT_BIT_32(30) | RT_BIT_32(31), 22,
635 kDisArmv8OpParmReg, kDisArmv8OpParmAddrInGpr);
636
637
638/*
639 * C4.1.94 - Loads and Stores - Load/Store register (register offset) variants
640 *
641 * Differentiate further based on the VR field.
642 *
643 * Bit 26
644 * +-------------------------------------------
645 * 0 GPR variants.
646 * 1 SIMD/FP variants
647 */
648DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegOff)
649 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegOffGpr),
650 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
651DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegOff, RT_BIT_32(26), 26);
652
653
654/*
655 * C4.1.94 - Loads and Stores - Load/Store register variants
656 *
657 * Differentiate further based on the op2<1:0> field.
658 *
659 * Bit 11 10
660 * +-------------------------------------------
661 * 0 0 Atomic memory operations
662 * 0 1 Load/store register (pac)
663 * 1 0 Load/store register (register offset)
664 * 1 1 Load/store register (pac)
665 */
666DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegOp2_11_1)
667 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
668 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
669 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegOff),
670 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
671DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegOp2_11_1, RT_BIT_32(10) | RT_BIT_32(11), 10);
672
673
674/*
675 * STURB/LDURB/LDURSB/STURH/LDURH/LDURSH/STUR/LDUR/LDURSW/PRFUM
676 *
677 * Note: The size,opc bitfields are concatenated to form an index.
678 */
679DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LdStRegUnscaledImmGpr)
680 DIS_ARMV8_OP(0x38000000, "sturb", OP_ARMV8_A64_STURB, DISOPTYPE_HARMLESS),
681 DIS_ARMV8_OP(0x38400000, "ldurb", OP_ARMV8_A64_LDURB, DISOPTYPE_HARMLESS),
682 DIS_ARMV8_OP_EX(0x38800000, "ldursb", OP_ARMV8_A64_LDURSB, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
683 DIS_ARMV8_OP(0x38c00000, "ldursb", OP_ARMV8_A64_LDURSB, DISOPTYPE_HARMLESS),
684 DIS_ARMV8_OP(0x78000000, "sturh", OP_ARMV8_A64_STURH, DISOPTYPE_HARMLESS),
685 DIS_ARMV8_OP(0x78400000, "ldurh", OP_ARMV8_A64_LDURH, DISOPTYPE_HARMLESS),
686 DIS_ARMV8_OP_EX(0x78800000, "ldursh", OP_ARMV8_A64_LDURSH, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
687 DIS_ARMV8_OP(0x78c00000, "ldursh", OP_ARMV8_A64_LDURSH, DISOPTYPE_HARMLESS),
688 DIS_ARMV8_OP(0xb8000000, "stur", OP_ARMV8_A64_STUR, DISOPTYPE_HARMLESS),
689 DIS_ARMV8_OP(0xb8400000, "ldur", OP_ARMV8_A64_LDUR, DISOPTYPE_HARMLESS),
690 DIS_ARMV8_OP_EX(0xb8800000, "ldursw", OP_ARMV8_A64_LDURSW, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
691 INVALID_OPCODE,
692 DIS_ARMV8_OP(0xf8000000, "stur", OP_ARMV8_A64_STUR, DISOPTYPE_HARMLESS),
693 DIS_ARMV8_OP(0xf8400000, "ldur", OP_ARMV8_A64_LDUR, DISOPTYPE_HARMLESS),
694 INVALID_OPCODE, /** @todo PRFUM */
695 INVALID_OPCODE,
696DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LdStRegUnscaledImmGpr)
697 DIS_ARMV8_INSN_DECODE(kDisParmParseSize, 30, 2, DIS_ARMV8_INSN_PARAM_UNSET),
698 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
699 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 1 /*idxParam*/),
700 DIS_ARMV8_INSN_DECODE(kDisParmParseSImmMemOffUnscaled, 12, 9, 1 /*idxParam*/),
701DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_2(LdStRegUnscaledImmGpr, 0xffe00c00 /*fFixedInsn*/, 0 /*fClass*/,
702 kDisArmV8OpcDecodeCollate,
703 RT_BIT_32(22) | RT_BIT_32(23) | RT_BIT_32(30) | RT_BIT_32(31), 22,
704 kDisArmv8OpParmReg, kDisArmv8OpParmAddrInGpr);
705
706
707/*
708 * C4.1.94 - Loads and Stores - Load/Store register (register offset) variants
709 *
710 * Differentiate further based on the VR field.
711 *
712 * Bit 26
713 * +-------------------------------------------
714 * 0 GPR variants.
715 * 1 SIMD/FP variants
716 */
717DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegUnscaledImm)
718 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegUnscaledImmGpr),
719 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
720DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegUnscaledImm, RT_BIT_32(26), 26);
721
722
723/*
724 * C4.1.94 - Loads and Stores - Load/Store register variants
725 *
726 * Differentiate further based on the op2<1:0> field.
727 *
728 * Bit 11 10
729 * +-------------------------------------------
730 * 0 0 Load/store register (unscaled immediate)
731 * 0 1 Load/store register (immediate post-indexed)
732 * 1 0 Load/store register (unprivileged)
733 * 1 1 Load/store register (immediate pre-indexed)
734 */
735DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegOp2_11_0)
736 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegUnscaledImm),
737 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
738 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
739 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
740DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegOp2_11_0, RT_BIT_32(10) | RT_BIT_32(11), 10);
741
742
743/*
744 * C4.1.94 - Loads and Stores - Load/Store register variants
745 *
746 * Differentiate further based on the op2<11> field.
747 *
748 * Bit 21
749 * +-------------------------------------------
750 * 0 Load/store register (unscaled immediate) / Load/store register (immediate post-indexed) / Load/store register (unprivileged) / Load/store register (immediate pre-indexed)
751 * 1 Atomic memory operations / Load/store register (register offset) / Load/store register (pac).
752 */
753DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegOp2_11)
754 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegOp2_11_0),
755 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegOp2_11_1),
756DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegOp2_11, RT_BIT_32(21), 21);
757
758
759/*
760 * C4.1.94 - Loads and Stores - Load/Store register variants
761 *
762 * Differentiate further based on the op2<14> field.
763 *
764 * Bit 24
765 * +-------------------------------------------
766 * 0 All the other Load/store register variants and Atomic memory operations.
767 * 1 Load/store register (unsigned immediate).
768 */
769DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStReg)
770 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegOp2_11),
771 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegUImm),
772DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStReg, RT_BIT_32(24), 24);
773
774
775/*
776 * STP/LDP/STGP/LDPSW
777 *
778 * Note: The opc,L bitfields are concatenated to form an index.
779 */
780DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LdStRegPairOff)
781 DIS_ARMV8_OP_EX(0x29000000, "stp", OP_ARMV8_A64_STP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_32BIT),
782 DIS_ARMV8_OP_EX(0x29400000, "ldp", OP_ARMV8_A64_LDP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_32BIT),
783 INVALID_OPCODE,
784 INVALID_OPCODE,
785 DIS_ARMV8_OP_EX(0xa9000000, "stp", OP_ARMV8_A64_STP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
786 DIS_ARMV8_OP_EX(0xa9400000, "ldp", OP_ARMV8_A64_LDP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
787 INVALID_OPCODE,
788 INVALID_OPCODE,
789DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LdStRegPairOff)
790 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
791 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 10, 5, 1 /*idxParam*/),
792 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 2 /*idxParam*/),
793 DIS_ARMV8_INSN_DECODE(kDisParmParseSImmMemOff, 15, 7, 2 /*idxParam*/),
794DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(LdStRegPairOff, 0xffc00000 /*fFixedInsn*/, 0 /*fClass*/,
795 kDisArmV8OpcDecodeCollate,
796 RT_BIT_32(22) | RT_BIT_32(30) | RT_BIT_32(31), 22,
797 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmAddrInGpr);
798
799
800/*
801 * STP/LDP/STGP/LDPSW - pre-indexed variant.
802 *
803 * Note: The opc,L bitfields are concatenated to form an index.
804 */
805DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LdStRegPairPreIndex)
806 DIS_ARMV8_OP_EX(0x29800000, "stp", OP_ARMV8_A64_STP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_32BIT),
807 DIS_ARMV8_OP_EX(0x29c00000, "ldp", OP_ARMV8_A64_LDP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_32BIT),
808 INVALID_OPCODE,
809 INVALID_OPCODE,
810 DIS_ARMV8_OP_EX(0xa9800000, "stp", OP_ARMV8_A64_STP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
811 DIS_ARMV8_OP_EX(0xa9c00000, "ldp", OP_ARMV8_A64_LDP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
812 INVALID_OPCODE,
813 INVALID_OPCODE,
814DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LdStRegPairPreIndex)
815 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
816 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 10, 5, 1 /*idxParam*/),
817 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 2 /*idxParam*/),
818 DIS_ARMV8_INSN_DECODE(kDisParmParseSImmMemOff, 15, 7, 2 /*idxParam*/),
819 DIS_ARMV8_INSN_DECODE(kDisParmParseSetPreIndexed, 0, 0, 2 /*idxParam*/),
820DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(LdStRegPairPreIndex, 0xffc00000 /*fFixedInsn*/, 0 /*fClass*/,
821 kDisArmV8OpcDecodeCollate,
822 RT_BIT_32(22) | RT_BIT_32(30) | RT_BIT_32(31), 22,
823 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmAddrInGpr);
824
825
826/*
827 * STP/LDP/STGP/LDPSW - post-indexed variant.
828 *
829 * Note: The opc,L bitfields are concatenated to form an index.
830 */
831DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(LdStRegPairPostIndex)
832 DIS_ARMV8_OP_EX(0x28800000, "stp", OP_ARMV8_A64_STP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_32BIT),
833 DIS_ARMV8_OP_EX(0x28c00000, "ldp", OP_ARMV8_A64_LDP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_32BIT),
834 INVALID_OPCODE,
835 INVALID_OPCODE,
836 DIS_ARMV8_OP_EX(0xa8800000, "stp", OP_ARMV8_A64_STP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
837 DIS_ARMV8_OP_EX(0xa8c00000, "ldp", OP_ARMV8_A64_LDP, DISOPTYPE_HARMLESS, DISARMV8INSNCLASS_F_FORCED_64BIT),
838 INVALID_OPCODE,
839 INVALID_OPCODE,
840DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_DECODER(LdStRegPairPostIndex)
841 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 0, 5, 0 /*idxParam*/),
842 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 10, 5, 1 /*idxParam*/),
843 DIS_ARMV8_INSN_DECODE(kDisParmParseReg, 5, 5, 2 /*idxParam*/),
844 DIS_ARMV8_INSN_DECODE(kDisParmParseSImmMemOff, 15, 7, 2 /*idxParam*/),
845 DIS_ARMV8_INSN_DECODE(kDisParmParseSetPostIndexed, 0, 0, 2 /*idxParam*/),
846DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END_PARAMS_3(LdStRegPairPostIndex, 0xffc00000 /*fFixedInsn*/, 0 /*fClass*/,
847 kDisArmV8OpcDecodeCollate,
848 RT_BIT_32(22) | RT_BIT_32(30) | RT_BIT_32(31), 22,
849 kDisArmv8OpParmReg, kDisArmv8OpParmReg, kDisArmv8OpParmAddrInGpr);
850
851
852/*
853 * C4.1.94 - Loads and Stores - Load/Store register pair variants
854 *
855 * Differentiate further based on the op2<14:13> field.
856 *
857 * Bit 24 23
858 * +-------------------------------------------
859 * 0 0 Load/store no-allocate pair (offset)
860 * 0 1 Load/store register pair (post-indexed)
861 * 1 0 Load/store register pair (offset).
862 * 1 1 Load/store register pair (pre-indexed).
863 */
864DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStRegPair)
865 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
866 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegPairPostIndex),
867 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegPairOff),
868 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegPairPreIndex),
869DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStRegPair, RT_BIT_32(23) | RT_BIT_32(24), 23);
870
871
872/*
873 * C4.1.94 - Loads and Stores
874 *
875 * Differentiate further based on the op0<1:0> field.
876 * Splitting this up because the decoding would get insane otherwise with tables doing cross referencing...
877 *
878 * Bit 29 28
879 * +-------------------------------------------
880 * 0 0 Compare and swap pair / Advanced SIMD loads/stores / Load/store exclusive pair / Load/store exclusive register
881 * Load/store ordered / Compare and swap
882 * 0 1 RCW compare and swap / 128-bit atomic memory instructions / GCS load/store / Load/store memory tags /
883 * LDIAPP/STILP / LDAPR/STLR / Load register (literal) / Memory Copy and Set
884 * 1 0 Load/store no-allocate pair / Load/store register pair /
885 * 1 1 Load/store register / Atomic memory operations
886 */
887DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(LdStOp0Lo)
888 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
889 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo */
890 DIS_ARMV8_DECODE_MAP_ENTRY(LdStRegPair),
891 DIS_ARMV8_DECODE_MAP_ENTRY(LdStReg),
892DIS_ARMV8_DECODE_MAP_DEFINE_END(LdStOp0Lo, RT_BIT_32(28) | RT_BIT_32(29), 28);
893
894
895/*
896 * C4.1 of the ARMv8 architecture reference manual has the following table for the
897 * topmost decoding level (Level 0 in our terms), x means don't care:
898 *
899 * Bit 28 27 26 25
900 * +-------------------------------------------
901 * 0 0 0 0 Reserved or SME encoding (depends on bit 31).
902 * 0 0 0 1 UNALLOC
903 * 0 0 1 0 SVE encodings
904 * 0 0 1 1 UNALLOC
905 * 1 0 0 x Data processing immediate
906 * 1 0 1 x Branch, exception generation and system instructions
907 * x 1 x 0 Loads and stores
908 * x 1 0 1 Data processing - register
909 * x 1 1 1 Data processing - SIMD and floating point
910 *
911 * In order to save us some fiddling with the don't care bits we blow up the lookup table
912 * which gives us 16 possible values (4 bits) we can use as an index into the decoder
913 * lookup table for the next level:
914 * Bit 28 27 26 25
915 * +-------------------------------------------
916 * 0 0 0 0 0 Reserved or SME encoding (depends on bit 31).
917 * 1 0 0 0 1 UNALLOC
918 * 2 0 0 1 0 SVE encodings
919 * 3 0 0 1 1 UNALLOC
920 * 4 0 1 0 0 Loads and stores
921 * 5 0 1 0 1 Data processing - register (using op1 (bit 28) from the next stage to differentiate further already)
922 * 6 0 1 1 0 Loads and stores
923 * 7 0 1 1 1 Data processing - SIMD and floating point
924 * 8 1 0 0 0 Data processing immediate
925 * 9 1 0 0 1 Data processing immediate
926 * 10 1 0 1 0 Branch, exception generation and system instructions
927 * 11 1 0 1 1 Branch, exception generation and system instructions
928 * 12 1 1 0 0 Loads and stores
929 * 13 1 1 0 1 Data processing - register (using op1 (bit 28) from the next stage to differentiate further already)
930 * 14 1 1 1 0 Loads and stores
931 * 15 1 1 1 1 Data processing - SIMD and floating point
932 */
933DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(DecodeL0)
934 DIS_ARMV8_DECODE_MAP_ENTRY(Rsvd), /* Reserved class or SME encoding (@todo). */
935 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Unallocated */
936 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /** @todo SVE */
937 DIS_ARMV8_DECODE_MAP_INVALID_ENTRY, /* Unallocated */
938 DIS_ARMV8_DECODE_MAP_ENTRY(LdStOp0Lo), /* Load/Stores. */
939 DIS_ARMV8_DECODE_MAP_ENTRY(LogicalAddSubReg), /* Data processing (register) (see op1 in C4.1.68). */
940 DIS_ARMV8_DECODE_MAP_ENTRY(LdStOp0Lo), /* Load/Stores. */
941 DIS_ARMV8_DECODE_MAP_ENTRY(DataProcSimdFpBit28_0), /* Data processing (SIMD & FP) (op0<0> 0) */
942 DIS_ARMV8_DECODE_MAP_ENTRY(DataProcessingImm), /* Data processing (immediate). */
943 DIS_ARMV8_DECODE_MAP_ENTRY(DataProcessingImm), /* Data processing (immediate). */
944 DIS_ARMV8_DECODE_MAP_ENTRY(BrExcpSys), /* Branches / Exception generation and system instructions. */
945 DIS_ARMV8_DECODE_MAP_ENTRY(BrExcpSys), /* Branches / Exception generation and system instructions. */
946 DIS_ARMV8_DECODE_MAP_ENTRY(LdStOp0Lo), /* Load/Stores. */
947 DIS_ARMV8_DECODE_MAP_ENTRY(DataProcReg), /* Data processing (register) (see op1 in C4.1.68). */
948 DIS_ARMV8_DECODE_MAP_ENTRY(LdStOp0Lo), /* Load/Stores. */
949 DIS_ARMV8_DECODE_MAP_ENTRY(DataProcSimdFpBit28_1) /* Data processing (SIMD & FP) (op0<0> 1). */
950DIS_ARMV8_DECODE_MAP_DEFINE_END_NON_STATIC(DecodeL0, 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