libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
op_decoders.h
1#pragma once
2
3#include "libmicroemu/internal/decoder/instr.h"
4#include "libmicroemu/internal/fetcher/raw_instr.h"
5#include "libmicroemu/internal/logic/thumb.h"
7#include "libmicroemu/internal/utils/bit_manip.h"
8#include "libmicroemu/register_details.h"
9#include "libmicroemu/types.h"
10#include <assert.h>
11#include <cstdint>
12
13namespace libmicroemu::internal {
14
15using Bm8 = BitManip<u8>;
16using Bm16 = BitManip<u16>;
17using Bm32 = BitManip<u32>;
18
19static constexpr u32 kDecodersOpCodeLast = 15U;
20static constexpr u32 kDecodersOpCodeFirst = 11U;
21
22template <typename TCpuAccessor, typename TItOps>
23static Result<Instr> InvalidInstrDecoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
24 static_cast<void>(rinstr);
25 static_cast<void>(cpua); // prevents warning when cpua is not used
26 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
27}
28
29template <typename TCpuAccessor, typename TItOps>
30static Result<Instr> NopT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
31 static_cast<void>(cpua); // prevents warning when cpua is not used
32 const InstrId iid{InstrId::kNop};
33 u8 flags = 0x0U;
34
35 static_cast<void>(rinstr);
36
37 assert(rinstr.low == 0b1011111100000000U);
38
39 return Ok(Instr{InstrNop{
40 iid,
41 flags,
42 }});
43}
44
45template <typename TCpuAccessor, typename TItOps>
46static Result<Instr> DmbT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
47 static_cast<void>(cpua); // prevents warning when cpua is not used
48 const InstrId iid{InstrId::kDmb};
49 u8 flags = 0x0U;
50
51 assert(rinstr.low == 0b1111001110111111U);
52 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.high)) == 0b100011110101U);
53 static_cast<void>(rinstr);
54
55 flags |= static_cast<u8>(InstrFlags::k32Bit);
56
57 return Ok(Instr{InstrDmb{
58 iid,
59 flags,
60 }});
61}
62
63template <typename TCpuAccessor, typename TItOps>
64static Result<Instr> AddPcPlusImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
65 static_cast<void>(cpua); // prevents warning when cpua is not used
66 const InstrId iid{InstrId::kAddPcPlusImmediate};
67 u8 flags = 0x0U;
68
69 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b10100U);
70
71 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
72 const u16 Rd = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
73 const u8 d = static_cast<u8>(Rd);
74 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
75 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8 << 2U);
76
77 return Ok(Instr{InstrAddPcPlusImmediate{iid, flags, d, imm32}});
78}
79
80template <typename TCpuAccessor, typename TItOps>
81static Result<Instr> LslImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
82 static_cast<void>(cpua); // prevents warning when cpua is not used
83 const InstrId iid{InstrId::kLslImmediate};
84 u8 flags = 0x0U;
85
86 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b00000U);
87 assert((Bm16::ExtractBits1R<10U, 6U>(rinstr.low)) != 0x0U);
88
89 flags |=
90 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
91 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
92 const u8 d = static_cast<u8>(Rd);
93 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
94 const u8 m = static_cast<u8>(Rm);
95 const u16 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
96 const auto shift_res = Alu32::DecodeImmShift(0b00, imm5);
97
98 assert(shift_res.type == SRType::SRType_LSL);
99
100 return Ok(Instr{InstrLslImmediate{iid, flags, d, m, shift_res}});
101}
102
103template <typename TCpuAccessor, typename TItOps>
104static Result<Instr> LslImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
105 static_cast<void>(cpua); // prevents warning when cpua is not used
106 const InstrId iid{InstrId::kLslImmediate};
107 u8 flags = 0x0U;
108
109 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010010U);
110 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
111 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
112 assert((Bm16::ExtractBits1R<5U, 4U>(rinstr.high)) == 0b00U);
113
114 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
115 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
116 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
117 const u8 d = static_cast<u8>(Rd);
118 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
119 const u8 m = static_cast<u8>(Rm);
120 const u16 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
121 const u16 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
122 const auto shift_res = Alu32::DecodeImmShift(0b00U, (imm3 << 2U) | imm2);
123
124 assert(shift_res.type == SRType::SRType_LSL);
125 assert(((imm3 << 2U) | imm2) != 0b0U);
126 if (d == 13U || d == 15U || m == 13U || m == 15U) {
127 return Err<Instr>(StatusCode::kDecoderUnpredictable);
128 }
129 flags |= static_cast<u8>(InstrFlags::k32Bit);
130
131 return Ok(Instr{InstrLslImmediate{iid, flags, d, m, shift_res}});
132}
133
134template <typename TCpuAccessor, typename TItOps>
135static Result<Instr> LslRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
136 static_cast<void>(cpua); // prevents warning when cpua is not used
137 const InstrId iid{InstrId::kLslRegister};
138 u8 flags = 0x0U;
139
140 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100000010U);
141
142 flags |=
143 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
144 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
145 const u8 n = static_cast<u8>(Rn);
146 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
147 const u8 d = static_cast<u8>(Rd);
148 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
149 const u8 m = static_cast<u8>(Rm);
150
151 return Ok(Instr{InstrLslRegister{iid, flags, n, d, m}});
152}
153
154template <typename TCpuAccessor, typename TItOps>
155static Result<Instr> LslRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
156 static_cast<void>(cpua); // prevents warning when cpua is not used
157 const InstrId iid{InstrId::kLslRegister};
158 u8 flags = 0x0U;
159
160 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11111010000U);
161 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
162 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
163
164 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
165 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
166 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
167 const u8 n = static_cast<u8>(Rn);
168 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
169 const u8 d = static_cast<u8>(Rd);
170 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
171 const u8 m = static_cast<u8>(Rm);
172
173 if (d == 13U || d == 15 || n == 13U || n == 15 || m == 13U || m == 15) {
174 return Err<Instr>(StatusCode::kDecoderUnpredictable);
175 }
176 flags |= static_cast<u8>(InstrFlags::k32Bit);
177
178 return Ok(Instr{InstrLslRegister{iid, flags, n, d, m}});
179}
180
181template <typename TCpuAccessor, typename TItOps>
182static Result<Instr> ClzT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
183 static_cast<void>(cpua); // prevents warning when cpua is not used
184 const InstrId iid{InstrId::kClz};
185 u8 flags = 0x0U;
186
187 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110101011U);
188 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
189 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b1000U);
190
191 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
192 const u8 d = static_cast<u8>(Rd);
193 const u16 Rm_1 = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
194 const u16 Rm_2 = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
195 if (Rm_1 != Rm_2) {
196 return Err<Instr>(StatusCode::kDecoderUnpredictable);
197 }
198 const u8 m = static_cast<u8>(Rm_1);
199
200 if (d == 13U || d == 15 || m == 13U || m == 15) {
201 return Err<Instr>(StatusCode::kDecoderUnpredictable);
202 }
203 flags |= static_cast<u8>(InstrFlags::k32Bit);
204
205 return Ok(Instr{InstrClz{iid, flags, d, m}});
206}
207
208template <typename TCpuAccessor, typename TItOps>
209static Result<Instr> AsrImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
210 static_cast<void>(cpua); // prevents warning when cpua is not used
211 const InstrId iid{InstrId::kAsrImmediate};
212 u8 flags = 0x0U;
213
214 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b00010U);
215
216 flags |=
217 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
218 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
219 const u8 m = static_cast<u8>(Rm);
220 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
221 const u8 d = static_cast<u8>(Rd);
222 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
223 const auto shift_res = Alu32::DecodeImmShift(0b10U, imm5);
224
225 return Ok(Instr{InstrAsrImmediate{iid, flags, m, d, shift_res}});
226}
227
228template <typename TCpuAccessor, typename TItOps>
229static Result<Instr> CmpRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
230 static_cast<void>(cpua); // prevents warning when cpua is not used
231 const InstrId iid{InstrId::kCmpRegister};
232 u8 flags = 0x0U;
233
234 assert((Bm16::ExtractBits1R<10U, 6U>(rinstr.low)) == 0b01010U);
235
236 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
237 const u8 n = static_cast<u8>(Rn);
238 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
239 const u8 m = static_cast<u8>(Rm);
240 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
241
242 return Ok(Instr{InstrCmpRegister{iid, flags, n, m, shift_res}});
243}
244
245template <typename TCpuAccessor, typename TItOps>
246static Result<Instr> CmpRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
247 static_cast<void>(cpua); // prevents warning when cpua is not used
248 const InstrId iid{InstrId::kCmpRegister};
249 u8 flags = 0x0U;
250
251 assert((Bm16::ExtractBits1R<10U, 8U>(rinstr.low)) == 0b101U);
252
253 const u16 N = Bm16::IsolateBit<7U>(rinstr.low);
254 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
255 const u8 n = static_cast<u8>(N << 3U | Rn);
256 const u16 Rm = Bm16::ExtractBits1R<6U, 3U>(rinstr.low);
257 const u8 m = static_cast<u8>(Rm);
258 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
259
260 if (n < 8U && m < 8U) {
261 return Err<Instr>(StatusCode::kDecoderUnpredictable);
262 }
263 if (n == 15U || m == 15U) {
264 return Err<Instr>(StatusCode::kDecoderUnpredictable);
265 }
266
267 return Ok(Instr{InstrCmpRegister{iid, flags, n, m, shift_res}});
268}
269
270template <typename TCpuAccessor, typename TItOps>
271static Result<Instr> CmpRegisterT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
272 static_cast<void>(cpua); // prevents warning when cpua is not used
273 const InstrId iid{InstrId::kCmpRegister};
274 u8 flags = 0x0U;
275
276 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111010111011U);
277 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
278 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
279
280 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
281 const u8 n = static_cast<u8>(Rn);
282 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
283 const u8 m = static_cast<u8>(Rm);
284 const u16 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
285 const u16 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
286 const u16 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
287 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2) | imm2);
288
289 if (n == 15U || m == 13U || m == 15U) {
290 return Err<Instr>(StatusCode::kDecoderUnpredictable);
291 }
292 flags |= static_cast<u8>(InstrFlags::k32Bit);
293
294 return Ok(Instr{InstrCmpRegister{iid, flags, n, m, shift_res}});
295}
296
297template <typename TCpuAccessor, typename TItOps>
298static Result<Instr> CmpImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
299 static_cast<void>(cpua); // prevents warning when cpua is not used
300 const InstrId iid{InstrId::kCmpImmediate};
301 u8 flags = 0x0U;
302
303 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b00101U);
304
305 const u16 Rn = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
306 const u8 n = static_cast<u8>(Rn);
307 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
308 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
309
310 return Ok(Instr{InstrCmpImmediate{iid, flags, n, imm32}});
311}
312
313template <typename TCpuAccessor, typename TItOps>
314static Result<Instr> CmpImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
315 static_cast<void>(cpua); // prevents warning when cpua is not used
316 const InstrId iid{InstrId::kCmpImmediate};
317 u8 flags = 0x0U;
318
319 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
320 assert((Bm16::ExtractBits1R<9U, 4U>(rinstr.low)) == 0b011011U);
321 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
322 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
323
324 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
325 const u8 n = static_cast<u8>(Rn);
326 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
327 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
328 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
329 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm((i << 11U) | (imm3 << 8U) | imm8));
330
331 if (n == 15) {
332 return Err<Instr>(StatusCode::kDecoderUnpredictable);
333 }
334 flags |= static_cast<u8>(InstrFlags::k32Bit);
335
336 return Ok(Instr{InstrCmpImmediate{iid, flags, n, imm32}});
337}
338
339template <typename TCpuAccessor, typename TItOps>
340static Result<Instr> CmnImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
341 static_cast<void>(cpua); // prevents warning when cpua is not used
342 const InstrId iid{InstrId::kCmnImmediate};
343 u8 flags = 0x0U;
344
345 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
346 assert((Bm16::ExtractBits1R<9U, 4U>(rinstr.low)) == 0b010001U);
347 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
348 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
349
350 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
351 const u8 n = static_cast<u8>(Rn);
352 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
353 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
354 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
355 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm((i << 11U) | (imm3 << 8U) | imm8));
356
357 if (n == 15) {
358 return Err<Instr>(StatusCode::kDecoderUnpredictable);
359 }
360 flags |= static_cast<u8>(InstrFlags::k32Bit);
361
362 return Ok(Instr{InstrCmnImmediate{iid, flags, n, imm32}});
363}
364
365template <typename TCpuAccessor, typename TItOps>
366static Result<Instr> MovImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
367 static_cast<void>(cpua); // prevents warning when cpua is not used
368 const InstrId iid{InstrId::kMovImmediate};
369 u8 flags = 0x0U;
370
371 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b00100U);
372
373 flags |=
374 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
375 const u16 Rd = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
376 const u8 d = static_cast<u8>(Rd);
377 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
378 const u16 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
379 const auto imm32_carry =
380 ThumbImmediateResult{imm8, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk};
381
382 return Ok(Instr{InstrMovImmediate{iid, flags, d, imm32_carry}});
383}
384
385template <typename TCpuAccessor, typename TItOps>
386static Result<Instr> MovImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
387 static_cast<void>(cpua); // prevents warning when cpua is not used
388 const InstrId iid{InstrId::kMovImmediate};
389 u8 flags = 0x0U;
390
391 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
392 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b00010U);
393 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
394 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
395
396 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
397 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
398 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
399 const u8 d = static_cast<u8>(Rd);
400 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
401 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
402 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
403 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
404 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
405 TRY_ASSIGN(imm32_carry, Instr,
406 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
407
408 if (d == 13U || d == 15) {
409 return Err<Instr>(StatusCode::kDecoderUnpredictable);
410 }
411 flags |= static_cast<u8>(InstrFlags::k32Bit);
412
413 return Ok(Instr{InstrMovImmediate{iid, flags, d, imm32_carry}});
414}
415
416template <typename TCpuAccessor, typename TItOps>
417static Result<Instr> MovImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
418 static_cast<void>(cpua); // prevents warning when cpua is not used
419 const InstrId iid{InstrId::kMovImmediate};
420 u8 flags = 0x0U;
421
422 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
423 assert((Bm16::ExtractBits1R<9U, 4U>(rinstr.low)) == 0b100100U);
424 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
425
426 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
427 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
428 const u8 d = static_cast<u8>(Rd);
429 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
430 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
431 const u32 imm4 = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
432 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
433 const auto imm32_carry =
434 ThumbImmediateResult{(imm4 << 12U) | (i << 11U) | (imm3 << 8U) | imm8, false};
435
436 if (d == 13U || d == 15) {
437 return Err<Instr>(StatusCode::kDecoderUnpredictable);
438 }
439 flags |= static_cast<u8>(InstrFlags::k32Bit);
440
441 return Ok(Instr{InstrMovImmediate{iid, flags, d, imm32_carry}});
442}
443
444template <typename TCpuAccessor, typename TItOps>
445static Result<Instr> MvnImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
446 static_cast<void>(cpua); // prevents warning when cpua is not used
447 const InstrId iid{InstrId::kMvnImmediate};
448 u8 flags = 0x0U;
449
450 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
451 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b00011U);
452 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
453 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
454
455 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
456 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
457 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
458 const u8 d = static_cast<u8>(Rd);
459 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
460 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
461 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
462 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
463 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
464 TRY_ASSIGN(imm32_carry, Instr,
465 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
466
467 if (d == 13U || d == 15) {
468 return Err<Instr>(StatusCode::kDecoderUnpredictable);
469 }
470 flags |= static_cast<u8>(InstrFlags::k32Bit);
471
472 return Ok(Instr{InstrMvnImmediate{iid, flags, d, imm32_carry}});
473}
474
475template <typename TCpuAccessor, typename TItOps>
476static Result<Instr> TbbHT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
477 static_cast<void>(cpua); // prevents warning when cpua is not used
478 const InstrId iid{InstrId::kTbbH};
479 u8 flags = 0x0U;
480
481 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111010001101U);
482 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.high)) == 0b11110000000U);
483
484 const u32 H = Bm16::IsolateBit<4U>(rinstr.high);
485 flags |= H << static_cast<InstrFlagsSet>(InstrFlagsShift::kTbhShift);
486 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
487 const u8 m = static_cast<u8>(Rm);
488 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
489 const u8 n = static_cast<u8>(Rn);
490
491 if (n == 13U || m == 13U || m == 15U) {
492 return Err<Instr>(StatusCode::kDecoderUnpredictable);
493 }
494 if (TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
495 return Err<Instr>(StatusCode::kDecoderUnpredictable);
496 }
497 flags |= static_cast<u8>(InstrFlags::k32Bit);
498
499 return Ok(Instr{InstrTbbH{iid, flags, m, n}});
500}
501
502template <typename TCpuAccessor, typename TItOps>
503static Result<Instr> RsbImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
504 static_cast<void>(cpua); // prevents warning when cpua is not used
505 const InstrId iid{InstrId::kRsbImmediate};
506 u8 flags = 0x0U;
507
508 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100001001U);
509
510 flags |=
511 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
512 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
513 const u8 n = static_cast<u8>(Rn);
514 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
515 const u8 d = static_cast<u8>(Rd);
516 const u32 imm32 = 0x0U;
517
518 return Ok(Instr{InstrRsbImmediate{iid, flags, n, d, imm32}});
519}
520
521template <typename TCpuAccessor, typename TItOps>
522static Result<Instr> RsbImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
523 static_cast<void>(cpua); // prevents warning when cpua is not used
524 const InstrId iid{InstrId::kRsbImmediate};
525 u8 flags = 0x0U;
526
527 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
528 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01110U);
529 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
530
531 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
532 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
533 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
534 const u8 n = static_cast<u8>(Rn);
535 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
536 const u8 d = static_cast<u8>(Rd);
537 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
538 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
539 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
540
541 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
542 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
543
544 if (d == 13U || d == 15U || n == 13U || n == 15U) {
545 return Err<Instr>(StatusCode::kDecoderUnpredictable);
546 }
547 flags |= static_cast<u8>(InstrFlags::k32Bit);
548
549 return Ok(Instr{InstrRsbImmediate{iid, flags, n, d, imm32}});
550}
551
552template <typename TCpuAccessor, typename TItOps>
553static Result<Instr> MovRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
554 static_cast<void>(cpua); // prevents warning when cpua is not used
555 const InstrId iid{InstrId::kMovRegister};
556 u8 flags = 0x0U;
557
558 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.low)) == 0x6U);
559
560 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
561 const u16 Rd = Bm32::ExtractBits2R<7U, 7U, 2U, 0U>(rinstr.low);
562 const u8 d = static_cast<u8>(Rd);
563 const u16 Rm = Bm16::ExtractBits1R<6U, 3U>(rinstr.low);
564 const u8 m = static_cast<u8>(Rm);
565
566 if (d == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
567 return Err<Instr>(StatusCode::kDecoderUnpredictable);
568 }
569
570 return Ok(Instr{InstrMovRegister{iid, flags, d, m}});
571}
572
573template <typename TCpuAccessor, typename TItOps>
574static Result<Instr> MovRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
575 static_cast<void>(cpua); // prevents warning when cpua is not used
576 const InstrId iid{InstrId::kMovRegister};
577 u8 flags = 0x0U;
578
579 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0000000000U);
580
581 flags |= static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
582 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
583 const u8 d = static_cast<u8>(Rd);
584 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
585 const u8 m = static_cast<u8>(Rm);
586
587 if (TItOps::InITBlock(cpua)) {
588 return Err<Instr>(StatusCode::kDecoderUnpredictable);
589 }
590
591 return Ok(Instr{InstrMovRegister{iid, flags, d, m}});
592}
593
594template <typename TCpuAccessor, typename TItOps>
595static Result<Instr> MovRegisterT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
596 static_cast<void>(cpua); // prevents warning when cpua is not used
597 const InstrId iid{InstrId::kMovRegister};
598 u8 flags = 0x0U;
599
600 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010010U);
601 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
602 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b0000U);
603 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
604
605 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
606 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
607 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
608 const u8 d = static_cast<u8>(Rd);
609 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
610 const u8 m = static_cast<u8>(Rm);
611
612 if ((flags & static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) != 0U) &&
613 (d == 13U || d == 15U || m == 13U || m == 15U)) {
614 return Err<Instr>(StatusCode::kDecoderUnpredictable);
615 }
616 if ((flags & static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) == 0U) &&
617 (d == 15U || m == 15U || (d == 13U && m == 13U))) {
618 return Err<Instr>(StatusCode::kDecoderUnpredictable);
619 }
620 flags |= static_cast<u8>(InstrFlags::k32Bit);
621
622 return Ok(Instr{InstrMovRegister{iid, flags, d, m}});
623}
624
625template <typename TCpuAccessor, typename TItOps>
626static Result<Instr> RrxT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
627 static_cast<void>(cpua); // prevents warning when cpua is not used
628 const InstrId iid{InstrId::kRrx};
629 u8 flags = 0x0U;
630
631 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010010U);
632 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
633 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b0000U);
634 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0011U);
635
636 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
637 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
638 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
639 const u8 d = static_cast<u8>(Rd);
640 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
641 const u8 m = static_cast<u8>(Rm);
642
643 if ((d == 13U) || (d == 15U) || (m == 13U) || (m == 15U)) {
644 return Err<Instr>(StatusCode::kDecoderUnpredictable);
645 }
646 flags |= static_cast<u8>(InstrFlags::k32Bit);
647
648 return Ok(Instr{InstrRrx{iid, flags, d, m}});
649}
650
651template <typename TCpuAccessor, typename TItOps>
652static Result<Instr> LdrLiteralT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
653 static_cast<void>(cpua); // prevents warning when cpua is not used
654 const InstrId iid{InstrId::kLdrLiteral};
655 u8 flags = 0x0U;
656
657 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
658 const u16 Rt = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
659 const u8 t = static_cast<u8>(Rt);
660 const u16 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
661 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8) << 2U;
662
663 return Ok(Instr{InstrLdrLiteral{iid, flags, t, imm32}});
664}
665
666template <typename TCpuAccessor, typename TItOps>
667static Result<Instr> LdrLiteralT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
668 static_cast<void>(cpua); // prevents warning when cpua is not used
669 const InstrId iid{InstrId::kLdrLiteral};
670 u8 flags = 0x0U;
671
672 assert((Bm16::ExtractBits1R<15U, 8U>(rinstr.low)) == 0b11111000U);
673 assert((Bm16::ExtractBits1R<6U, 0U>(rinstr.low)) == 0b1011111U);
674
675 const u32 U = Bm16::IsolateBit<7U>(rinstr.low);
676 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
677 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
678 const u8 t = static_cast<u8>(Rt);
679 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
680 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
681
682 if (t == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
683 return Err<Instr>(StatusCode::kDecoderUnpredictable);
684 }
685 flags |= static_cast<u8>(InstrFlags::k32Bit);
686
687 return Ok(Instr{InstrLdrLiteral{iid, flags, t, imm32}});
688}
689
690template <typename TCpuAccessor, typename TItOps>
691static Result<Instr> LdrbImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
692 static_cast<void>(cpua); // prevents warning when cpua is not used
693 const InstrId iid{InstrId::kLdrbImmediate};
694 u8 flags = 0x0U;
695
696 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b01111U);
697
698 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
699 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
700 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
701 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
702 const u8 t = static_cast<u8>(Rt);
703 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
704 const u8 n = static_cast<u8>(Rn);
705 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
706 const u32 imm32 = Bm32::ZeroExtend<u32>(imm5);
707
708 return Ok(Instr{InstrLdrbImmediate{iid, flags, t, n, imm32}});
709}
710
711template <typename TCpuAccessor, typename TItOps>
712static Result<Instr> LdrbImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
713 static_cast<void>(cpua); // prevents warning when cpua is not used
714 const InstrId iid{InstrId::kLdrbImmediate};
715 u8 flags = 0x0U;
716
717 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110001001U);
718
719 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
720 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
721 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
722 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
723 const u8 t = static_cast<u8>(Rt);
724 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
725 const u8 n = static_cast<u8>(Rn);
726 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
727 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
728
729 assert(Rt != 0b1111U);
730 assert(Rn != 0b1111U);
731 if (t == 13U) {
732 return Err<Instr>(StatusCode::kDecoderUnpredictable);
733 }
734 flags |= static_cast<u8>(InstrFlags::k32Bit);
735
736 return Ok(Instr{InstrLdrbImmediate{iid, flags, t, n, imm32}});
737}
738
739template <typename TCpuAccessor, typename TItOps>
740static Result<Instr> LdrbImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
741 static_cast<void>(cpua); // prevents warning when cpua is not used
742 const InstrId iid{InstrId::kLdrbImmediate};
743 u8 flags = 0x0U;
744
745 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000001U);
746 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
747
748 const u32 U = Bm16::IsolateBit<9U>(rinstr.high);
749 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
750 const u32 P = Bm16::IsolateBit<10U>(rinstr.high);
751 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
752 const u32 W = Bm16::IsolateBit<8U>(rinstr.high);
753 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
754 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
755 const u8 t = static_cast<u8>(Rt);
756 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
757 const u8 n = static_cast<u8>(Rn);
758 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
759 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
760
761 assert((Rt != 0b1111U) || (P != 1U) || (U != 0U) || (W != 0U));
762 assert(Rn != 0b1111U);
763 assert((P != 0b1U) || (U != 0b1U) || (W != 0b0U));
764 assert((Rn != 0b1101U) || (P != 0x0U) || (U != 0x1U) || (W != 0x1U) || (imm8 != 0b00000100U));
765 if ((P == 0x0U) && (W == 0x0U)) {
766 return Err<Instr>(StatusCode::kDecoderUndefined);
767 }
768 if (t == 13U || (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
769 return Err<Instr>(StatusCode::kDecoderUnpredictable);
770 }
771 if (t == 15U && ((P == 0U) || (U == 1U) || (W == 1U))) {
772 return Err<Instr>(StatusCode::kDecoderUnpredictable);
773 }
774 flags |= static_cast<u8>(InstrFlags::k32Bit);
775
776 return Ok(Instr{InstrLdrbImmediate{iid, flags, t, n, imm32}});
777}
778
779template <typename TCpuAccessor, typename TItOps>
780static Result<Instr> LdrsbImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
781 static_cast<void>(cpua); // prevents warning when cpua is not used
782 const InstrId iid{InstrId::kLdrsbImmediate};
783 u8 flags = 0x0U;
784
785 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110011001U);
786
787 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
788 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
789 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
790 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
791 const u8 t = static_cast<u8>(Rt);
792 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
793 const u8 n = static_cast<u8>(Rn);
794 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
795 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
796
797 assert(Rt != 0b1111U);
798 assert(Rn != 0b1111U);
799 if (t == 13U) {
800 return Err<Instr>(StatusCode::kDecoderUnpredictable);
801 }
802 flags |= static_cast<u8>(InstrFlags::k32Bit);
803
804 return Ok(Instr{InstrLdrsbImmediate{iid, flags, t, n, imm32}});
805}
806
807template <typename TCpuAccessor, typename TItOps>
808static Result<Instr> LdrsbImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
809 static_cast<void>(cpua); // prevents warning when cpua is not used
810 const InstrId iid{InstrId::kLdrsbImmediate};
811 u8 flags = 0x0U;
812
813 assert(false); // not tested
814 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110010001U);
815 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
816
817 const u32 U = Bm16::IsolateBit<9U>(rinstr.high);
818 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
819 const u32 P = Bm16::IsolateBit<10U>(rinstr.high);
820 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
821 const u32 W = Bm16::IsolateBit<8U>(rinstr.high);
822 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
823 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
824 const u8 t = static_cast<u8>(Rt);
825 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
826 const u8 n = static_cast<u8>(Rn);
827 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
828 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
829
830 assert((Rt != 0b1111U) || (P != 1U) || (U != 0U) || (W != 0U));
831 assert(Rn != 0b1111U);
832 assert((P != 0b1U) || (U != 0b1U) || (W != 0b0U));
833 assert((Rn != 0b1101U) || (P != 0x0U) || (U != 0x1U) || (W != 0x1U) || (imm8 != 0b00000100U));
834 if ((P == 0x0U) && (W == 0x0U)) {
835 return Err<Instr>(StatusCode::kDecoderUndefined);
836 }
837 if (t == 13U || (t == 15U && (W == 1U)) ||
838 (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
839 return Err<Instr>(StatusCode::kDecoderUnpredictable);
840 }
841 flags |= static_cast<u8>(InstrFlags::k32Bit);
842
843 return Ok(Instr{InstrLdrsbImmediate{iid, flags, t, n, imm32}});
844}
845
846template <typename TCpuAccessor, typename TItOps>
847static Result<Instr> LdrshImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
848 static_cast<void>(cpua); // prevents warning when cpua is not used
849 const InstrId iid{InstrId::kLdrshImmediate};
850 u8 flags = 0x0U;
851
852 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110011011U);
853
854 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
855 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
856 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
857 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
858 const u8 t = static_cast<u8>(Rt);
859 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
860 const u8 n = static_cast<u8>(Rn);
861 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
862 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
863
864 assert(Rn != 0b1111U);
865 assert(Rt != 0b1111U);
866 if (t == 13U) {
867 return Err<Instr>(StatusCode::kDecoderUnpredictable);
868 }
869 flags |= static_cast<u8>(InstrFlags::k32Bit);
870
871 return Ok(Instr{InstrLdrshImmediate{iid, flags, t, n, imm32}});
872}
873
874template <typename TCpuAccessor, typename TItOps>
875static Result<Instr> LdrshImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
876 static_cast<void>(cpua); // prevents warning when cpua is not used
877 const InstrId iid{InstrId::kLdrshImmediate};
878 u8 flags = 0x0U;
879
880 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110010011U);
881 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
882
883 const u32 U = static_cast<u32>(Bm16::IsolateBit<9U>(rinstr.high));
884 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
885 const u32 P = static_cast<u32>(Bm16::IsolateBit<10U>(rinstr.high));
886 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
887 const u32 W = static_cast<u32>(Bm16::IsolateBit<8U>(rinstr.high));
888 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
889 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
890 const u8 t = static_cast<u8>(Rt);
891 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
892 const u8 n = static_cast<u8>(Rn);
893 const u32 imm8 = static_cast<u32>(Bm16::ExtractBits1R<7U, 0U>(rinstr.high));
894 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
895
896 assert(Rn != 0b1111U);
897 assert(Rt != 0b1111U || P != 1U || U != 0U || W != 0U);
898 assert(P != 0b1U || U != 0b1U || W != 0b0U);
899 if (P == 0b0U && W == 0b0U) {
900 return Err<Instr>(StatusCode::kDecoderUndefined);
901 }
902 if (t == 13U || (t == 15U && W == 1U) ||
903 (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
904 return Err<Instr>(StatusCode::kDecoderUnpredictable);
905 }
906 flags |= static_cast<u8>(InstrFlags::k32Bit);
907
908 return Ok(Instr{InstrLdrshImmediate{iid, flags, t, n, imm32}});
909}
910
911template <typename TCpuAccessor, typename TItOps>
912static Result<Instr> LdrhImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
913 static_cast<void>(cpua); // prevents warning when cpua is not used
914 const InstrId iid{InstrId::kLdrhImmediate};
915 u8 flags = 0x0U;
916
917 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b10001U);
918
919 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
920 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
921 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
922 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
923 const u8 t = static_cast<u8>(Rt);
924 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
925 const u8 n = static_cast<u8>(Rn);
926 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
927 const u32 imm32 = Bm32::ZeroExtend<u32>(imm5 << 1U);
928
929 return Ok(Instr{InstrLdrhImmediate{iid, flags, t, n, imm32}});
930}
931
932template <typename TCpuAccessor, typename TItOps>
933static Result<Instr> LdrhImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
934 static_cast<void>(cpua); // prevents warning when cpua is not used
935 const InstrId iid{InstrId::kLdrhImmediate};
936 u8 flags = 0x0U;
937
938 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110001011U);
939
940 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
941 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
942 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
943 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
944 const u8 t = static_cast<u8>(Rt);
945 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
946 const u8 n = static_cast<u8>(Rn);
947 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
948 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
949
950 assert(Rt != 0b1111U);
951 assert(Rn != 0b1111U);
952 if (t == 13U) {
953 return Err<Instr>(StatusCode::kDecoderUnpredictable);
954 }
955 flags |= static_cast<u8>(InstrFlags::k32Bit);
956
957 return Ok(Instr{InstrLdrhImmediate{iid, flags, t, n, imm32}});
958}
959
960template <typename TCpuAccessor, typename TItOps>
961static Result<Instr> LdrhImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
962 static_cast<void>(cpua); // prevents warning when cpua is not used
963 const InstrId iid{InstrId::kLdrhImmediate};
964 u8 flags = 0x0U;
965
966 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000011U);
967 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
968
969 const u32 U = static_cast<u32>(Bm16::IsolateBit<9U>(rinstr.high));
970 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
971 const u32 P = static_cast<u32>(Bm16::IsolateBit<10U>(rinstr.high));
972 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
973 const u32 W = static_cast<u32>(Bm16::IsolateBit<8U>(rinstr.high));
974 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
975 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
976 const u8 t = static_cast<u8>(Rt);
977 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
978 const u8 n = static_cast<u8>(Rn);
979 const u32 imm8 = static_cast<u32>(Bm16::ExtractBits1R<7U, 0U>(rinstr.high));
980 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
981
982 assert(Rn != 0b1111U);
983 assert(Rt != 0b1111U || P != 1U || U != 0U || W != 0U);
984 assert(P != 0b1U || U != 0b1U || W != 0b0U);
985 if (P == 0b0U && W == 0b0U) {
986 return Err<Instr>(StatusCode::kDecoderUndefined);
987 }
988 if (t == 13U || (t == 15U && W == 1U) ||
989 (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
990 return Err<Instr>(StatusCode::kDecoderUnpredictable);
991 }
992 flags |= static_cast<u8>(InstrFlags::k32Bit);
993
994 return Ok(Instr{InstrLdrhImmediate{iid, flags, t, n, imm32}});
995}
996
997template <typename TCpuAccessor, typename TItOps>
998static Result<Instr> PopT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
999 static_cast<void>(cpua); // prevents warning when cpua is not used
1000 const InstrId iid{InstrId::kPop};
1001 u8 flags = 0x0U;
1002
1003 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b1011110U);
1004
1005 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
1006 const u32 P = Bm16::IsolateBit<8U>(rinstr.low);
1007 const u32 register_list = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
1008 const u32 registers = (P << 15U) | register_list;
1009
1010 if (Bm32::BitCount(registers) < 1U) {
1011 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1012 }
1013 if ((Bm32::ExtractBits1R<15U, 15U>(registers) == 0x1U) && (TItOps::InITBlock(cpua)) &&
1014 (!TItOps::LastInITBlock(cpua))) {
1015 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1016 }
1017
1018 return Ok(Instr{InstrPop{iid, flags, registers}});
1019}
1020
1021template <typename TCpuAccessor, typename TItOps>
1022static Result<Instr> PopT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1023 static_cast<void>(cpua); // prevents warning when cpua is not used
1024 const InstrId iid{InstrId::kPop};
1025 u8 flags = 0x0U;
1026
1027 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1110100010111101U);
1028 assert((Bm16::IsolateBit<13U>(rinstr.high)) == 0b0U);
1029
1030 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
1031 const u32 P = Bm16::IsolateBit<15U>(rinstr.high);
1032 const u32 M = Bm16::IsolateBit<14U>(rinstr.high);
1033 const u32 register_list = Bm16::ExtractBits1R<12U, 0U>(rinstr.high);
1034 const u32 registers = (P << 15U) | (M << 14U) | register_list;
1035
1036 if ((Bm32::BitCount(registers) < 2U) || ((P == 1U) && M == 1U)) {
1037 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1038 }
1039 if ((Bm32::ExtractBits1R<15U, 15U>(registers) == 0x1U) && (TItOps::InITBlock(cpua)) &&
1040 (!TItOps::LastInITBlock(cpua))) {
1041 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1042 }
1043 flags |= static_cast<u8>(InstrFlags::k32Bit);
1044
1045 return Ok(Instr{InstrPop{iid, flags, registers}});
1046}
1047
1048template <typename TCpuAccessor, typename TItOps>
1049static Result<Instr> PopT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1050 static_cast<void>(cpua); // prevents warning when cpua is not used
1051 const InstrId iid{InstrId::kPop};
1052 u8 flags = 0x0U;
1053
1054 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1111100001011101U);
1055 assert((Bm16::ExtractBits1R<11U, 0U>(rinstr.high)) == 0b101100000100U);
1056
1057 flags |= static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
1058 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
1059 const u8 t = static_cast<u8>(Rt);
1060 const u32 registers = 1U << Rt;
1061
1062 if (t == 13U || (t == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua))) {
1063 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1064 }
1065 flags |= static_cast<u8>(InstrFlags::k32Bit);
1066
1067 return Ok(Instr{InstrPop{iid, flags, registers}});
1068}
1069
1070template <typename TCpuAccessor, typename TItOps>
1071static Result<Instr> LdrImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1072 static_cast<void>(cpua); // prevents warning when cpua is not used
1073 const InstrId iid{InstrId::kLdrImmediate};
1074 u8 flags = 0x0U;
1075
1076 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b01101U);
1077
1078 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
1079 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
1080 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
1081 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
1082 const u8 t = static_cast<u8>(Rt);
1083 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
1084 const u8 n = static_cast<u8>(Rn);
1085 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
1086 const u32 imm32 = Bm32::ZeroExtend<u32>(imm5 << 2U);
1087
1088 return Ok(Instr{InstrLdrImmediate{iid, flags, t, n, imm32}});
1089}
1090
1091template <typename TCpuAccessor, typename TItOps>
1092static Result<Instr> LdrImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1093 static_cast<void>(cpua); // prevents warning when cpua is not used
1094 const InstrId iid{InstrId::kLdrImmediate};
1095 u8 flags = 0x0U;
1096
1097 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b10011U);
1098
1099 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
1100 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
1101 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
1102 const u16 Rt = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
1103 const u8 t = static_cast<u8>(Rt);
1104 const u8 n = 13U;
1105 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
1106 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8 << 2U);
1107
1108 return Ok(Instr{InstrLdrImmediate{iid, flags, t, n, imm32}});
1109}
1110
1111template <typename TCpuAccessor, typename TItOps>
1112static Result<Instr> LdrImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1113 static_cast<void>(cpua); // prevents warning when cpua is not used
1114 const InstrId iid{InstrId::kLdrImmediate};
1115 u8 flags = 0x0U;
1116
1117 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110001101U);
1118
1119 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
1120 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
1121 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
1122 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
1123 const u8 t = static_cast<u8>(Rt);
1124 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1125 const u8 n = static_cast<u8>(Rn);
1126 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
1127 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
1128
1129 if (t == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
1130 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1131 }
1132 flags |= static_cast<u8>(InstrFlags::k32Bit);
1133
1134 return Ok(Instr{InstrLdrImmediate{iid, flags, t, n, imm32}});
1135}
1136
1137template <typename TCpuAccessor, typename TItOps>
1138static Result<Instr> LdrImmediateT4Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1139 static_cast<void>(cpua); // prevents warning when cpua is not used
1140 const InstrId iid{InstrId::kLdrImmediate};
1141 u8 flags = 0x0U;
1142
1143 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000101U);
1144 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
1145
1146 const u32 U = Bm16::IsolateBit<9U>(rinstr.high);
1147 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
1148 const u32 P = Bm16::IsolateBit<10U>(rinstr.high);
1149 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
1150 const u32 W = Bm16::IsolateBit<8U>(rinstr.high);
1151 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
1152 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
1153 const u8 t = static_cast<u8>(Rt);
1154 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1155 const u8 n = static_cast<u8>(Rn);
1156 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1157 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
1158
1159 assert(Rn != 0b1111U);
1160 assert((P != 0b1U) || (U != 0b1U) || (W != 0b0U));
1161 if ((Rn == 0b1101U) && (P == 0x0U) && (U == 0x1U) && (W == 0x1U) && (imm8 == 0b00000100U)) {
1162 // SEE POP
1163 return PopT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
1164 }
1165 if ((P == 0x0U) && (W == 0x0U)) {
1166 return Err<Instr>(StatusCode::kDecoderUndefined);
1167 }
1168 if ((flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t) ||
1169 t == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
1170 return Err<Instr>(StatusCode::kDecoderUndefined);
1171 }
1172 flags |= static_cast<u8>(InstrFlags::k32Bit);
1173
1174 return Ok(Instr{InstrLdrImmediate{iid, flags, t, n, imm32}});
1175}
1176
1177template <typename TCpuAccessor, typename TItOps>
1178static Result<Instr> LdrexT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1179 static_cast<void>(cpua); // prevents warning when cpua is not used
1180 const InstrId iid{InstrId::kLdrex};
1181 u8 flags = 0x0U;
1182
1183 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111010000101U);
1184 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
1185
1186 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
1187 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
1188 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
1189 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
1190 const u8 t = static_cast<u8>(Rt);
1191 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1192 const u8 n = static_cast<u8>(Rn);
1193 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1194 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
1195
1196 if (t == 13U || t == 15U || n == 15U) {
1197 return Err<Instr>(StatusCode::kDecoderUndefined);
1198 }
1199 flags |= static_cast<u8>(InstrFlags::k32Bit);
1200
1201 return Ok(Instr{InstrLdrex{iid, flags, t, n, imm32}});
1202}
1203
1204template <typename TCpuAccessor, typename TItOps>
1205static Result<Instr> LdrdImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1206 static_cast<void>(cpua); // prevents warning when cpua is not used
1207 const InstrId iid{InstrId::kLdrdImmediate};
1208 u8 flags = 0x0U;
1209
1210 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b1110100U);
1211 assert((Bm16::IsolateBit<6U>(rinstr.low)) == 0b1U);
1212 assert((Bm16::IsolateBit<4U>(rinstr.low)) == 0b1U);
1213
1214 const u32 U = Bm16::IsolateBit<7U>(rinstr.low);
1215 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
1216 const u32 P = Bm16::IsolateBit<8U>(rinstr.low);
1217 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
1218 const u32 W = Bm16::IsolateBit<5U>(rinstr.low);
1219 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
1220 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
1221 const u8 t = static_cast<u8>(Rt);
1222 const u32 Rt2 = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1223 const u8 t2 = static_cast<u8>(Rt2);
1224 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1225 const u8 n = static_cast<u8>(Rn);
1226 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1227 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8 << 2U);
1228
1229 assert((P != 0U) || (W != 0));
1230 assert(Rn != 0b1111U);
1231 if (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && ((n == t) || (n == t2))) {
1232 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1233 }
1234 if (t == 13U || t == 15 || (t2 == 13U) || (t2 == 15) || (t == t2)) {
1235 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1236 }
1237 flags |= static_cast<u8>(InstrFlags::k32Bit);
1238
1239 return Ok(Instr{InstrLdrdImmediate{iid, flags, t, t2, n, imm32}});
1240}
1241
1242template <typename TCpuAccessor, typename TItOps>
1243static Result<Instr> ItT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1244 static_cast<void>(cpua); // prevents warning when cpua is not used
1245 const InstrId iid{InstrId::kIt};
1246 u8 flags = 0x0U;
1247
1248 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.low)) == 0xFU);
1249
1250 const u32 firstcond_32 = Bm16::ExtractBits1R<7U, 4U>(rinstr.low);
1251 const u8 firstcond = static_cast<u8>(firstcond_32);
1252 const u32 mask_32 = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1253 const u8 mask = static_cast<u8>(mask_32);
1254
1255 assert(mask != 0x0U);
1256 if (firstcond == 0xFU || (firstcond == 0b1110U && Bm8::BitCount(mask) != 1U)) {
1257 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1258 }
1259
1260 if (TItOps::InITBlock(cpua)) {
1261 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1262 }
1263
1264 return Ok(Instr{InstrIt{iid, flags, firstcond, mask}});
1265}
1266
1267template <typename TCpuAccessor, typename TItOps>
1268static Result<Instr> BlT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1269 static_cast<void>(cpua); // prevents warning when cpua is not used
1270 const InstrId iid{InstrId::kBl};
1271 u8 flags = 0x0U;
1272
1273 assert((Bm16::ExtractBits1R<15U, 14U>(rinstr.high)) == 0x3U);
1274 assert((Bm16::IsolateBit<12U>(rinstr.high)) == 0x1U);
1275 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1276
1277 const u32 s = Bm16::IsolateBit<10U>(rinstr.low);
1278 const u32 imm10 = Bm16::ExtractBits1R<9U, 0U>(rinstr.low);
1279 const u32 j1 = Bm16::IsolateBit<13U>(rinstr.high); // bit 13
1280 const u32 j2 = Bm16::IsolateBit<11U>(rinstr.high); // bit 11
1281 const u32 imm11 = Bm16::ExtractBits1R<10U, 0U>(rinstr.high); // bit 10..0
1282 const u32 i1 = (~(j1 ^ s)) & 0x1U;
1283 const u32 i2 = (~(j2 ^ s)) & 0x1U;
1284 const u32 imm32_us = (s << 24U) | (i1 << 23U) | (i2 << 22U) | (imm10 << 12U) | imm11 << 1U;
1285 const i32 imm32 = static_cast<int32_t>(Bm32::SignExtend<u32, 24U>(imm32_us));
1286
1287 if (TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
1288 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1289 }
1290 flags |= static_cast<u8>(InstrFlags::k32Bit);
1291
1292 return Ok(Instr{InstrBl{iid, flags, imm32}});
1293}
1294
1295template <typename TCpuAccessor, typename TItOps>
1296static Result<Instr> BxT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1297 static_cast<void>(cpua); // prevents warning when cpua is not used
1298 const InstrId iid{InstrId::kBx};
1299 u8 flags = 0x0U;
1300
1301 assert((Bm16::ExtractBits1R<15U, 7U>(rinstr.low) == 0b010001110U));
1302
1303 const u16 Rm = Bm16::ExtractBits1R<6U, 3U>(rinstr.low);
1304 const u8 m = static_cast<u8>(Rm);
1305
1306 if (TItOps::InITBlock(cpua) && (!TItOps::LastInITBlock(cpua))) {
1307 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1308 }
1309
1310 return Ok(Instr{InstrBx{iid, flags, m}});
1311}
1312
1313template <typename TCpuAccessor, typename TItOps>
1314static Result<Instr> BlxT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1315 static_cast<void>(cpua); // prevents warning when cpua is not used
1316 const InstrId iid{InstrId::kBlx};
1317 u8 flags = 0x0U;
1318
1319 assert((Bm16::ExtractBits1R<15U, 7U>(rinstr.low) == 0b010001111U));
1320
1321 const u16 Rm = Bm16::ExtractBits1R<6U, 3U>(rinstr.low);
1322 const u8 m = static_cast<u8>(Rm);
1323
1324 if (m == 15U) {
1325 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1326 }
1327 if (TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
1328 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1329 }
1330
1331 return Ok(Instr{InstrBlx{iid, flags, m}});
1332}
1333
1334template <typename TCpuAccessor, typename TItOps>
1335static Result<Instr> BT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1336 static_cast<void>(cpua); // prevents warning when cpua is not used
1337 const InstrId iid{InstrId::kBCond};
1338 u8 flags = 0x0U;
1339
1340 if (TItOps::InITBlock(cpua)) {
1341 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1342 }
1343
1344 const u32 cond_32 = Bm16::ExtractBits1R<11U, 8U>(rinstr.low);
1345 const u8 cond = static_cast<u8>(cond_32);
1346 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
1347 const i32 imm32 = Bm32::SignExtend<u32, 8U>(imm8 << 1U);
1348
1349 assert(cond != 0b1110U);
1350 assert(cond != 0b1111U);
1351
1352 return Ok(Instr{InstrBCond{iid, flags, cond, imm32}});
1353}
1354
1355template <typename TCpuAccessor, typename TItOps>
1356static Result<Instr> BT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1357 static_cast<void>(cpua); // prevents warning when cpua is not used
1358 const InstrId iid{InstrId::kB};
1359 u8 flags = 0x0U;
1360
1361 const u32 imm_11_32 = Bm16::ExtractBits1R<10U, 0U>(rinstr.low);
1362 const i32 imm32 = Bm32::SignExtend<u32, 11U>((imm_11_32) << 1U);
1363
1364 if (TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
1365 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1366 }
1367
1368 return Ok(Instr{InstrB{iid, flags, imm32}});
1369}
1370
1371template <typename TCpuAccessor, typename TItOps>
1372static Result<Instr> BT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1373 static_cast<void>(cpua); // prevents warning when cpua is not used
1374 const InstrId iid{InstrId::kBCond};
1375 u8 flags = 0x0U;
1376
1377 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1378 assert((Bm16::ExtractBits1R<15U, 14U>(rinstr.high)) == 0b10U);
1379 assert((Bm16::IsolateBit<12U>(rinstr.high)) == 0b0U);
1380
1381 const u32 cond_32 = Bm16::ExtractBits1R<9U, 6U>(rinstr.low);
1382 const u8 cond = static_cast<u8>(cond_32);
1383 const u32 imm11 = Bm16::ExtractBits1R<10U, 0U>(rinstr.high);
1384 const u32 imm6 = Bm16::ExtractBits1R<5U, 0U>(rinstr.low);
1385 const u32 J1 = Bm16::IsolateBit<13U>(rinstr.high); // bit 13
1386 const u32 J2 = Bm16::IsolateBit<11U>(rinstr.high); // bit 11
1387 const u32 S = Bm16::IsolateBit<10U>(rinstr.low);
1388 const u32 imm32_us = (S << 20U) | (J2 << 19U) | (J1 << 18U) | (imm6 << 12U) | (imm11 << 1U);
1389 const i32 imm32 = static_cast<int32_t>(Bm32::SignExtend<u32, 20U>(imm32_us));
1390
1391 if (TItOps::InITBlock(cpua)) {
1392 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1393 }
1394 flags |= static_cast<u8>(InstrFlags::k32Bit);
1395
1396 return Ok(Instr{InstrBCond{iid, flags, cond, imm32}});
1397}
1398
1399template <typename TCpuAccessor, typename TItOps>
1400static Result<Instr> BT4Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1401 static_cast<void>(cpua); // prevents warning when cpua is not used
1402 const InstrId iid{InstrId::kB};
1403 u8 flags = 0x0U;
1404
1405 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1406 assert((Bm16::ExtractBits1R<15U, 14U>(rinstr.high)) == 0b10U);
1407 assert((Bm16::IsolateBit<12U>(rinstr.high)) == 0b1U);
1408
1409 const u32 imm11 = Bm16::ExtractBits1R<10U, 0U>(rinstr.high);
1410 const u32 imm10 = Bm16::ExtractBits1R<9U, 0U>(rinstr.low);
1411 const u32 J1 = Bm16::IsolateBit<13U>(rinstr.high); // bit 13
1412 const u32 J2 = Bm16::IsolateBit<11U>(rinstr.high); // bit 11
1413 const u32 S = Bm16::IsolateBit<10U>(rinstr.low);
1414 const u32 I1 = (~(J1 ^ S)) & 0x1U;
1415 const u32 I2 = (~(J2 ^ S)) & 0x1U;
1416 const u32 imm32_us = (S << 24U) | (I1 << 23U) | (I2 << 22U) | (imm10 << 12U) | imm11 << 1U;
1417 const i32 imm32 = static_cast<int32_t>(Bm32::SignExtend<u32, 24U>(imm32_us));
1418
1419 if (TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
1420 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1421 }
1422 flags |= static_cast<u8>(InstrFlags::k32Bit);
1423
1424 return Ok(Instr{InstrB{iid, flags, imm32}});
1425}
1426
1427template <typename TCpuAccessor, typename TItOps>
1428static Result<Instr> SubSpMinusImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1429 static_cast<void>(cpua); // prevents warning when cpua is not used
1430 const InstrId iid{InstrId::kSubSpMinusImmediate};
1431 u8 flags = 0x0U;
1432
1433 assert((Bm16::ExtractBits1R<15U, 7U>(rinstr.low)) == 0b101100001U);
1434
1435 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1436 const u8 d = 13U;
1437 const u32 imm7 = Bm16::ExtractBits1R<6U, 0U>(rinstr.low);
1438 const u32 imm32 = Bm32::ZeroExtend<u32>(imm7 << 2);
1439
1440 return Ok(Instr{InstrSubSpMinusImmediate{iid, flags, d, imm32}});
1441}
1442
1443template <typename TCpuAccessor, typename TItOps>
1444static Result<Instr> SubSpMinusImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1445 static_cast<void>(cpua); // prevents warning when cpua is not used
1446 const InstrId iid{InstrId::kSubSpMinusImmediate};
1447 u8 flags = 0x0U;
1448
1449 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1450 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01101U);
1451 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1101U);
1452 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1453
1454 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1455 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1456 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1457 const u8 d = static_cast<u8>(Rd);
1458 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1459 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1460 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1461
1462 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1463 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
1464
1465 assert((d != 0b1111U) || (S != 1U));
1466 if (d == 15U && (S == 0x0U)) {
1467 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1468 }
1469 flags |= static_cast<u8>(InstrFlags::k32Bit);
1470
1471 return Ok(Instr{InstrSubSpMinusImmediate{iid, flags, d, imm32}});
1472}
1473
1474template <typename TCpuAccessor, typename TItOps>
1475static Result<Instr> SubSpMinusImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1476 static_cast<void>(cpua); // prevents warning when cpua is not used
1477 const InstrId iid{InstrId::kSubSpMinusImmediate};
1478 u8 flags = 0x0U;
1479
1480 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1481 assert((Bm16::ExtractBits1R<9U, 0U>(rinstr.low)) == 0b1010101101U);
1482 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1483
1484 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1485 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1486 const u8 d = static_cast<u8>(Rd);
1487 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1488 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1489 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1490
1491 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1492 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
1493
1494 if (d == 15U) {
1495 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1496 }
1497 flags |= static_cast<u8>(InstrFlags::k32Bit);
1498
1499 return Ok(Instr{InstrSubSpMinusImmediate{iid, flags, d, imm32}});
1500}
1501
1502template <typename TCpuAccessor, typename TItOps>
1503static Result<Instr> SubImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1504 static_cast<void>(cpua); // prevents warning when cpua is not used
1505 const InstrId iid{InstrId::kSubImmediate};
1506 u8 flags = 0x0U;
1507
1508 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0001111U);
1509
1510 flags |=
1511 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
1512 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<5U, 3U>(rinstr.low));
1513 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<2U, 0U>(rinstr.low));
1514 const u32 imm3 = Bm16::ExtractBits1R<8U, 6U>(rinstr.low);
1515 const u32 imm32 = Bm32::ZeroExtend<u32>(imm3);
1516
1517 return Ok(Instr{InstrSubImmediate{iid, flags, n, d, imm32}});
1518}
1519
1520template <typename TCpuAccessor, typename TItOps>
1521static Result<Instr> SubImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1522 static_cast<void>(cpua); // prevents warning when cpua is not used
1523 const InstrId iid{InstrId::kSubImmediate};
1524 u8 flags = 0x0U;
1525
1526 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b00111U);
1527
1528 flags |=
1529 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
1530 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<10U, 8U>(rinstr.low));
1531 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<10U, 8U>(rinstr.low));
1532 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
1533 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
1534
1535 return Ok(Instr{InstrSubImmediate{iid, flags, n, d, imm32}});
1536}
1537
1538template <typename TCpuAccessor, typename TItOps>
1539static Result<Instr> SubImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1540 static_cast<void>(cpua); // prevents warning when cpua is not used
1541 const InstrId iid{InstrId::kSubImmediate};
1542 u8 flags = 0x0U;
1543
1544 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1545 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01101U);
1546 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1547
1548 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1549 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1550 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1551 const u8 n = static_cast<u8>(Rn);
1552 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1553 const u8 d = static_cast<u8>(Rd);
1554 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1555 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1556 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1557
1558 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1559 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
1560
1561 assert(!((d == 0xFU) && (S == 1U)));
1562 if (n == 0b1101U) {
1563 return SubSpMinusImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
1564 }
1565 if (d == 13U || (d == 15U && S == 0x0U) || n == 15U) {
1566 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1567 }
1568 flags |= static_cast<u8>(InstrFlags::k32Bit);
1569
1570 return Ok(Instr{InstrSubImmediate{iid, flags, n, d, imm32}});
1571}
1572
1573template <typename TCpuAccessor, typename TItOps>
1574static Result<Instr> SubImmediateT4Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1575 static_cast<void>(cpua); // prevents warning when cpua is not used
1576 const InstrId iid{InstrId::kSubImmediate};
1577 u8 flags = 0x0U;
1578
1579 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1580 assert((Bm16::ExtractBits1R<9U, 4U>(rinstr.low)) == 0b101010U);
1581 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1582
1583 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1584 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1585 const u8 n = static_cast<u8>(Rn);
1586 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1587 const u8 d = static_cast<u8>(Rd);
1588 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1589 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1590 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1591
1592 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1593 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
1594
1595 assert(Rn != 0b1111U);
1596 if (Rn == 0b1101U) {
1597 return SubSpMinusImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
1598 }
1599 if (d == 13U || d == 15U) {
1600 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1601 }
1602 flags |= static_cast<u8>(InstrFlags::k32Bit);
1603
1604 return Ok(Instr{InstrSubImmediate{iid, flags, n, d, imm32}});
1605}
1606
1607template <typename TCpuAccessor, typename TItOps>
1608static Result<Instr> SbcImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1609 static_cast<void>(cpua); // prevents warning when cpua is not used
1610 const InstrId iid{InstrId::kSbcImmediate};
1611 u8 flags = 0x0U;
1612
1613 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1614 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01011U);
1615 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1616
1617 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1618 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1619 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1620 const u8 n = static_cast<u8>(Rn);
1621 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1622 const u8 d = static_cast<u8>(Rd);
1623 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1624 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1625 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1626
1627 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1628 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
1629
1630 assert(!((d == 0xFU) && (S == 1U)));
1631 assert(n != 0xDU);
1632 if (d == 13U || (d == 15U && S == 0x0U) || n == 15U) {
1633 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1634 }
1635 flags |= static_cast<u8>(InstrFlags::k32Bit);
1636
1637 return Ok(Instr{InstrSbcImmediate{iid, flags, n, d, imm32}});
1638}
1639
1640template <typename TCpuAccessor, typename TItOps>
1641static Result<Instr> AddSpPlusImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1642 static_cast<void>(cpua); // prevents warning when cpua is not used
1643 const InstrId iid{InstrId::kAddSpPlusImmediate};
1644 u8 flags = 0x0U;
1645
1646 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b10101U);
1647
1648 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1649 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<10U, 8U>(rinstr.low));
1650 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
1651 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8 << 2U);
1652
1653 return Ok(Instr{InstrAddSpPlusImmediate{iid, flags, d, imm32}});
1654}
1655
1656template <typename TCpuAccessor, typename TItOps>
1657static Result<Instr> AddSpPlusImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1658 static_cast<void>(cpua); // prevents warning when cpua is not used
1659 const InstrId iid{InstrId::kAddSpPlusImmediate};
1660 u8 flags = 0x0U;
1661
1662 assert((Bm16::ExtractBits1R<15U, 7U>(rinstr.low)) == 0b101100000U);
1663
1664 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1665 const u8 d = 13U;
1666 const u32 imm7 = Bm16::ExtractBits1R<6U, 0U>(rinstr.low);
1667 const u32 imm32 = Bm32::ZeroExtend<u32>(imm7 << 2U);
1668
1669 return Ok(Instr{InstrAddSpPlusImmediate{iid, flags, d, imm32}});
1670}
1671
1672template <typename TCpuAccessor, typename TItOps>
1673static Result<Instr> AddSpPlusImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1674 static_cast<void>(cpua); // prevents warning when cpua is not used
1675 const InstrId iid{InstrId::kAddSpPlusImmediate};
1676 u8 flags = 0x0U;
1677
1678 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1679 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01000U);
1680 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1101U);
1681 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1682
1683 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1684 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1685 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1686 const u8 d = static_cast<u8>(Rd);
1687 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1688 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1689 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1690
1691 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1692 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
1693
1694 assert((Rd != 0b1111U) || (S != 1));
1695 if (d == 15U && S == 0x0U) {
1696 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1697 }
1698 flags |= static_cast<u8>(InstrFlags::k32Bit);
1699
1700 return Ok(Instr{InstrAddSpPlusImmediate{iid, flags, d, imm32}});
1701}
1702
1703template <typename TCpuAccessor, typename TItOps>
1704static Result<Instr> AddSpPlusImmediateT4Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1705 static_cast<void>(cpua); // prevents warning when cpua is not used
1706 const InstrId iid{InstrId::kAddSpPlusImmediate};
1707 u8 flags = 0x0U;
1708
1709 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1710 assert((Bm16::ExtractBits1R<9U, 0U>(rinstr.low)) == 0b1000001101U);
1711 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1712
1713 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1714 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1715 const u8 d = static_cast<u8>(Rd);
1716 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1717 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1718 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1719
1720 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1721 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
1722
1723 if (d == 15U) {
1724 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1725 }
1726 flags |= static_cast<u8>(InstrFlags::k32Bit);
1727
1728 return Ok(Instr{InstrAddSpPlusImmediate{iid, flags, d, imm32}});
1729}
1730
1731template <typename TCpuAccessor, typename TItOps>
1732static Result<Instr> AddImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1733 static_cast<void>(cpua); // prevents warning when cpua is not used
1734 const InstrId iid{InstrId::kAddImmediate};
1735 u8 flags = 0x0U;
1736
1737 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0001110U);
1738
1739 flags |=
1740 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
1741 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<5U, 3U>(rinstr.low));
1742 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<2U, 0U>(rinstr.low));
1743 const u32 imm3 = Bm16::ExtractBits1R<8U, 6U>(rinstr.low);
1744 const u32 imm32 = Bm32::ZeroExtend<u32>(imm3);
1745
1746 return Ok(Instr{InstrAddImmediate{iid, flags, n, d, imm32}});
1747}
1748
1749template <typename TCpuAccessor, typename TItOps>
1750static Result<Instr> AddImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1751 static_cast<void>(cpua); // prevents warning when cpua is not used
1752 const InstrId iid{InstrId::kAddImmediate};
1753 u8 flags = 0x0U;
1754
1755 flags |=
1756 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
1757 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<10U, 8U>(rinstr.low));
1758 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<10U, 8U>(rinstr.low));
1759 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
1760 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
1761
1762 return Ok(Instr{InstrAddImmediate{iid, flags, n, d, imm32}});
1763}
1764
1765template <typename TCpuAccessor, typename TItOps>
1766static Result<Instr> AddImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1767 static_cast<void>(cpua); // prevents warning when cpua is not used
1768 const InstrId iid{InstrId::kAddImmediate};
1769 u8 flags = 0x0U;
1770
1771 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1772 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01000U);
1773 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0x0U);
1774
1775 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1776 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1777 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1778 const u8 n = static_cast<u8>(Rn);
1779 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1780 const u8 d = static_cast<u8>(Rd);
1781 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1782 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1783 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1784
1785 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1786 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
1787
1788 assert(!((d == 0xFU) && (S == 1U)));
1789 if (Rn == 0b1101U) {
1790 return AddSpPlusImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
1791 }
1792 if (d == 13U || (d == 15U && S == 0x0U) || n == 15U) {
1793 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1794 }
1795 flags |= static_cast<u8>(InstrFlags::k32Bit);
1796
1797 return Ok(Instr{InstrAddImmediate{iid, flags, n, d, imm32}});
1798}
1799
1800template <typename TCpuAccessor, typename TItOps>
1801static Result<Instr> AddImmediateT4Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1802 static_cast<void>(cpua); // prevents warning when cpua is not used
1803 const InstrId iid{InstrId::kAddImmediate};
1804 u8 flags = 0x0U;
1805
1806 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0x0U);
1807 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b10000U);
1808 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1809
1810 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
1811 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1812 const u8 n = static_cast<u8>(Rn);
1813 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1814 const u8 d = static_cast<u8>(Rd);
1815 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1816 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1817 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1818
1819 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1820 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
1821
1822 assert(Rn != 0b1111U);
1823 if (Rn == 0b1101U) {
1824 return AddSpPlusImmediateT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
1825 }
1826 if (d == 13U || d == 15U) {
1827 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1828 }
1829 flags |= static_cast<u8>(InstrFlags::k32Bit);
1830
1831 return Ok(Instr{InstrAddImmediate{iid, flags, n, d, imm32}});
1832}
1833
1834template <typename TCpuAccessor, typename TItOps>
1835static Result<Instr> AdcImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1836 static_cast<void>(cpua); // prevents warning when cpua is not used
1837 const InstrId iid{InstrId::kAdcImmediate};
1838 u8 flags = 0x0U;
1839
1840 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1841 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b01010U);
1842 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0x0U);
1843
1844 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1845 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1846 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1847 const u8 n = static_cast<u8>(Rn);
1848 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1849 const u8 d = static_cast<u8>(Rd);
1850 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1851 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1852 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1853
1854 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1855 TRY_ASSIGN(imm32, Instr, Thumb::ThumbExpandImm(imm12));
1856
1857 if (d == 13U || d == 15U || n == 13U || n == 15U) {
1858 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1859 }
1860 flags |= static_cast<u8>(InstrFlags::k32Bit);
1861
1862 return Ok(Instr{InstrAdcImmediate{iid, flags, n, d, imm32}});
1863}
1864
1865template <typename TCpuAccessor, typename TItOps>
1866static Result<Instr> TstImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1867 static_cast<void>(cpua); // prevents warning when cpua is not used
1868 const InstrId iid{InstrId::kTstImmediate};
1869 u8 flags = 0x0U;
1870
1871 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1872 assert((Bm16::ExtractBits1R<9U, 4U>(rinstr.low)) == 0b000001U);
1873 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1874 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
1875
1876 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1877 const u8 n = static_cast<u8>(Rn);
1878 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1879 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1880 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1881 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1882 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
1883 TRY_ASSIGN(imm32_carry, Instr,
1884 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
1885
1886 if (n == 13U || n == 15U) {
1887 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1888 }
1889 flags |= static_cast<u8>(InstrFlags::k32Bit);
1890
1891 return Ok(Instr{InstrTstImmediate{iid, flags, n, imm32_carry}});
1892}
1893
1894template <typename TCpuAccessor, typename TItOps>
1895static Result<Instr> TeqImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1896 static_cast<void>(cpua); // prevents warning when cpua is not used
1897 const InstrId iid{InstrId::kTeqImmediate};
1898 u8 flags = 0x0U;
1899
1900 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
1901 assert((Bm16::ExtractBits1R<9U, 4U>(rinstr.low)) == 0b001001U);
1902 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1903 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
1904
1905 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1906 const u8 n = static_cast<u8>(Rn);
1907 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1908 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1909 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1910 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1911 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
1912 TRY_ASSIGN(imm32_carry, Instr,
1913 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
1914
1915 if (n == 13U || n == 15U) {
1916 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1917 }
1918 flags |= static_cast<u8>(InstrFlags::k32Bit);
1919
1920 return Ok(Instr{InstrTeqImmediate{iid, flags, n, imm32_carry}});
1921}
1922
1923template <typename TCpuAccessor, typename TItOps>
1924static Result<Instr> TstRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1925 static_cast<void>(cpua); // prevents warning when cpua is not used
1926 const InstrId iid{InstrId::kTstRegister};
1927 u8 flags = 0x0U;
1928
1929 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100001000U);
1930
1931 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
1932 const u8 n = static_cast<u8>(Rn);
1933 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
1934 const u8 m = static_cast<u8>(Rm);
1935 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
1936
1937 return Ok(Instr{InstrTstRegister{iid, flags, n, m, shift_res}});
1938}
1939
1940template <typename TCpuAccessor, typename TItOps>
1941static Result<Instr> TeqRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1942 static_cast<void>(cpua); // prevents warning when cpua is not used
1943 const InstrId iid{InstrId::kTeqRegister};
1944 u8 flags = 0x0U;
1945
1946 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111010101001U);
1947 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1948 assert((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) == 0b1111U);
1949
1950 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1951 const u8 n = static_cast<u8>(Rn);
1952 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
1953 const u8 m = static_cast<u8>(Rm);
1954 const u32 type = static_cast<u32>(Bm16::ExtractBits1R<5U, 4U>(rinstr.high));
1955 const u32 imm2 = static_cast<u32>(Bm16::ExtractBits1R<7U, 6U>(rinstr.high));
1956 const u32 imm3 = static_cast<u32>(Bm16::ExtractBits1R<14U, 12U>(rinstr.high));
1957 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2) | imm2);
1958
1959 if (n == 13U || n == 15U || m == 13U || m == 15U) {
1960 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1961 }
1962 flags |= static_cast<u8>(InstrFlags::k32Bit);
1963
1964 return Ok(Instr{InstrTeqRegister{iid, flags, n, m, shift_res}});
1965}
1966
1967template <typename TCpuAccessor, typename TItOps>
1968static Result<Instr> AndImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
1969 static_cast<void>(cpua); // prevents warning when cpua is not used
1970 const InstrId iid{InstrId::kAndImmediate};
1971 u8 flags = 0x0U;
1972
1973 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
1974 assert(((Bm16::ExtractBits1R<11U, 8U>(rinstr.high)) != 0b1111U) ||
1975 ((Bm16::IsolateBit<4U>(rinstr.low)) != 0b1U));
1976 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b00000U);
1977
1978 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
1979 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
1980 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
1981 const u8 n = static_cast<u8>(Rn);
1982 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
1983 const u8 d = static_cast<u8>(Rd);
1984 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
1985 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
1986 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
1987 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
1988 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
1989 TRY_ASSIGN(imm32_carry, Instr,
1990 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
1991
1992 if (d == 13U || (d == 15U && S == 0U) || n == 13U || n == 15U) {
1993 return Err<Instr>(StatusCode::kDecoderUnpredictable);
1994 }
1995 flags |= static_cast<u8>(InstrFlags::k32Bit);
1996
1997 return Ok(Instr{InstrAndImmediate{iid, flags, n, d, imm32_carry}});
1998}
1999
2000template <typename TCpuAccessor, typename TItOps>
2001static Result<Instr> OrrImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2002 static_cast<void>(cpua); // prevents warning when cpua is not used
2003 const InstrId iid{InstrId::kOrrImmediate};
2004 u8 flags = 0x0U;
2005
2006 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
2007 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b00010U);
2008 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2009
2010 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
2011 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2012 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2013 const u8 n = static_cast<u8>(Rn);
2014 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2015 const u8 d = static_cast<u8>(Rd);
2016 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
2017 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2018 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
2019 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
2020 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
2021 TRY_ASSIGN(imm32_carry, Instr,
2022 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
2023
2024 assert(Rn != 0b1111U);
2025 if (d == 13U || d == 15U || n == 13U) {
2026 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2027 }
2028 flags |= static_cast<u8>(InstrFlags::k32Bit);
2029
2030 return Ok(Instr{InstrOrrImmediate{iid, flags, n, d, imm32_carry}});
2031}
2032
2033template <typename TCpuAccessor, typename TItOps>
2034static Result<Instr> EorImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2035 static_cast<void>(cpua); // prevents warning when cpua is not used
2036 const InstrId iid{InstrId::kEorImmediate};
2037 u8 flags = 0x0U;
2038
2039 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11110U);
2040 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b00100U);
2041 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2042
2043 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
2044 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2045 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2046 const u8 n = static_cast<u8>(Rn);
2047 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2048 const u8 d = static_cast<u8>(Rd);
2049 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
2050 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2051 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
2052 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
2053 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
2054 TRY_ASSIGN(imm32_carry, Instr,
2055 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
2056
2057 if (d == 13U || (d == 15U && (S == 0U)) || n == 13U || n == 15U) {
2058 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2059 }
2060 flags |= static_cast<u8>(InstrFlags::k32Bit);
2061
2062 return Ok(Instr{InstrEorImmediate{iid, flags, n, d, imm32_carry}});
2063}
2064
2065template <typename TCpuAccessor, typename TItOps>
2066static Result<Instr> SubRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2067 static_cast<void>(cpua); // prevents warning when cpua is not used
2068 const InstrId iid{InstrId::kSubRegister};
2069 u8 flags = 0x0U;
2070
2071 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0001101U);
2072
2073 flags |=
2074 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
2075 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
2076 const u8 m = static_cast<u8>(Bm16::ExtractBits1R<8U, 6U>(rinstr.low));
2077 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<5U, 3U>(rinstr.low));
2078 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<2U, 0U>(rinstr.low));
2079
2080 return Ok(Instr{InstrSubRegister{iid, flags, shift_res, m, n, d}});
2081}
2082
2083template <typename TCpuAccessor, typename TItOps>
2084static Result<Instr> SubRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2085 static_cast<void>(cpua); // prevents warning when cpua is not used
2086 const InstrId iid{InstrId::kSubRegister};
2087 u8 flags = 0x0U;
2088
2089 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101011101U);
2090 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2091
2092 const u32 S = static_cast<u32>(Bm16::IsolateBit<4U>(rinstr.low));
2093 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2094 const u32 type = static_cast<u32>(Bm16::ExtractBits1R<5U, 4U>(rinstr.high));
2095 const u32 imm2 = static_cast<u32>(Bm16::ExtractBits1R<7U, 6U>(rinstr.high));
2096 const u32 imm3 = static_cast<u32>(Bm16::ExtractBits1R<14U, 12U>(rinstr.high));
2097 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2) | imm2);
2098 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2099 const u8 m = static_cast<u8>(Rm);
2100 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2101 const u8 n = static_cast<u8>(Rn);
2102 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2103 const u8 d = static_cast<u8>(Rd);
2104
2105 assert((Rd != 0b1111U) || (S != 1U));
2106 assert(Rn != 0b1101U);
2107 if (d == 13U || (d == 15U && S == 0U) || n == 15U || m == 13U || m == 15U) {
2108 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2109 }
2110 flags |= static_cast<u8>(InstrFlags::k32Bit);
2111
2112 return Ok(Instr{InstrSubRegister{iid, flags, shift_res, m, n, d}});
2113}
2114
2115template <typename TCpuAccessor, typename TItOps>
2116static Result<Instr> RsbRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2117 static_cast<void>(cpua); // prevents warning when cpua is not used
2118 const InstrId iid{InstrId::kRsbRegister};
2119 u8 flags = 0x0U;
2120
2121 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101011110U);
2122 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2123
2124 const u32 S = static_cast<u32>(Bm16::IsolateBit<4U>(rinstr.low));
2125 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2126 const u32 type = static_cast<u32>(Bm16::ExtractBits1R<5U, 4U>(rinstr.high));
2127 const u32 imm2 = static_cast<u32>(Bm16::ExtractBits1R<7U, 6U>(rinstr.high));
2128 const u32 imm3 = static_cast<u32>(Bm16::ExtractBits1R<14U, 12U>(rinstr.high));
2129 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2) | imm2);
2130 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2131 const u8 m = static_cast<u8>(Rm);
2132 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2133 const u8 n = static_cast<u8>(Rn);
2134 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2135 const u8 d = static_cast<u8>(Rd);
2136
2137 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
2138 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2139 }
2140 flags |= static_cast<u8>(InstrFlags::k32Bit);
2141
2142 return Ok(Instr{InstrRsbRegister{iid, flags, shift_res, m, n, d}});
2143}
2144
2145template <typename TCpuAccessor, typename TItOps>
2146static Result<Instr> UmlalT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2147 static_cast<void>(cpua); // prevents warning when cpua is not used
2148 const InstrId iid{InstrId::kUmlal};
2149 u8 flags = 0x0U;
2150
2151 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110111110U);
2152 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
2153
2154 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
2155 const u16 RdHi = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2156 const u8 dHi = static_cast<u8>(RdHi);
2157 const u16 RdLo = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
2158 const u8 dLo = static_cast<u8>(RdLo);
2159 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2160 const u8 m = static_cast<u8>(Rm);
2161 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2162 const u8 n = static_cast<u8>(Rn);
2163
2164 if (dLo == 13U || dLo == 15U || dHi == 13U || dHi == 15U || n == 13U || n == 15U || m == 13U ||
2165 m == 15U) {
2166 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2167 }
2168 if (dHi == dLo) {
2169 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2170 }
2171 flags |= static_cast<u8>(InstrFlags::k32Bit);
2172
2173 return Ok(Instr{InstrUmlal{iid, flags, dHi, dLo, m, n}});
2174}
2175
2176template <typename TCpuAccessor, typename TItOps>
2177static Result<Instr> UmullT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2178 static_cast<void>(cpua); // prevents warning when cpua is not used
2179 const InstrId iid{InstrId::kUmull};
2180 u8 flags = 0x0U;
2181
2182 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110111010U);
2183 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
2184
2185 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
2186 const u16 RdHi = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2187 const u8 dHi = static_cast<u8>(RdHi);
2188 const u16 RdLo = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
2189 const u8 dLo = static_cast<u8>(RdLo);
2190 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2191 const u8 m = static_cast<u8>(Rm);
2192 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2193 const u8 n = static_cast<u8>(Rn);
2194
2195 if (dLo == 13U || dLo == 15U || dHi == 13U || dHi == 15U || n == 13U || n == 15U || m == 13U ||
2196 m == 15U) {
2197 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2198 }
2199 if (dHi == dLo) {
2200 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2201 }
2202 flags |= static_cast<u8>(InstrFlags::k32Bit);
2203
2204 return Ok(Instr{InstrUmull{iid, flags, dHi, dLo, m, n}});
2205}
2206
2207template <typename TCpuAccessor, typename TItOps>
2208static Result<Instr> SmullT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2209 static_cast<void>(cpua); // prevents warning when cpua is not used
2210 const InstrId iid{InstrId::kSmull};
2211 u8 flags = 0x0U;
2212
2213 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110111000U);
2214 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
2215
2216 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
2217 const u16 RdHi = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2218 const u8 dHi = static_cast<u8>(RdHi);
2219 const u16 RdLo = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
2220 const u8 dLo = static_cast<u8>(RdLo);
2221 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2222 const u8 m = static_cast<u8>(Rm);
2223 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2224 const u8 n = static_cast<u8>(Rn);
2225
2226 if (dHi == dLo) {
2227 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2228 }
2229 flags |= static_cast<u8>(InstrFlags::k32Bit);
2230
2231 return Ok(Instr{InstrSmull{iid, flags, dHi, dLo, m, n}});
2232}
2233
2234template <typename TCpuAccessor, typename TItOps>
2235static Result<Instr> MulT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2236 static_cast<void>(cpua); // prevents warning when cpua is not used
2237 const InstrId iid{InstrId::kMul};
2238 u8 flags = 0x0U;
2239
2240 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110110000U);
2241 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2242 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
2243
2244 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
2245 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2246 const u8 d = static_cast<u8>(Rd);
2247 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2248 const u8 m = static_cast<u8>(Rm);
2249 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2250 const u8 n = static_cast<u8>(Rn);
2251
2252 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
2253 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2254 }
2255 flags |= static_cast<u8>(InstrFlags::k32Bit);
2256
2257 return Ok(Instr{InstrMul{iid, flags, d, m, n}});
2258}
2259
2260template <typename TCpuAccessor, typename TItOps>
2261static Result<Instr> UdivT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2262 static_cast<void>(cpua); // prevents warning when cpua is not used
2263 const InstrId iid{InstrId::kUdiv};
2264 u8 flags = 0x0U;
2265
2266 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110111011U);
2267 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2268 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b1111U);
2269
2270 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2271 const u8 d = static_cast<u8>(Rd);
2272 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2273 const u8 m = static_cast<u8>(Rm);
2274 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2275 const u8 n = static_cast<u8>(Rn);
2276
2277 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
2278 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2279 }
2280 flags |= static_cast<u8>(InstrFlags::k32Bit);
2281
2282 return Ok(Instr{InstrUdiv{iid, flags, d, m, n}});
2283}
2284
2285template <typename TCpuAccessor, typename TItOps>
2286static Result<Instr> SdivT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2287 static_cast<void>(cpua); // prevents warning when cpua is not used
2288 const InstrId iid{InstrId::kSdiv};
2289 u8 flags = 0x0U;
2290
2291 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110111001U);
2292 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2293 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b1111U);
2294
2295 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2296 const u8 d = static_cast<u8>(Rd);
2297 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2298 const u8 m = static_cast<u8>(Rm);
2299 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2300 const u8 n = static_cast<u8>(Rn);
2301
2302 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
2303 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2304 }
2305 flags |= static_cast<u8>(InstrFlags::k32Bit);
2306
2307 return Ok(Instr{InstrSdiv{iid, flags, d, m, n}});
2308}
2309
2310template <typename TCpuAccessor, typename TItOps>
2311static Result<Instr> MlsT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2312 static_cast<void>(cpua); // prevents warning when cpua is not used
2313 const InstrId iid{InstrId::kMls};
2314 u8 flags = 0x0U;
2315
2316 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110110000U);
2317 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0001U);
2318
2319 const u16 Ra = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
2320 const u8 a = static_cast<u8>(Ra);
2321 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2322 const u8 d = static_cast<u8>(Rd);
2323 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2324 const u8 m = static_cast<u8>(Rm);
2325 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2326 const u8 n = static_cast<u8>(Rn);
2327
2328 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U || (a == 13U) ||
2329 (a == 15U)) {
2330 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2331 }
2332 flags |= static_cast<u8>(InstrFlags::k32Bit);
2333
2334 return Ok(Instr{InstrMls{iid, flags, a, d, m, n}});
2335}
2336
2337template <typename TCpuAccessor, typename TItOps>
2338static Result<Instr> MlaT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2339 static_cast<void>(cpua); // prevents warning when cpua is not used
2340 const InstrId iid{InstrId::kMla};
2341 u8 flags = 0x0U;
2342
2343 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110110000U);
2344 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
2345
2346 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
2347 const u16 Ra = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
2348 const u8 a = static_cast<u8>(Ra);
2349 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2350 const u8 d = static_cast<u8>(Rd);
2351 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2352 const u8 m = static_cast<u8>(Rm);
2353 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2354 const u8 n = static_cast<u8>(Rn);
2355
2356 assert(Ra != 0b1111U);
2357 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U || (a == 13U) ||
2358 (a == 15U)) {
2359 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2360 }
2361 flags |= static_cast<u8>(InstrFlags::k32Bit);
2362
2363 return Ok(Instr{InstrMla{iid, flags, a, d, m, n}});
2364}
2365
2366template <typename TCpuAccessor, typename TItOps>
2367static Result<Instr> AddRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2368 static_cast<void>(cpua); // prevents warning when cpua is not used
2369 const InstrId iid{InstrId::kAddRegister};
2370 u8 flags = 0x0U;
2371
2372 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0001100U);
2373
2374 flags |=
2375 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
2376 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
2377 const u8 m = static_cast<u8>(Bm16::ExtractBits1R<8U, 6U>(rinstr.low));
2378 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<5U, 3U>(rinstr.low));
2379 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<2U, 0U>(rinstr.low));
2380
2381 return Ok(Instr{InstrAddRegister{iid, flags, shift_res, m, n, d}});
2382}
2383
2384template <typename TCpuAccessor, typename TItOps>
2385static Result<Instr> AddRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2386 static_cast<void>(cpua); // prevents warning when cpua is not used
2387 const InstrId iid{InstrId::kAddRegister};
2388 u8 flags = 0x0U;
2389
2390 assert((Bm16::ExtractBits1R<10U, 8U>(rinstr.low)) == 0b100U);
2391
2392 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kSetFlags);
2393 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
2394 const u8 m = static_cast<u8>(Bm16::ExtractBits1R<6U, 3U>(rinstr.low));
2395 const u32 dn_1 = Bm16::IsolateBit<7U>(rinstr.low);
2396 const u8 n = static_cast<u8>(dn_1 << 3U | Bm16::ExtractBits1R<2U, 0U>(rinstr.low));
2397 const u32 dn_2 = Bm16::IsolateBit<7U>(rinstr.low);
2398 const u8 d = static_cast<u8>(dn_2 << 3U | Bm16::ExtractBits1R<2U, 0U>(rinstr.low));
2399
2400 assert(d != 0b1101U);
2401 assert(n != 0b1101U);
2402 if (d == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
2403 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2404 }
2405 if (d == 15U && m == 15U) {
2406 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2407 }
2408
2409 return Ok(Instr{InstrAddRegister{iid, flags, shift_res, m, n, d}});
2410}
2411
2412template <typename TCpuAccessor, typename TItOps>
2413static Result<Instr> AddRegisterT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2414 static_cast<void>(cpua); // prevents warning when cpua is not used
2415 const InstrId iid{InstrId::kAddRegister};
2416 u8 flags = 0x0U;
2417
2418 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101011000U);
2419 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2420
2421 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
2422 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2423 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2424 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
2425 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2426 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2) | imm2);
2427 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2428 const u8 m = static_cast<u8>(Rm);
2429 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2430 const u8 n = static_cast<u8>(Rn);
2431 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2432 const u8 d = static_cast<u8>(Rd);
2433
2434 assert((d != 0b1111U) || (S != 1U));
2435 assert(m != 0b1101U);
2436 if (d == 13U || (d == 15U && S == 0U) || n == 15U || m == 13U || m == 15U) {
2437 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2438 }
2439 flags |= static_cast<u8>(InstrFlags::k32Bit);
2440
2441 return Ok(Instr{InstrAddRegister{iid, flags, shift_res, m, n, d}});
2442}
2443
2444template <typename TCpuAccessor, typename TItOps>
2445static Result<Instr> AdcRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2446 static_cast<void>(cpua); // prevents warning when cpua is not used
2447 const InstrId iid{InstrId::kAdcRegister};
2448 u8 flags = 0x0U;
2449
2450 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100000101U);
2451
2452 flags |=
2453 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
2454 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, static_cast<u8>(0U)};
2455 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
2456 const u8 m = static_cast<u8>(Rm);
2457 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2458 const u8 n = static_cast<u8>(Rn);
2459 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2460 const u8 d = static_cast<u8>(Rd);
2461
2462 return Ok(Instr{InstrAdcRegister{iid, flags, shift_res, m, n, d}});
2463}
2464
2465template <typename TCpuAccessor, typename TItOps>
2466static Result<Instr> AdcRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2467 static_cast<void>(cpua); // prevents warning when cpua is not used
2468 const InstrId iid{InstrId::kAdcRegister};
2469 u8 flags = 0x0U;
2470
2471 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101011010U);
2472 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2473
2474 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
2475 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2476 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2477 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
2478 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2479 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2) | imm2);
2480 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2481 const u8 m = static_cast<u8>(Rm);
2482 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2483 const u8 n = static_cast<u8>(Rn);
2484 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2485 const u8 d = static_cast<u8>(Rd);
2486
2487 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
2488 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2489 }
2490 flags |= static_cast<u8>(InstrFlags::k32Bit);
2491
2492 return Ok(Instr{InstrAdcRegister{iid, flags, shift_res, m, n, d}});
2493}
2494
2495template <typename TCpuAccessor, typename TItOps>
2496static Result<Instr> StmdbT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2497 static_cast<void>(cpua); // prevents warning when cpua is not used
2498 const InstrId iid{InstrId::kStmdb};
2499 u8 flags = 0x0U;
2500
2501 assert(false); // not implemented
2502 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b1110100100U);
2503 assert((Bm16::IsolateBit<4U>(rinstr.low)) == 0b0U);
2504 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2505 assert((Bm16::IsolateBit<13U>(rinstr.high)) == 0b0U);
2506
2507 const u32 W = Bm16::IsolateBit<5U>(rinstr.low);
2508 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
2509 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2510 const u8 n = static_cast<u8>(Rn);
2511 const u32 M = Bm16::IsolateBit<14U>(rinstr.high);
2512 const u32 register_list = Bm16::ExtractBits1R<12U, 0U>(rinstr.high);
2513 const u32 registers = (M << 14U) | register_list;
2514
2515 assert((W != 0x1U) || (Rn != 0b1101U));
2516 if (n == 15 || (Bm32::BitCount(registers) < 2U)) {
2517 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2518 }
2519 // if wback && registers<n> == '1' then UNPREDICTABLE;
2520 flags |= static_cast<u8>(InstrFlags::k32Bit);
2521
2522 return Ok(Instr{InstrStmdb{iid, flags, n, registers}});
2523}
2524
2525template <typename TCpuAccessor, typename TItOps>
2526static Result<Instr> PushT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2527 static_cast<void>(cpua); // prevents warning when cpua is not used
2528 const InstrId iid{InstrId::kPush};
2529 u8 flags = 0x0U;
2530
2531 assert((Bm16::ExtractBits1R<10U, 9U>(rinstr.low)) == 0b10U);
2532
2533 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
2534 const u32 M = Bm16::IsolateBit<8U>(rinstr.low);
2535 const u32 register_list = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
2536 const u32 registers = (M << 14U) | register_list;
2537
2538 if (Bm32::BitCount(registers) < 1U) {
2539 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2540 }
2541
2542 return Ok(Instr{InstrPush{iid, flags, registers}});
2543}
2544
2545template <typename TCpuAccessor, typename TItOps>
2546static Result<Instr> PushT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2547 static_cast<void>(cpua); // prevents warning when cpua is not used
2548 const InstrId iid{InstrId::kPush};
2549 u8 flags = 0x0U;
2550
2551 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1110100100101101U);
2552 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2553 assert((Bm16::IsolateBit<13U>(rinstr.high)) == 0b0U);
2554
2555 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
2556 const u32 M = Bm16::IsolateBit<14U>(rinstr.high);
2557 const u32 register_list = Bm16::ExtractBits1R<12U, 0U>(rinstr.high);
2558 const u32 registers = (M << 14U) | register_list;
2559
2560 if (Bm32::BitCount(registers) < 2U) {
2561 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2562 }
2563 flags |= static_cast<u8>(InstrFlags::k32Bit);
2564
2565 return Ok(Instr{InstrPush{iid, flags, registers}});
2566}
2567
2568template <typename TCpuAccessor, typename TItOps>
2569static Result<Instr> PushT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2570 static_cast<void>(cpua); // prevents warning when cpua is not used
2571 const InstrId iid{InstrId::kPush};
2572 u8 flags = 0x0U;
2573
2574 assert(rinstr.low == 0b1111100001001101U);
2575 assert((Bm16::ExtractBits1R<11U, 0U>(rinstr.high)) == 0b110100000100U);
2576
2577 flags |= static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
2578 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
2579 const u8 t = static_cast<u8>(Rt);
2580 const u32 registers = 1U << Rt;
2581
2582 if (t == 13U || t == 15U) {
2583 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2584 }
2585 flags |= static_cast<u8>(InstrFlags::k32Bit);
2586
2587 return Ok(Instr{InstrPush{iid, flags, registers}});
2588}
2589
2590template <typename TCpuAccessor, typename TItOps>
2591static Result<Instr> LdmT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2592 static_cast<void>(cpua); // prevents warning when cpua is not used
2593 const InstrId iid{InstrId::kLdm};
2594 u8 flags = 0x0U;
2595
2596 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11001U);
2597
2598 const u8 Rn_flag = static_cast<u8>(Bm16::ExtractBits1R<10U, 8U>(rinstr.low));
2599 const u16 register_list_flag = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
2600 const u16 n_mask = 1U << Rn_flag;
2601 flags |= (register_list_flag & n_mask) == 0 ? static_cast<InstrFlagsSet>(InstrFlags::kWBack) : 0U;
2602 const u16 register_list = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
2603 const u32 registers = static_cast<u32>(register_list);
2604 const u16 Rn = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
2605 const u8 n = static_cast<u8>(Rn);
2606
2607 if (Bm32::BitCount(registers) < 1U) {
2608 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2609 }
2610
2611 return Ok(Instr{InstrLdm{iid, flags, registers, n}});
2612}
2613
2614template <typename TCpuAccessor, typename TItOps>
2615static Result<Instr> LdmT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2616 static_cast<void>(cpua); // prevents warning when cpua is not used
2617 const InstrId iid{InstrId::kLdm};
2618 u8 flags = 0x0U;
2619
2620 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b1110100010U);
2621 assert((Bm16::IsolateBit<4U>(rinstr.low)) == 0b1U);
2622 assert((Bm16::IsolateBit<13U>(rinstr.high)) == 0b0U);
2623
2624 const u32 W = Bm16::IsolateBit<5U>(rinstr.low);
2625 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
2626 const u32 P = Bm16::IsolateBit<15U>(rinstr.high);
2627 const u32 M = Bm16::IsolateBit<14U>(rinstr.high);
2628 const u32 register_list = Bm16::ExtractBits1R<12U, 0U>(rinstr.high);
2629 const u32 registers = (P << 15U) | (M << 14U) | register_list;
2630 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2631 const u8 n = static_cast<u8>(Rn);
2632
2633 assert((W != 1) || (Rn != 0b1101U));
2634 if (n == 15 || (Bm32::BitCount(registers) < 2U) || ((P == 1U) && M == 1U)) {
2635 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2636 }
2637 if ((Bm32::ExtractBits1R<15U, 15U>(registers) == 0x1U) && (TItOps::InITBlock(cpua)) &&
2638 (!TItOps::LastInITBlock(cpua))) {
2639 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2640 }
2641 if (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && ((registers & (1 << n)) != 0U)) {
2642 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2643 }
2644 flags |= static_cast<u8>(InstrFlags::k32Bit);
2645
2646 return Ok(Instr{InstrLdm{iid, flags, registers, n}});
2647}
2648
2649template <typename TCpuAccessor, typename TItOps>
2650static Result<Instr> StmT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2651 static_cast<void>(cpua); // prevents warning when cpua is not used
2652 const InstrId iid{InstrId::kStm};
2653 u8 flags = 0x0U;
2654
2655 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b11000U);
2656
2657 flags |= static_cast<InstrFlagsSet>(InstrFlags::kWBack);
2658 const u16 register_list = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
2659 const u32 registers = static_cast<u32>(register_list);
2660 const u16 Rn = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
2661 const u8 n = static_cast<u8>(Rn);
2662
2663 return Ok(Instr{InstrStm{iid, flags, registers, n}});
2664}
2665
2666template <typename TCpuAccessor, typename TItOps>
2667static Result<Instr> StmT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2668 static_cast<void>(cpua); // prevents warning when cpua is not used
2669 const InstrId iid{InstrId::kStm};
2670 u8 flags = 0x0U;
2671
2672 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b1110100010U);
2673 assert((Bm16::IsolateBit<4U>(rinstr.low)) == 0b0U);
2674 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2675 assert((Bm16::IsolateBit<13U>(rinstr.high)) == 0b0U);
2676
2677 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kUnalignedAllow);
2678 const u32 W = Bm16::IsolateBit<5U>(rinstr.low);
2679 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
2680 const u32 M = Bm16::IsolateBit<14U>(rinstr.high);
2681 const u32 register_list = Bm16::ExtractBits1R<12U, 0U>(rinstr.high);
2682 const u32 registers = (M << 14U) | register_list;
2683 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2684 const u8 n = static_cast<u8>(Rn);
2685
2686 if (n == 15 || (Bm32::BitCount(registers) < 2U)) {
2687 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2688 }
2689 if (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && ((registers & (1 << n)) != 0U)) {
2690 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2691 }
2692 flags |= static_cast<u8>(InstrFlags::k32Bit);
2693
2694 return Ok(Instr{InstrStm{iid, flags, registers, n}});
2695}
2696
2697template <typename TCpuAccessor, typename TItOps>
2698static Result<Instr> SxthT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2699 static_cast<void>(cpua); // prevents warning when cpua is not used
2700 const InstrId iid{InstrId::kSxth};
2701 u8 flags = 0x0U;
2702
2703 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b1011001000U);
2704
2705 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
2706 const u8 m = static_cast<u8>(Rm);
2707 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2708 const u8 d = static_cast<u8>(Rd);
2709 const u8 rotation = 0U;
2710
2711 return Ok(Instr{InstrSxth{iid, flags, m, d, rotation}});
2712}
2713
2714template <typename TCpuAccessor, typename TItOps>
2715static Result<Instr> SxthT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2716 static_cast<void>(cpua); // prevents warning when cpua is not used
2717 const InstrId iid{InstrId::kSxth};
2718 u8 flags = 0x0U;
2719
2720 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1111101000001111U);
2721 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2722 assert((Bm16::ExtractBits1R<7U, 6U>(rinstr.high)) == 0b10U);
2723
2724 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2725 const u8 m = static_cast<u8>(Rm);
2726 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2727 const u8 d = static_cast<u8>(Rd);
2728 const u16 rotate = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2729 const u8 rotation = static_cast<u8>(rotate << 3U);
2730
2731 if (d == 13U || d == 15U || m == 13U || m == 15U) {
2732 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2733 }
2734 flags |= static_cast<u8>(InstrFlags::k32Bit);
2735
2736 return Ok(Instr{InstrSxth{iid, flags, m, d, rotation}});
2737}
2738
2739template <typename TCpuAccessor, typename TItOps>
2740static Result<Instr> UxtbT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2741 static_cast<void>(cpua); // prevents warning when cpua is not used
2742 const InstrId iid{InstrId::kUxtb};
2743 u8 flags = 0x0U;
2744
2745 assert((Bm16::ExtractBits1R<11U, 6U>(rinstr.low)) == 0b001011U);
2746
2747 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
2748 const u8 m = static_cast<u8>(Rm);
2749 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2750 const u8 d = static_cast<u8>(Rd);
2751 const u8 rotation = 0U;
2752
2753 return Ok(Instr{InstrUxtb{iid, flags, m, d, rotation}});
2754}
2755
2756template <typename TCpuAccessor, typename TItOps>
2757static Result<Instr> UxtbT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2758 static_cast<void>(cpua); // prevents warning when cpua is not used
2759 const InstrId iid{InstrId::kUxtb};
2760 u8 flags = 0x0U;
2761
2762 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1111101001011111U);
2763 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2764 assert((Bm16::ExtractBits1R<7U, 6U>(rinstr.high)) == 0b10U);
2765
2766 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2767 const u8 m = static_cast<u8>(Rm);
2768 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2769 const u8 d = static_cast<u8>(Rd);
2770 const u32 rotate = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2771 const u8 rotation = static_cast<u8>(rotate << 3U);
2772
2773 if (d == 13U || d == 15U || m == 13U || m == 15U) {
2774 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2775 }
2776 flags |= static_cast<u8>(InstrFlags::k32Bit);
2777
2778 return Ok(Instr{InstrUxtb{iid, flags, m, d, rotation}});
2779}
2780
2781template <typename TCpuAccessor, typename TItOps>
2782static Result<Instr> SxtbT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2783 static_cast<void>(cpua); // prevents warning when cpua is not used
2784 const InstrId iid{InstrId::kSxtb};
2785 u8 flags = 0x0U;
2786
2787 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b1011001001U);
2788
2789 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
2790 const u8 m = static_cast<u8>(Rm);
2791 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2792 const u8 d = static_cast<u8>(Rd);
2793 const u8 rotation = 0U;
2794
2795 return Ok(Instr{InstrSxtb{iid, flags, m, d, rotation}});
2796}
2797
2798template <typename TCpuAccessor, typename TItOps>
2799static Result<Instr> SxtbT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2800 static_cast<void>(cpua); // prevents warning when cpua is not used
2801 const InstrId iid{InstrId::kSxtb};
2802 u8 flags = 0x0U;
2803
2804 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1111101001001111U);
2805 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2806 assert((Bm16::ExtractBits1R<7U, 6U>(rinstr.high)) == 0b10U);
2807
2808 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2809 const u8 m = static_cast<u8>(Rm);
2810 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2811 const u8 d = static_cast<u8>(Rd);
2812 const u16 rotate = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2813 const u8 rotation = static_cast<u8>(rotate << 3U);
2814
2815 if (d == 13U || d == 15U || m == 13U || m == 15U) {
2816 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2817 }
2818 flags |= static_cast<u8>(InstrFlags::k32Bit);
2819
2820 return Ok(Instr{InstrSxtb{iid, flags, m, d, rotation}});
2821}
2822
2823template <typename TCpuAccessor, typename TItOps>
2824static Result<Instr> UxthT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2825 static_cast<void>(cpua); // prevents warning when cpua is not used
2826 const InstrId iid{InstrId::kUxth};
2827 u8 flags = 0x0U;
2828
2829 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b1011001010U);
2830
2831 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
2832 const u8 m = static_cast<u8>(Rm);
2833 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2834 const u8 d = static_cast<u8>(Rd);
2835 const u8 rotation = 0U;
2836
2837 return Ok(Instr{InstrUxth{iid, flags, m, d, rotation}});
2838}
2839
2840template <typename TCpuAccessor, typename TItOps>
2841static Result<Instr> UxthT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2842 static_cast<void>(cpua); // prevents warning when cpua is not used
2843 const InstrId iid{InstrId::kUxth};
2844 u8 flags = 0x0U;
2845
2846 assert((Bm16::ExtractBits1R<15U, 0U>(rinstr.low)) == 0b1111101000011111U);
2847 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
2848 assert((Bm16::ExtractBits1R<7U, 6U>(rinstr.high)) == 0b10U);
2849
2850 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2851 const u8 m = static_cast<u8>(Rm);
2852 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2853 const u8 d = static_cast<u8>(Rd);
2854 const u32 rotate = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2855 const u8 rotation = rotate << 3U;
2856
2857 if (d == 13U || d == 15U || m == 13U || m == 15U) {
2858 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2859 }
2860 flags |= static_cast<u8>(InstrFlags::k32Bit);
2861
2862 return Ok(Instr{InstrUxth{iid, flags, m, d, rotation}});
2863}
2864
2865template <typename TCpuAccessor, typename TItOps>
2866static Result<Instr> BfiT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2867 static_cast<void>(cpua); // prevents warning when cpua is not used
2868 const InstrId iid{InstrId::kBfi};
2869 u8 flags = 0x0U;
2870
2871 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111100110110U);
2872 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2873 assert((Bm16::IsolateBit<5U>(rinstr.high)) == 0b0U);
2874
2875 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2876 const u8 d = static_cast<u8>(Rd);
2877 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2878 const u8 n = static_cast<u8>(Rn);
2879 const u32 imm2 = static_cast<u32>(Bm16::ExtractBits1R<7U, 6U>(rinstr.high));
2880 const u32 imm3 = static_cast<u32>(Bm16::ExtractBits1R<14U, 12U>(rinstr.high));
2881 const u8 lsbit = static_cast<u8>((imm3 << 2U) | imm2);
2882 const u16 msb = Bm16::ExtractBits1R<4U, 0U>(rinstr.high);
2883 const u8 msbit = static_cast<u8>(msb);
2884
2885 if (d == 13U || d == 15U || n == 13U) {
2886 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2887 }
2888 flags |= static_cast<u8>(InstrFlags::k32Bit);
2889
2890 return Ok(Instr{InstrBfi{iid, flags, d, n, lsbit, msbit}});
2891}
2892
2893template <typename TCpuAccessor, typename TItOps>
2894static Result<Instr> UbfxT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2895 static_cast<void>(cpua); // prevents warning when cpua is not used
2896 const InstrId iid{InstrId::kUbfx};
2897 u8 flags = 0x0U;
2898
2899 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111100111100U);
2900 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2901 assert((Bm16::IsolateBit<5U>(rinstr.high)) == 0b0U);
2902
2903 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2904 const u8 d = static_cast<u8>(Rd);
2905 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2906 const u8 n = static_cast<u8>(Rn);
2907 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
2908 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2909 const u8 lsbit = static_cast<u8>((imm3 << 2U) | imm2);
2910 const u32 widthm1 = Bm16::ExtractBits1R<4U, 0U>(rinstr.high);
2911 const u8 widthminus1 = static_cast<u8>(widthm1);
2912
2913 if (d == 13U || d == 15U || n == 13U || n == 15U) {
2914 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2915 }
2916 flags |= static_cast<u8>(InstrFlags::k32Bit);
2917
2918 return Ok(Instr{InstrUbfx{iid, flags, d, n, lsbit, widthminus1}});
2919}
2920
2921template <typename TCpuAccessor, typename TItOps>
2922static Result<Instr> EorRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2923 static_cast<void>(cpua); // prevents warning when cpua is not used
2924 const InstrId iid{InstrId::kEorRegister};
2925 u8 flags = 0x0U;
2926
2927 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100000001U);
2928
2929 flags |=
2930 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
2931 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2932 const u8 n = static_cast<u8>(Rn);
2933 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
2934 const u8 d = static_cast<u8>(Rd);
2935 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
2936 const u8 m = static_cast<u8>(Rm);
2937 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
2938
2939 return Ok(Instr{InstrEorRegister{iid, flags, n, d, m, shift_res}});
2940}
2941
2942template <typename TCpuAccessor, typename TItOps>
2943static Result<Instr> EorRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2944 static_cast<void>(cpua); // prevents warning when cpua is not used
2945 const InstrId iid{InstrId::kEorRegister};
2946 u8 flags = 0x0U;
2947
2948 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010100U);
2949 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2950
2951 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
2952 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2953 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2954 const u8 n = static_cast<u8>(Rn);
2955 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2956 const u8 d = static_cast<u8>(Rd);
2957 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2958 const u8 m = static_cast<u8>(Rm);
2959 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2960 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
2961 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2962 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2U) | imm2);
2963
2964 assert((Rd != 0b1111U) || (S != 1));
2965 if (d == 13U || (d == 15U && (S == 0)) || n == 15U || m == 13U || m == 15U) {
2966 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2967 }
2968 flags |= static_cast<u8>(InstrFlags::k32Bit);
2969
2970 return Ok(Instr{InstrEorRegister{iid, flags, n, d, m, shift_res}});
2971}
2972
2973template <typename TCpuAccessor, typename TItOps>
2974static Result<Instr> SbcRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
2975 static_cast<void>(cpua); // prevents warning when cpua is not used
2976 const InstrId iid{InstrId::kSbcRegister};
2977 u8 flags = 0x0U;
2978
2979 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101011011U);
2980 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
2981
2982 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
2983 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
2984 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
2985 const u8 n = static_cast<u8>(Rn);
2986 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
2987 const u8 d = static_cast<u8>(Rd);
2988 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
2989 const u8 m = static_cast<u8>(Rm);
2990 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
2991 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
2992 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
2993 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2U) | imm2);
2994
2995 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
2996 return Err<Instr>(StatusCode::kDecoderUnpredictable);
2997 }
2998 flags |= static_cast<u8>(InstrFlags::k32Bit);
2999
3000 return Ok(Instr{InstrSbcRegister{iid, flags, n, d, m, shift_res}});
3001}
3002
3003template <typename TCpuAccessor, typename TItOps>
3004static Result<Instr> OrrRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3005 static_cast<void>(cpua); // prevents warning when cpua is not used
3006 const InstrId iid{InstrId::kOrrRegister};
3007 u8 flags = 0x0U;
3008
3009 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100001100U);
3010
3011 flags |=
3012 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
3013 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3014 const u8 n = static_cast<u8>(Rn);
3015 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3016 const u8 d = static_cast<u8>(Rd);
3017 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3018 const u8 m = static_cast<u8>(Rm);
3019 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
3020
3021 return Ok(Instr{InstrOrrRegister{iid, flags, n, d, m, shift_res}});
3022}
3023
3024template <typename TCpuAccessor, typename TItOps>
3025static Result<Instr> OrrRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3026 static_cast<void>(cpua); // prevents warning when cpua is not used
3027 const InstrId iid{InstrId::kOrrRegister};
3028 u8 flags = 0x0U;
3029
3030 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010010U);
3031 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3032
3033 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3034 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3035 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3036 const u8 n = static_cast<u8>(Rn);
3037 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3038 const u8 d = static_cast<u8>(Rd);
3039 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3040 const u8 m = static_cast<u8>(Rm);
3041 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3042 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
3043 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
3044 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2U) | imm2);
3045
3046 assert(Rn != 0b1111U);
3047 if (d == 13U || d == 15U || n == 15U || m == 13U || m == 15U) {
3048 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3049 }
3050 flags |= static_cast<u8>(InstrFlags::k32Bit);
3051
3052 return Ok(Instr{InstrOrrRegister{iid, flags, n, d, m, shift_res}});
3053}
3054
3055template <typename TCpuAccessor, typename TItOps>
3056static Result<Instr> AndRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3057 static_cast<void>(cpua); // prevents warning when cpua is not used
3058 const InstrId iid{InstrId::kAndRegister};
3059 u8 flags = 0x0U;
3060
3061 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100000000U);
3062
3063 flags |=
3064 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
3065 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3066 const u8 n = static_cast<u8>(Rn);
3067 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3068 const u8 d = static_cast<u8>(Rd);
3069 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3070 const u8 m = static_cast<u8>(Rm);
3071 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
3072
3073 return Ok(Instr{InstrAndRegister{iid, flags, n, d, m, shift_res}});
3074}
3075
3076template <typename TCpuAccessor, typename TItOps>
3077static Result<Instr> AndRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3078 static_cast<void>(cpua); // prevents warning when cpua is not used
3079 const InstrId iid{InstrId::kAndRegister};
3080 u8 flags = 0x0U;
3081
3082 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010000U);
3083 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3084
3085 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3086 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3087 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3088 const u8 n = static_cast<u8>(Rn);
3089 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3090 const u8 d = static_cast<u8>(Rd);
3091 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3092 const u8 m = static_cast<u8>(Rm);
3093 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3094 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
3095 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
3096 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2U) | imm2);
3097
3098 assert((Rd != 0b1111U) || (S != 0b1U));
3099 if (d == 13U || (d == 15U && (S == 0U)) || n == 13U || n == 15U || m == 13U || m == 15U) {
3100 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3101 }
3102 flags |= static_cast<u8>(InstrFlags::k32Bit);
3103
3104 return Ok(Instr{InstrAndRegister{iid, flags, n, d, m, shift_res}});
3105}
3106
3107template <typename TCpuAccessor, typename TItOps>
3108static Result<Instr> BicImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3109 static_cast<void>(cpua); // prevents warning when cpua is not used
3110 const InstrId iid{InstrId::kBicImmediate};
3111 u8 flags = 0x0U;
3112
3113 assert((Bm16::ExtractBits1R<9U, 5U>(rinstr.low)) == 0b00001U);
3114 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3115
3116 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3117 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3118 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3119 const u8 n = static_cast<u8>(Rn);
3120 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3121 const u8 d = static_cast<u8>(Rd);
3122 const u32 i = Bm16::IsolateBit<10U>(rinstr.low);
3123 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
3124 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
3125 const u32 imm12 = (i << 11U) | (imm3 << 8U) | imm8;
3126 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
3127 TRY_ASSIGN(imm32_carry, Instr,
3128 Thumb::ThumbExpandImm_C(imm12, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk));
3129
3130 if (d == 13U || d == 15U || n == 13U || n == 15U) {
3131 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3132 }
3133 flags |= static_cast<u8>(InstrFlags::k32Bit);
3134
3135 return Ok(Instr{InstrBicImmediate{iid, flags, n, d, imm32_carry}});
3136}
3137
3138template <typename TCpuAccessor, typename TItOps>
3139static Result<Instr> BicRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3140 static_cast<void>(cpua); // prevents warning when cpua is not used
3141 const InstrId iid{InstrId::kBicRegister};
3142 u8 flags = 0x0U;
3143
3144 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100001110U);
3145
3146 flags |=
3147 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
3148 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3149 const u8 n = static_cast<u8>(Rn);
3150 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3151 const u8 d = static_cast<u8>(Rd);
3152 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3153 const u8 m = static_cast<u8>(Rm);
3154 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
3155
3156 return Ok(Instr{InstrBicRegister{iid, flags, n, d, m, shift_res}});
3157}
3158
3159template <typename TCpuAccessor, typename TItOps>
3160static Result<Instr> BicRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3161 static_cast<void>(cpua); // prevents warning when cpua is not used
3162 const InstrId iid{InstrId::kBicRegister};
3163 u8 flags = 0x0U;
3164
3165 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010001U);
3166 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3167
3168 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3169 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3170 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3171 const u8 n = static_cast<u8>(Rn);
3172 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3173 const u8 d = static_cast<u8>(Rd);
3174 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3175 const u8 m = static_cast<u8>(Rm);
3176 const u32 type = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3177 const u32 imm2 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
3178 const u32 imm3 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
3179 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2U) | imm2);
3180
3181 if (d == 13U || d == 15U || n == 13U || n == 15U || m == 13U || m == 15U) {
3182 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3183 }
3184 flags |= static_cast<u8>(InstrFlags::k32Bit);
3185
3186 return Ok(Instr{InstrBicRegister{iid, flags, n, d, m, shift_res}});
3187}
3188
3189template <typename TCpuAccessor, typename TItOps>
3190static Result<Instr> LsrRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3191 static_cast<void>(cpua); // prevents warning when cpua is not used
3192 const InstrId iid{InstrId::kLsrRegister};
3193 u8 flags = 0x0U;
3194
3195 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100000011U);
3196
3197 flags |=
3198 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
3199 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3200 const u8 n = static_cast<u8>(Rn);
3201 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3202 const u8 d = static_cast<u8>(Rd);
3203 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3204 const u8 m = static_cast<u8>(Rm);
3205
3206 return Ok(Instr{InstrLsrRegister{iid, flags, n, d, m}});
3207}
3208
3209template <typename TCpuAccessor, typename TItOps>
3210static Result<Instr> LsrRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3211 static_cast<void>(cpua); // prevents warning when cpua is not used
3212 const InstrId iid{InstrId::kLsrRegister};
3213 u8 flags = 0x0U;
3214
3215 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11111010001U);
3216 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
3217 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
3218
3219 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3220 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3221 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3222 const u8 n = static_cast<u8>(Rn);
3223 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3224 const u8 d = static_cast<u8>(Rd);
3225 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3226 const u8 m = static_cast<u8>(Rm);
3227
3228 if (d == 13U || d == 15 || n == 13U || n == 15 || m == 13U || m == 15) {
3229 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3230 }
3231 flags |= static_cast<u8>(InstrFlags::k32Bit);
3232
3233 return Ok(Instr{InstrLsrRegister{iid, flags, n, d, m}});
3234}
3235
3236template <typename TCpuAccessor, typename TItOps>
3237static Result<Instr> AsrRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3238 static_cast<void>(cpua); // prevents warning when cpua is not used
3239 const InstrId iid{InstrId::kAsrRegister};
3240 u8 flags = 0x0U;
3241
3242 assert((Bm16::ExtractBits1R<15U, 6U>(rinstr.low)) == 0b0100000100U);
3243
3244 flags |=
3245 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
3246 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3247 const u8 n = static_cast<u8>(Rn);
3248 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3249 const u8 d = static_cast<u8>(Rd);
3250 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3251 const u8 m = static_cast<u8>(Rm);
3252
3253 return Ok(Instr{InstrAsrRegister{iid, flags, n, d, m}});
3254}
3255
3256template <typename TCpuAccessor, typename TItOps>
3257static Result<Instr> AsrRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3258 static_cast<void>(cpua); // prevents warning when cpua is not used
3259 const InstrId iid{InstrId::kAsrRegister};
3260 u8 flags = 0x0U;
3261
3262 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11111010010U);
3263 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1111U);
3264 assert((Bm16::ExtractBits1R<7U, 4U>(rinstr.high)) == 0b0000U);
3265
3266 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3267 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3268 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3269 const u8 n = static_cast<u8>(Rn);
3270 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3271 const u8 d = static_cast<u8>(Rd);
3272 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3273 const u8 m = static_cast<u8>(Rm);
3274
3275 if (d == 13U || d == 15 || n == 13U || n == 15 || m == 13U || m == 15) {
3276 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3277 }
3278 flags |= static_cast<u8>(InstrFlags::k32Bit);
3279
3280 return Ok(Instr{InstrAsrRegister{iid, flags, n, d, m}});
3281}
3282
3283template <typename TCpuAccessor, typename TItOps>
3284static Result<Instr> LsrImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3285 static_cast<void>(cpua); // prevents warning when cpua is not used
3286 const InstrId iid{InstrId::kLsrImmediate};
3287 u8 flags = 0x0U;
3288
3289 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b00001U);
3290
3291 flags |=
3292 TItOps::InITBlock(cpua) == false ? static_cast<InstrFlagsSet>(InstrFlags::kSetFlags) : 0U;
3293 const u16 Rm = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3294 const u8 m = static_cast<u8>(Rm);
3295 const u16 Rd = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3296 const u8 d = static_cast<u8>(Rd);
3297 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
3298 const auto shift_res = Alu32::DecodeImmShift(0b01U, imm5);
3299
3300 return Ok(Instr{InstrLsrImmediate{iid, flags, m, d, shift_res}});
3301}
3302
3303template <typename TCpuAccessor, typename TItOps>
3304static Result<Instr> LsrImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3305 static_cast<void>(cpua); // prevents warning when cpua is not used
3306 const InstrId iid{InstrId::kLsrImmediate};
3307 u8 flags = 0x0U;
3308
3309 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010010U);
3310 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
3311 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3312 assert((Bm16::ExtractBits1R<5U, 4U>(rinstr.high)) == 0b01U);
3313
3314 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3315 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3316 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3317 const u8 m = static_cast<u8>(Rm);
3318 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3319 const u8 d = static_cast<u8>(Rd);
3320 const u32 imm3_32 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
3321 const u32 imm2_32 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
3322 const auto shift_res = Alu32::DecodeImmShift(0b01U, (imm3_32 << 2U) | imm2_32);
3323
3324 assert(shift_res.type == SRType::SRType_LSR);
3325 if (d == 13U || d == 15U || m == 13U || m == 15U) {
3326 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3327 }
3328 flags |= static_cast<u8>(InstrFlags::k32Bit);
3329
3330 return Ok(Instr{InstrLsrImmediate{iid, flags, m, d, shift_res}});
3331}
3332
3333template <typename TCpuAccessor, typename TItOps>
3334static Result<Instr> MvnRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3335 static_cast<void>(cpua); // prevents warning when cpua is not used
3336 const InstrId iid{InstrId::kMvnRegister};
3337 u8 flags = 0x0U;
3338
3339 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010011U);
3340 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
3341 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3342
3343 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3344 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3345 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3346 const u8 m = static_cast<u8>(Rm);
3347 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3348 const u8 d = static_cast<u8>(Rd);
3349 const u32 imm3 = static_cast<u32>(Bm16::ExtractBits1R<14U, 12U>(rinstr.high));
3350 const u32 imm2 = static_cast<u32>(Bm16::ExtractBits1R<7U, 6U>(rinstr.high));
3351 const u32 type = static_cast<u32>(Bm16::ExtractBits1R<5U, 4U>(rinstr.high));
3352 const auto shift_res = Alu32::DecodeImmShift(type, (imm3 << 2U) | imm2);
3353
3354 if (d == 13U || d == 15U || m == 13U || m == 15U) {
3355 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3356 }
3357 flags |= static_cast<u8>(InstrFlags::k32Bit);
3358
3359 return Ok(Instr{InstrMvnRegister{iid, flags, m, d, shift_res}});
3360}
3361
3362template <typename TCpuAccessor, typename TItOps>
3363static Result<Instr> AsrImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3364 static_cast<void>(cpua); // prevents warning when cpua is not used
3365 const InstrId iid{InstrId::kAsrImmediate};
3366 u8 flags = 0x0U;
3367
3368 assert((Bm16::ExtractBits1R<15U, 5U>(rinstr.low)) == 0b11101010010U);
3369 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) == 0b1111U);
3370 assert((Bm16::IsolateBit<15U>(rinstr.high)) == 0b0U);
3371 assert((Bm16::ExtractBits1R<5U, 4U>(rinstr.high)) == 0b10U);
3372
3373 const u32 S = Bm16::IsolateBit<4U>(rinstr.low);
3374 flags |= S << static_cast<InstrFlagsSet>(InstrFlagsShift::kSetFlagsShift);
3375 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3376 const u8 m = static_cast<u8>(Rm);
3377 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3378 const u8 d = static_cast<u8>(Rd);
3379 const u32 imm3_32 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
3380 const u32 imm2_32 = Bm16::ExtractBits1R<7U, 6U>(rinstr.high);
3381 const auto shift_res = Alu32::DecodeImmShift(0b10U, (imm3_32 << 2U) | imm2_32);
3382
3383 assert(shift_res.type == SRType::SRType_ASR);
3384 if (d == 13U || d == 15U || m == 13U || m == 15U) {
3385 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3386 }
3387 flags |= static_cast<u8>(InstrFlags::k32Bit);
3388
3389 return Ok(Instr{InstrAsrImmediate{iid, flags, m, d, shift_res}});
3390}
3391
3392template <typename TCpuAccessor, typename TItOps>
3393static Result<Instr> StrRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3394 static_cast<void>(cpua); // prevents warning when cpua is not used
3395 const InstrId iid{InstrId::kStrRegister};
3396 u8 flags = 0x0U;
3397
3398 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0101000U);
3399
3400 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3401 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3402 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3403 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3404 const u8 n = static_cast<u8>(Rn);
3405 const u16 Rm = Bm16::ExtractBits1R<8U, 6U>(rinstr.low);
3406 const u8 m = static_cast<u8>(Rm);
3407 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3408 const u8 t = static_cast<u8>(Rt);
3409 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
3410
3411 return Ok(Instr{InstrStrRegister{iid, flags, n, m, t, shift_res}});
3412}
3413
3414template <typename TCpuAccessor, typename TItOps>
3415static Result<Instr> StrRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3416 static_cast<void>(cpua); // prevents warning when cpua is not used
3417 const InstrId iid{InstrId::kStrRegister};
3418 u8 flags = 0x0U;
3419
3420 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000100U);
3421 assert((Bm16::ExtractBits1R<11U, 6U>(rinstr.high)) == 0b000000U);
3422
3423 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3424 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3425 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3426 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3427 const u8 n = static_cast<u8>(Rn);
3428 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3429 const u8 m = static_cast<u8>(Rm);
3430 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3431 const u8 t = static_cast<u8>(Rt);
3432 const u32 imm2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3433 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, static_cast<u8>(imm2)};
3434
3435 if (t == 15U || m == 13U || m == 15) {
3436 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3437 }
3438 flags |= static_cast<u8>(InstrFlags::k32Bit);
3439
3440 return Ok(Instr{InstrStrRegister{iid, flags, n, m, t, shift_res}});
3441}
3442
3443template <typename TCpuAccessor, typename TItOps>
3444static Result<Instr> StrbRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3445 static_cast<void>(cpua); // prevents warning when cpua is not used
3446 const InstrId iid{InstrId::kStrbRegister};
3447 u8 flags = 0x0U;
3448
3449 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0101010U);
3450
3451 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3452 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3453 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3454 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3455 const u8 n = static_cast<u8>(Rn);
3456 const u16 Rm = Bm16::ExtractBits1R<8U, 6U>(rinstr.low);
3457 const u8 m = static_cast<u8>(Rm);
3458 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3459 const u8 t = static_cast<u8>(Rt);
3460 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0U};
3461
3462 return Ok(Instr{InstrStrbRegister{iid, flags, n, m, t, shift_res}});
3463}
3464
3465template <typename TCpuAccessor, typename TItOps>
3466static Result<Instr> StrbRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3467 static_cast<void>(cpua); // prevents warning when cpua is not used
3468 const InstrId iid{InstrId::kStrbRegister};
3469 u8 flags = 0x0U;
3470
3471 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000000U);
3472 assert((Bm16::ExtractBits1R<11U, 6U>(rinstr.high)) == 0b000000U);
3473
3474 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3475 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3476 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3477 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3478 const u8 n = static_cast<u8>(Rn);
3479 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3480 const u8 m = static_cast<u8>(Rm);
3481 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3482 const u8 t = static_cast<u8>(Rt);
3483 const u32 imm2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3484 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, static_cast<u8>(imm2)};
3485
3486 if (Rn == 0b1111U) {
3487 return Err<Instr>(StatusCode::kDecoderUndefined);
3488 }
3489 if (t == 13U || t == 15U || m == 13U || m == 15) {
3490 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3491 }
3492 flags |= static_cast<u8>(InstrFlags::k32Bit);
3493
3494 return Ok(Instr{InstrStrbRegister{iid, flags, n, m, t, shift_res}});
3495}
3496
3497template <typename TCpuAccessor, typename TItOps>
3498static Result<Instr> StrhRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3499 static_cast<void>(cpua); // prevents warning when cpua is not used
3500 const InstrId iid{InstrId::kStrhRegister};
3501 u8 flags = 0x0U;
3502
3503 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000010U);
3504 assert((Bm16::ExtractBits1R<11U, 6U>(rinstr.high)) == 0b000000U);
3505
3506 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3507 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3508 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3509 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3510 const u8 n = static_cast<u8>(Rn);
3511 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3512 const u8 m = static_cast<u8>(Rm);
3513 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3514 const u8 t = static_cast<u8>(Rt);
3515 const u32 imm2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3516 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, static_cast<u8>(imm2)};
3517
3518 if (Rn == 0b1111U) {
3519 return Err<Instr>(StatusCode::kDecoderUndefined);
3520 }
3521 if (t == 13U || t == 15U || m == 13U || m == 15) {
3522 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3523 }
3524 flags |= static_cast<u8>(InstrFlags::k32Bit);
3525
3526 return Ok(Instr{InstrStrhRegister{iid, flags, n, m, t, shift_res}});
3527}
3528
3529template <typename TCpuAccessor, typename TItOps>
3530static Result<Instr> LdrbRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3531 static_cast<void>(cpua); // prevents warning when cpua is not used
3532 const InstrId iid{InstrId::kLdrbRegister};
3533 u8 flags = 0x0U;
3534
3535 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0101110U);
3536
3537 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3538 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3539 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3540 const u16 Rm = Bm16::ExtractBits1R<8U, 6U>(rinstr.low);
3541 const u8 m = static_cast<u8>(Rm);
3542 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3543 const u8 n = static_cast<u8>(Rn);
3544 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3545 const u8 t = static_cast<u8>(Rt);
3546 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0x0U};
3547
3548 return Ok(Instr{InstrLdrbRegister{iid, flags, m, n, t, shift_res}});
3549}
3550
3551template <typename TCpuAccessor, typename TItOps>
3552static Result<Instr> LdrRegisterT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3553 static_cast<void>(cpua); // prevents warning when cpua is not used
3554 const InstrId iid{InstrId::kLdrRegister};
3555 u8 flags = 0x0U;
3556
3557 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b0101100U);
3558
3559 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3560 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3561 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3562 const u16 Rm = Bm16::ExtractBits1R<8U, 6U>(rinstr.low);
3563 const u8 m = static_cast<u8>(Rm);
3564 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3565 const u8 n = static_cast<u8>(Rn);
3566 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3567 const u8 t = static_cast<u8>(Rt);
3568 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, 0x0U};
3569
3570 return Ok(Instr{InstrLdrRegister{iid, flags, m, n, t, shift_res}});
3571}
3572
3573template <typename TCpuAccessor, typename TItOps>
3574static Result<Instr> LdrRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3575 static_cast<void>(cpua); // prevents warning when cpua is not used
3576 const InstrId iid{InstrId::kLdrRegister};
3577 u8 flags = 0x0U;
3578
3579 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000101U);
3580 assert((Bm16::ExtractBits1R<11U, 6U>(rinstr.high)) == 0b000000U);
3581 assert((Bm16::ExtractBits1R<3U, 0U>(rinstr.low)) != 0b1111U);
3582
3583 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3584 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3585 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3586 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3587 const u8 m = static_cast<u8>(Rm);
3588 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3589 const u8 n = static_cast<u8>(Rn);
3590 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3591 const u8 t = static_cast<u8>(Rt);
3592 const u32 imm2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3593 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, static_cast<u8>(imm2)};
3594
3595 if (m == 13U || m == 15) {
3596 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3597 }
3598 if (t == 15U && TItOps::InITBlock(cpua) && !TItOps::LastInITBlock(cpua)) {
3599 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3600 }
3601 flags |= static_cast<u8>(InstrFlags::k32Bit);
3602
3603 return Ok(Instr{InstrLdrRegister{iid, flags, m, n, t, shift_res}});
3604}
3605
3606template <typename TCpuAccessor, typename TItOps>
3607static Result<Instr> LdrhRegisterT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3608 static_cast<void>(cpua); // prevents warning when cpua is not used
3609 const InstrId iid{InstrId::kLdrhRegister};
3610 u8 flags = 0x0U;
3611
3612 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000011U);
3613 assert((Bm16::ExtractBits1R<11U, 6U>(rinstr.high)) == 0b000000U);
3614
3615 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3616 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3617 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3618 const u16 Rm = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
3619 const u8 m = static_cast<u8>(Rm);
3620 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3621 const u8 n = static_cast<u8>(Rn);
3622 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3623 const u8 t = static_cast<u8>(Rt);
3624 const u32 imm2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
3625 const auto shift_res = ImmShiftResults{SRType::SRType_LSL, static_cast<u8>(imm2)};
3626
3627 assert(Rn != 0b1111U);
3628 assert(Rt != 0b1111U);
3629 if (t == 13U || m == 13U || m == 15) {
3630 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3631 }
3632 flags |= static_cast<u8>(InstrFlags::k32Bit);
3633
3634 return Ok(Instr{InstrLdrhRegister{iid, flags, m, n, t, shift_res}});
3635}
3636
3637template <typename TCpuAccessor, typename TItOps>
3638static Result<Instr> StrdImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3639 static_cast<void>(cpua); // prevents warning when cpua is not used
3640 const InstrId iid{InstrId::kStrdImmediate};
3641 u8 flags = 0x0U;
3642
3643 assert((Bm16::ExtractBits1R<15U, 9U>(rinstr.low)) == 0b1110100U);
3644 assert((Bm16::IsolateBit<6U>(rinstr.low)) == 0b1U);
3645 assert((Bm16::IsolateBit<4U>(rinstr.low)) == 0b0U);
3646
3647 const u32 U = Bm16::IsolateBit<7U>(rinstr.low);
3648 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
3649 const u32 P = Bm16::IsolateBit<8U>(rinstr.low);
3650 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
3651 const u32 W = Bm16::IsolateBit<5U>(rinstr.low);
3652 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
3653 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3654 const u8 n = static_cast<u8>(Rn);
3655 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3656 const u8 t = static_cast<u8>(Rt);
3657 const u16 Rt2 = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3658 const u8 t2 = static_cast<u8>(Rt2);
3659 const u32 imm8_32 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
3660 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8_32 << 2U);
3661
3662 assert((P != 0U) || (W != 0U));
3663 if (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && (n == t || n == t2)) {
3664 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3665 }
3666 if (n == 15U || t == 13U || t == 15U || t2 == 13U || t2 == 15U) {
3667 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3668 }
3669 flags |= static_cast<u8>(InstrFlags::k32Bit);
3670
3671 return Ok(Instr{InstrStrdImmediate{iid, flags, n, t, t2, imm32}});
3672}
3673
3674template <typename TCpuAccessor, typename TItOps>
3675static Result<Instr> StrhImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3676 static_cast<void>(cpua); // prevents warning when cpua is not used
3677 const InstrId iid{InstrId::kStrhImmediate};
3678 u8 flags = 0x0U;
3679
3680 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b10000U);
3681
3682 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3683 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3684 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3685 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3686 const u8 n = static_cast<u8>(Rn);
3687 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3688 const u8 t = static_cast<u8>(Rt);
3689 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
3690 const u32 imm32 = Bm32::ZeroExtend<u32>(imm5 << 1U);
3691
3692 return Ok(Instr{InstrStrhImmediate{iid, flags, n, t, imm32}});
3693}
3694
3695template <typename TCpuAccessor, typename TItOps>
3696static Result<Instr> StrhImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3697 static_cast<void>(cpua); // prevents warning when cpua is not used
3698 const InstrId iid{InstrId::kStrhImmediate};
3699 u8 flags = 0x0U;
3700
3701 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110001010U);
3702
3703 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3704 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3705 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3706 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3707 const u8 n = static_cast<u8>(Rn);
3708 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3709 const u8 t = static_cast<u8>(Rt);
3710 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
3711 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
3712
3713 if (t == 13U || t == 15U) {
3714 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3715 }
3716 flags |= static_cast<u8>(InstrFlags::k32Bit);
3717
3718 return Ok(Instr{InstrStrhImmediate{iid, flags, n, t, imm32}});
3719}
3720
3721template <typename TCpuAccessor, typename TItOps>
3722static Result<Instr> StrhImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3723 static_cast<void>(cpua); // prevents warning when cpua is not used
3724 const InstrId iid{InstrId::kStrhImmediate};
3725 u8 flags = 0x0U;
3726
3727 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000010U);
3728 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
3729
3730 const u32 U = Bm16::IsolateBit<9U>(rinstr.high);
3731 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
3732 const u32 P = Bm16::IsolateBit<10U>(rinstr.high);
3733 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
3734 const u32 W = Bm16::IsolateBit<8U>(rinstr.high);
3735 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
3736 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3737 const u8 n = static_cast<u8>(Rn);
3738 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3739 const u8 t = static_cast<u8>(Rt);
3740 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
3741 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
3742
3743 assert(P != 0b1U || U != 0b1U || W != 0b0U);
3744 if ((Rn == 0b1111U) || (P == 0b0 && W == 0b0U)) {
3745 return Err<Instr>(StatusCode::kDecoderUndefined);
3746 }
3747 if ((t == 13U || t == 15U) &&
3748 (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
3749 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3750 }
3751 flags |= static_cast<u8>(InstrFlags::k32Bit);
3752
3753 return Ok(Instr{InstrStrhImmediate{iid, flags, n, t, imm32}});
3754}
3755
3756template <typename TCpuAccessor, typename TItOps>
3757static Result<Instr> StrbImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3758 static_cast<void>(cpua); // prevents warning when cpua is not used
3759 const InstrId iid{InstrId::kStrbImmediate};
3760 u8 flags = 0x0U;
3761
3762 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b01110U);
3763
3764 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3765 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3766 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3767 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3768 const u8 n = static_cast<u8>(Rn);
3769 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3770 const u8 t = static_cast<u8>(Rt);
3771 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
3772 const u32 imm32 = Bm32::ZeroExtend<u32>(imm5);
3773
3774 return Ok(Instr{InstrStrbImmediate{iid, flags, n, t, imm32}});
3775}
3776
3777template <typename TCpuAccessor, typename TItOps>
3778static Result<Instr> StrbImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3779 static_cast<void>(cpua); // prevents warning when cpua is not used
3780 const InstrId iid{InstrId::kStrbImmediate};
3781 u8 flags = 0x0U;
3782
3783 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110001000U);
3784
3785 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3786 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3787 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3788 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3789 const u8 n = static_cast<u8>(Rn);
3790 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3791 const u8 t = static_cast<u8>(Rt);
3792 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
3793 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
3794
3795 if (Rn == 0b1111U) {
3796 return Err<Instr>(StatusCode::kDecoderUndefined);
3797 }
3798 if (t == 13U || t == 15U) {
3799 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3800 }
3801 flags |= static_cast<u8>(InstrFlags::k32Bit);
3802
3803 return Ok(Instr{InstrStrbImmediate{iid, flags, n, t, imm32}});
3804}
3805
3806template <typename TCpuAccessor, typename TItOps>
3807static Result<Instr> StrbImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3808 static_cast<void>(cpua); // prevents warning when cpua is not used
3809 const InstrId iid{InstrId::kStrbImmediate};
3810 u8 flags = 0x0U;
3811
3812 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000000U);
3813 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
3814
3815 const u32 U = Bm16::IsolateBit<9U>(rinstr.high);
3816 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
3817 const u32 P = Bm16::IsolateBit<10U>(rinstr.high);
3818 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
3819 const u32 W = Bm16::IsolateBit<8U>(rinstr.high);
3820 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
3821 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3822 const u8 n = static_cast<u8>(Rn);
3823 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3824 const u8 t = static_cast<u8>(Rt);
3825 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
3826 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
3827
3828 assert((P != 1U) || (U != 1) || (W != 0U));
3829 if (n == 15U || ((P == 0U) && (W == 0U))) {
3830 return Err<Instr>(StatusCode::kDecoderUndefined);
3831 }
3832 if (t == 13U || t == 15U || (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
3833 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3834 }
3835 flags |= static_cast<u8>(InstrFlags::k32Bit);
3836
3837 return Ok(Instr{InstrStrbImmediate{iid, flags, n, t, imm32}});
3838}
3839
3840template <typename TCpuAccessor, typename TItOps>
3841static Result<Instr> StrImmediateT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3842 static_cast<void>(cpua); // prevents warning when cpua is not used
3843 const InstrId iid{InstrId::kStrImmediate};
3844 u8 flags = 0x0U;
3845
3846 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b01100U);
3847
3848 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3849 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3850 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3851 const u16 Rn = Bm16::ExtractBits1R<5U, 3U>(rinstr.low);
3852 const u8 n = static_cast<u8>(Rn);
3853 const u16 Rt = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3854 const u8 t = static_cast<u8>(Rt);
3855 const u32 imm5 = Bm16::ExtractBits1R<10U, 6U>(rinstr.low);
3856 const u32 imm32 = Bm32::ZeroExtend<u32>(imm5 << 2);
3857
3858 return Ok(Instr{InstrStrImmediate{iid, flags, n, t, imm32}});
3859}
3860
3861template <typename TCpuAccessor, typename TItOps>
3862static Result<Instr> StrImmediateT2Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3863 static_cast<void>(cpua); // prevents warning when cpua is not used
3864 const InstrId iid{InstrId::kStrImmediate};
3865 u8 flags = 0x0U;
3866
3867 assert((Bm16::ExtractBits1R<15U, 11U>(rinstr.low)) == 0b10010U);
3868
3869 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3870 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3871 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3872 const u8 n = 13U;
3873 const u16 Rt = Bm16::ExtractBits1R<10U, 8U>(rinstr.low);
3874 const u8 t = static_cast<u8>(Rt);
3875 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
3876 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8 << 2U);
3877
3878 return Ok(Instr{InstrStrImmediate{iid, flags, n, t, imm32}});
3879}
3880
3881template <typename TCpuAccessor, typename TItOps>
3882static Result<Instr> StrImmediateT3Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3883 static_cast<void>(cpua); // prevents warning when cpua is not used
3884 const InstrId iid{InstrId::kStrImmediate};
3885 u8 flags = 0x0U;
3886
3887 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110001100U);
3888
3889 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3890 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3891 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3892 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3893 const u8 n = static_cast<u8>(Rn);
3894 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3895 const u8 t = static_cast<u8>(Rt);
3896 const u32 imm12 = Bm16::ExtractBits1R<11U, 0U>(rinstr.high);
3897 const u32 imm32 = Bm32::ZeroExtend<u32>(imm12);
3898
3899 if (n == 0b1111U) {
3900 return Err<Instr>(StatusCode::kDecoderUndefined);
3901 }
3902 if (t == 15U) {
3903 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3904 }
3905 flags |= static_cast<u8>(InstrFlags::k32Bit);
3906
3907 return Ok(Instr{InstrStrImmediate{iid, flags, n, t, imm32}});
3908}
3909
3910template <typename TCpuAccessor, typename TItOps>
3911static Result<Instr> StrImmediateT4Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3912 static_cast<void>(cpua); // prevents warning when cpua is not used
3913 const InstrId iid{InstrId::kStrImmediate};
3914 u8 flags = 0x0U;
3915
3916 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111110000100U);
3917 assert((Bm16::IsolateBit<11U>(rinstr.high)) == 0b1U);
3918
3919 const u32 U = Bm16::IsolateBit<9U>(rinstr.high);
3920 flags |= U << static_cast<InstrFlagsSet>(InstrFlagsShift::kAddShift);
3921 const u32 P = Bm16::IsolateBit<10U>(rinstr.high);
3922 flags |= P << static_cast<InstrFlagsSet>(InstrFlagsShift::kIndexShift);
3923 const u32 W = Bm16::IsolateBit<8U>(rinstr.high);
3924 flags |= W << static_cast<InstrFlagsSet>(InstrFlagsShift::kWBackShift);
3925 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3926 const u8 n = static_cast<u8>(Rn);
3927 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3928 const u8 t = static_cast<u8>(Rt);
3929 const u32 imm8_32 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
3930 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8_32);
3931
3932 assert((P != 1U) || (U != 1) || (W != 0U));
3933 if ((n == 13U) && (P == 1) && (U == 0U) && (W == 1U) && (imm8_32 == 0b00000100U)) {
3934 return PushT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
3935 }
3936 if (n == 15U || ((P == 0U) && (W == 0U))) {
3937 return Err<Instr>(StatusCode::kDecoderUndefined);
3938 }
3939 if (t == 15U || (flags & static_cast<InstrFlagsSet>(InstrFlags::kWBack) && n == t)) {
3940 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3941 }
3942 flags |= static_cast<u8>(InstrFlags::k32Bit);
3943
3944 return Ok(Instr{InstrStrImmediate{iid, flags, n, t, imm32}});
3945}
3946
3947template <typename TCpuAccessor, typename TItOps>
3948static Result<Instr> StrexT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3949 static_cast<void>(cpua); // prevents warning when cpua is not used
3950 const InstrId iid{InstrId::kStrex};
3951 u8 flags = 0x0U;
3952
3953 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111010000100U);
3954
3955 flags |= static_cast<InstrFlagsSet>(InstrFlags::kAdd);
3956 flags |= static_cast<InstrFlagsSet>(InstrFlags::kIndex);
3957 flags &= ~static_cast<InstrFlagsSet>(InstrFlags::kWBack);
3958 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
3959 const u8 n = static_cast<u8>(Rn);
3960 const u16 Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
3961 const u8 t = static_cast<u8>(Rt);
3962 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
3963 const u8 d = static_cast<u8>(Rd);
3964 const u32 imm8_32 = Bm16::ExtractBits1R<7U, 0U>(rinstr.high);
3965 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8_32);
3966
3967 if (d == n || d == t) {
3968 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3969 }
3970 flags |= static_cast<u8>(InstrFlags::k32Bit);
3971
3972 return Ok(Instr{InstrStrex{iid, flags, n, t, d, imm32}});
3973}
3974
3975template <typename TCpuAccessor, typename TItOps>
3976static Result<Instr> CbNZT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
3977 static_cast<void>(cpua); // prevents warning when cpua is not used
3978 const InstrId iid{InstrId::kCbNZ};
3979 u8 flags = 0x0U;
3980
3981 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.low)) == 0b1011U);
3982 assert((Bm16::IsolateBit<10U>(rinstr.low)) == 0b0U);
3983 assert((Bm16::IsolateBit<8U>(rinstr.low)) == 0b1U);
3984
3985 const u32 op = Bm16::IsolateBit<11U>(rinstr.low);
3986 flags |= op << static_cast<InstrFlagsSet>(InstrFlagsShift::kNonZeroShift);
3987 const u16 Rn = Bm16::ExtractBits1R<2U, 0U>(rinstr.low);
3988 const u8 n = static_cast<u8>(Rn);
3989 const u32 imm5 = Bm16::ExtractBits1R<7U, 3U>(rinstr.low);
3990 const u32 i = Bm16::IsolateBit<9U>(rinstr.low);
3991 const i32 imm32 = Bm32::ZeroExtend<u32>((i << 6U) | (imm5 << 1U));
3992
3993 if (TItOps::InITBlock(cpua)) {
3994 return Err<Instr>(StatusCode::kDecoderUnpredictable);
3995 }
3996
3997 return Ok(Instr{InstrCbNZ{iid, flags, n, imm32}});
3998}
3999
4000template <typename TCpuAccessor, typename TItOps>
4001static Result<Instr> SvcT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
4002 static_cast<void>(cpua); // prevents warning when cpua is not used
4003 const InstrId iid{InstrId::kSvc};
4004 u8 flags = 0x0U;
4005
4006 assert((Bm16::ExtractBits1R<15U, 8U>(rinstr.low)) == 0b11011111U);
4007
4008 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
4009 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
4010
4011 return Ok(Instr{InstrSvc{iid, flags, imm32}});
4012}
4013
4014template <typename TCpuAccessor, typename TItOps>
4015static Result<Instr> BkptT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
4016 static_cast<void>(cpua); // prevents warning when cpua is not used
4017 const InstrId iid{InstrId::kBkpt};
4018 u8 flags = 0x0U;
4019
4020 assert((Bm16::ExtractBits1R<15U, 8U>(rinstr.low)) == 0b10111110U);
4021
4022 const u32 imm8 = Bm16::ExtractBits1R<7U, 0U>(rinstr.low);
4023 const u32 imm32 = Bm32::ZeroExtend<u32>(imm8);
4024
4025 return Ok(Instr{InstrBkpt{iid, flags, imm32}});
4026}
4027
4028template <typename TCpuAccessor, typename TItOps>
4029static Result<Instr> MsrT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
4030 static_cast<void>(cpua); // prevents warning when cpua is not used
4031 const InstrId iid{InstrId::kMsr};
4032 u8 flags = 0x0U;
4033
4034 assert((Bm16::ExtractBits1R<15U, 4U>(rinstr.low)) == 0b111100111000U);
4035 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1000U);
4036 assert((Bm16::ExtractBits1R<9U, 8U>(rinstr.high)) == 0b00U);
4037
4038 const u8 n = static_cast<u8>(Bm16::ExtractBits1R<3U, 0U>(rinstr.low));
4039 const u8 mask = static_cast<u8>(Bm16::ExtractBits1R<11U, 10U>(rinstr.high));
4040 const u8 SYSm = static_cast<u8>(Bm16::ExtractBits1R<7U, 0U>(rinstr.high));
4041
4042 if (mask == 0b00U || (mask != 0b10U && !(SYSm == 0U || SYSm == 1U || SYSm == 2U || SYSm == 3U))) {
4043 return Err<Instr>(StatusCode::kDecoderUnpredictable);
4044 }
4045 if ((n == 13U) || (n == 15U) ||
4046 !(SYSm == 0U || SYSm == 1U || SYSm == 2U || SYSm == 3U || SYSm == 5U || SYSm == 6U ||
4047 SYSm == 7U || SYSm == 8U || SYSm == 9U || SYSm == 16U || SYSm == 17U || SYSm == 18U ||
4048 SYSm == 19U || SYSm == 20U)) {
4049 return Err<Instr>(StatusCode::kDecoderUnpredictable);
4050 }
4051 flags |= static_cast<u8>(InstrFlags::k32Bit);
4052
4053 return Ok(Instr{InstrMsr{iid, flags, n, mask, SYSm}});
4054}
4055
4056template <typename TCpuAccessor, typename TItOps>
4057static Result<Instr> MrsT1Decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
4058 static_cast<void>(cpua); // prevents warning when cpua is not used
4059 const InstrId iid{InstrId::kMrs};
4060 u8 flags = 0x0U;
4061
4062 assert(rinstr.low == 0b1111001111101111U);
4063 assert((Bm16::ExtractBits1R<15U, 12U>(rinstr.high)) == 0b1000U);
4064
4065 const u8 d = static_cast<u8>(Bm16::ExtractBits1R<11U, 8U>(rinstr.high));
4066 const u8 mask = static_cast<u8>(Bm16::ExtractBits1R<11U, 10U>(rinstr.high));
4067 const u8 SYSm = static_cast<u8>(Bm16::ExtractBits1R<7U, 0U>(rinstr.high));
4068
4069 if ((d == 13U) || (d == 15U) ||
4070 !(SYSm == 0U || SYSm == 1U || SYSm == 2U || SYSm == 3U || SYSm == 5U || SYSm == 6U ||
4071 SYSm == 7U || SYSm == 8U || SYSm == 9U || SYSm == 16U || SYSm == 17U || SYSm == 18U ||
4072 SYSm == 19U || SYSm == 20U)) {
4073 return Err<Instr>(StatusCode::kDecoderUnpredictable);
4074 }
4075 flags |= static_cast<u8>(InstrFlags::k32Bit);
4076
4077 return Ok(Instr{InstrMrs{iid, flags, d, mask, SYSm}});
4078}
4079
4080template <typename TCpuAccessor, typename TItOps>
4081static Result<Instr> Splitter16bit_op00000(const RawInstr &rinstr, TCpuAccessor &cpua) {
4082 // # 16-bit Thumb instruction encoding
4083 // see Armv7-M Architecture Reference Manual Issue E.e p129
4084 //
4085 // # Shift (immediate), add, subtract, move, and compare
4086 const u16 opcode = Bm16::ExtractBits1R<13U, 9U>(rinstr.low);
4087 if (Bm16::ExtractBits1R<4U, 2U>(opcode) == 0b000U) {
4088 if (Bm16::ExtractBits1R<10U, 6U>(rinstr.low) == 0b00000U) {
4089 return MovRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4090 } else {
4091 return LslImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4092 }
4093 }
4094 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4095}
4096template <typename TCpuAccessor, typename TItOps>
4097static Result<Instr> Splitter16bit_op00011(const RawInstr &rinstr, TCpuAccessor &cpua) {
4098 // # 16-bit Thumb instruction encoding
4099 // see Armv7-M Architecture Reference Manual Issue E.e p129
4100 //
4101 // # Shift (immediate), add, subtract, move, and compare
4102 // see Armv7-M Architecture Reference Manual Issue E.e p130
4103 const u16 opcode = Bm16::ExtractBits1R<13U, 9U>(rinstr.low);
4104 if (opcode == 0b01100U) {
4105 return AddRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4106 } else if (opcode == 0b01110U) {
4107 return AddImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4108 } else if (opcode == 0b01101U) {
4109 return SubRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4110 } else if (opcode == 0b01111U) {
4111 return SubImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4112 }
4113 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4114}
4115template <typename TCpuAccessor, typename TItOps>
4116static Result<Instr> Splitter16bit_op01010(const RawInstr &rinstr, TCpuAccessor &cpua) {
4117 // # Load/store single data item
4118 // see Armv7-M Architecture Reference Manual Issue E.e p133
4119 //
4120 const u16 op_a = Bm16::ExtractBits1R<15U, 12U>(rinstr.low);
4121 const u16 op_b = Bm16::ExtractBits1R<11U, 9U>(rinstr.low);
4122 if (op_a == 0b0101U && op_b == 0b000U) {
4123 return StrRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4124 } else if (op_a == 0b0101U && op_b == 0b010U) {
4125 return StrbRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4126 }
4127 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4128}
4129template <typename TCpuAccessor, typename TItOps>
4130static Result<Instr> Splitter16bit_op10111(const RawInstr &rinstr, TCpuAccessor &cpua) {
4131 // # Miscellaneous 16-bit instructions
4132 // see Armv7-M Architecture Reference Manual Issue E.e p134
4133 //
4134 const u16 opcode = Bm16::ExtractBits1R<11U, 5U>(rinstr.low);
4135 if (Bm16::ExtractBits1R<6U, 3U>(opcode) == 0b1001U) {
4136 return CbNZT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4137 } else if (Bm16::ExtractBits1R<6U, 3U>(opcode) == 0b1011U) {
4138 return CbNZT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4139 } else if (Bm16::ExtractBits1R<6U, 4U>(opcode) == 0b110U) {
4140 return PopT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4141 } else if (Bm16::ExtractBits1R<6U, 3U>(opcode) == 0b1110U) {
4142 return BkptT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4143 } else if (Bm16::ExtractBits1R<6U, 3U>(opcode) == 0b1111U) {
4144 // # If-Then, and hints
4145 // see Armv7-M Architecture Reference Manual Issue E.e p135
4146 if (Bm16::ExtractBits1R<3U, 0U>(rinstr.low) != 0x0U) {
4147 return ItT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4148 }
4149 if ((Bm16::ExtractBits1R<3U, 0U>(rinstr.low) == 0x0U) &&
4150 (Bm16::ExtractBits1R<7U, 4U>(rinstr.low) == 0x0U)) {
4151 return NopT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4152 }
4153 }
4154 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4155}
4156template <typename TCpuAccessor, typename TItOps>
4157static Result<Instr> Splitter16bit_op10110(const RawInstr &rinstr, TCpuAccessor &cpua) {
4158 // # 16-bit Thumb instruction encoding
4159 // see Armv7-M Architecture Reference Manual Issue E.e p129
4160 //
4161 // ## Miscellaneous 16-bit instructions
4162 // see Armv7-M Architecture Reference Manual Issue E.e p134
4163 const u16 opcode = Bm16::ExtractBits1R<11U, 5U>(rinstr.low);
4164 if (Bm16::ExtractBits1R<6U, 2U>(opcode) == 0b00000U) {
4165 return AddSpPlusImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4166 } else if (Bm16::ExtractBits1R<6U, 3U>(opcode) == 0b0001U) {
4167 return CbNZT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4168 } else if (Bm16::ExtractBits1R<6U, 2U>(opcode) == 0b00001U) {
4169 return SubSpMinusImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4170 } else if (Bm16::ExtractBits1R<6U, 3U>(opcode) == 0b0011U) {
4171 return CbNZT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4172 } else if (Bm16::ExtractBits1R<6U, 1U>(opcode) == 0b001001U) {
4173 return SxtbT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4174 } else if (Bm16::ExtractBits1R<6U, 1U>(opcode) == 0b001011U) {
4175 return UxtbT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4176 } else if (Bm16::ExtractBits1R<6U, 1U>(opcode) == 0b001010U) {
4177 return UxthT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4178 } else if (Bm16::ExtractBits1R<6U, 1U>(opcode) == 0b001000U) {
4179 return SxthT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4180 } else if (Bm16::ExtractBits1R<6U, 4U>(opcode) == 0b010U) {
4181 return PushT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4182 }
4183 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4184}
4185template <typename TCpuAccessor, typename TItOps>
4186static Result<Instr> Splitter16bit_op01000(const RawInstr &rinstr, TCpuAccessor &cpua) {
4187 if (Bm16::IsolateBit<10U>(rinstr.low) == 0x1) {
4188 // ## Special data instructions and branch and exchange
4189 // see Armv7-M Architecture Reference Manual Issue E.e p132
4190 if (Bm16::ExtractBits1R<9U, 8U>(rinstr.low) == 0b00U) {
4191 return AddRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4192 } else if (Bm16::ExtractBits1R<9U, 8U>(rinstr.low) == 0b10U) {
4193 return MovRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4194 } else if (Bm16::ExtractBits1R<9U, 8U>(rinstr.low) == 0b01U) {
4195 return CmpRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4196 } else if (Bm16::ExtractBits1R<9U, 7U>(rinstr.low) == 0b110U) {
4197 return BxT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4198 } else if (Bm16::ExtractBits1R<9U, 7U>(rinstr.low) == 0b111U) {
4199 return BlxT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4200 }
4201 } else {
4202 // ## Data processing
4203 // see Armv7-M Architecture Reference Manual Issue E.e p131
4204 const u16 _opcode = Bm16::ExtractBits1R<9U, 6U>(rinstr.low);
4205 if (_opcode == 0b0000U) {
4206 return AndRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4207 } else if (_opcode == 0b0010U) {
4208 return LslRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4209 } else if (_opcode == 0b0011U) {
4210 return LsrRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4211 } else if (_opcode == 0b0100U) {
4212 return AsrRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4213 } else if (_opcode == 0b0101U) {
4214 return AdcRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4215 } else if (_opcode == 0b0001U) {
4216 return EorRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4217 } else if (_opcode == 0b1000U) {
4218 return TstRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4219 } else if (_opcode == 0b1001U) {
4220 return RsbImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4221 } else if (_opcode == 0b1010U) {
4222 return CmpRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4223 } else if (_opcode == 0b1100U) {
4224 return OrrRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4225 } else if (_opcode == 0b1110U) {
4226 return BicRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4227 }
4228 }
4229 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4230}
4231template <typename TCpuAccessor, typename TItOps>
4232static Result<Instr> Splitter16bit_op01011(const RawInstr &rinstr, TCpuAccessor &cpua) {
4233 // # 16-bit Thumb instruction encoding
4234 // see Armv7-M Architecture Reference Manual Issue E.e p129
4235
4236 const u16 opB = Bm16::ExtractBits1R<11U, 9U>(rinstr.low);
4237 // # Load/store single data item
4238 // see Armv7-M Architecture Reference Manual Issue E.e p133
4239 if (opB == 0b100U) {
4240 return LdrRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4241 } else if (opB == 0b110U) {
4242 return LdrbRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4243 }
4244 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4245}
4246template <typename TCpuAccessor, typename TItOps>
4247static Result<Instr> Splitter16bit_op01101(const RawInstr &rinstr, TCpuAccessor &cpua) {
4248 // # 16-bit Thumb instruction encoding
4249 // see Armv7-M Architecture Reference Manual Issue E.e p129
4250
4251 const u16 opB = Bm16::ExtractBits1R<11U, 9U>(rinstr.low);
4252 // # Load/store single data item
4253 // see Armv7-M Architecture Reference Manual Issue E.e p133
4254 if (Bm16::ExtractBits1R<2U, 2U>(opB) == 0b1U) {
4255 return LdrImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4256 }
4257 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4258}
4259template <typename TCpuAccessor, typename TItOps>
4260static Result<Instr> Splitter16bit_op11011(const RawInstr &rinstr, TCpuAccessor &cpua) {
4261 // # 16-bit Thumb instruction encoding
4262 // see Armv7-M Architecture Reference Manual Issue E.e p129
4263 //
4264 // ## Conditional branch, and Supervisor Call
4265 // see Armv7-M Architecture Reference Manual Issue E.e p136
4266 const u16 opcode = Bm16::ExtractBits1R<11U, 8U>(rinstr.low);
4267 if (Bm16::ExtractBits1R<3U, 1U>(opcode) != 0b111U) {
4268 return BT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4269 } else if (opcode == 0b1111U) {
4270 return SvcT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4271 }
4272 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4273}
4274template <typename TCpuAccessor, typename TItOps>
4275static Result<Instr> Splitter32bit_op11101(const RawInstr &rinstr, TCpuAccessor &cpua) {
4276 // # 32-bit Thumb instruction encoding
4277 // see Armv7-M Architecture Reference Manual Issue E.e p137
4278 if (Bm16::ExtractBits1R<10U, 9U>(rinstr.low) == 0b01U) {
4279 // ## Data processing (shifted register)
4280 // see Armv7-M Architecture Reference Manual Issue E.e p150
4281 const u16 op = Bm16::ExtractBits1R<8U, 5U>(rinstr.low);
4282 const u16 Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
4283 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4284 const u16 S = Bm16::IsolateBit<4U>(rinstr.low);
4285 if ((op == 0b0000U) && (Rd != 0b1111U)) {
4286 return AndRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4287 } else if (op == 0b0001U) {
4288 return BicRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4289 } else if (op == 0b0011U && Rn == 0b1111U) {
4290 return MvnRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4291 } else if (op == 0b1000U && Rd != 0b1111U) {
4292 return AddRegisterT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4293 } else if (op == 0b1110U) {
4294 return RsbRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4295 } else if (op == 0b0010U && Rn == 0b1111U) {
4296 // ### Move register and immediate shifts
4297 // see Armv7-M Architecture Reference Manual Issue E.e p151
4298 const u32 type = static_cast<u32>(Bm16::ExtractBits1R<5U, 4U>(rinstr.high));
4299 const u32 imm2 = static_cast<u32>(Bm16::ExtractBits1R<7U, 6U>(rinstr.high));
4300 const u32 imm3 = static_cast<u32>(Bm16::ExtractBits1R<14U, 12U>(rinstr.high));
4301 const u32 imm3_2 = imm3 << 2U | imm2;
4302 if (type == 0b00U && imm3_2 == 0b00000U) {
4303 return MovRegisterT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4304 } else if (type == 0b01U) {
4305 return LsrImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4306 } else if (type == 0b10U) {
4307 return AsrImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4308 } else if (type == 0b00U && imm3_2 != 0b00000U) {
4309 return LslImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4310 } else if (type == 0b11U && imm3_2 == 0b00000U) {
4311 return RrxT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4312 }
4313 } else if (op == 0b0010U && Rn != 0b1111U) {
4314 return OrrRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4315 } else if (op == 0b0100U && Rd != 0b1111U) {
4316 return EorRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4317 } else if (op == 0b0100U && Rd == 0b1111U && S == 1) {
4318 return TeqRegisterT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4319 } else if (op == 0b0100U && Rd == 0b1111U && S == 0) {
4320 return Err<Instr>(StatusCode::kDecoderUnpredictable);
4321 } else if (op == 0b1101U && Rd != 0b1111U) {
4322 return SubRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4323 } else if (op == 0b1010U) {
4324 return AdcRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4325 } else if (op == 0b1011U) {
4326 return SbcRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4327 } else if (op == 0b1101U && Rd == 0b1111U) {
4328 return CmpRegisterT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4329 }
4330 } else if ((Bm16::ExtractBits1R<10U, 9U>(rinstr.low) == 0b00U) &&
4331 (Bm16::IsolateBit<6U>(rinstr.low) == 0b0U)) {
4332 // ## Load Multiple and Store Multiple
4333 // see Armv7-M Architecture Reference Manual Issue E.e p144
4334 const u16 op = Bm16::ExtractBits1R<8U, 7U>(rinstr.low);
4335 const u16 W = Bm16::IsolateBit<5U>(rinstr.low);
4336 const u16 Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4337 const u16 L = Bm16::IsolateBit<4U>(rinstr.low);
4338 const u16 W_Rn = (W << 4U) | Rn;
4339 if ((op == 0b10U) && (L == 0U) && (W_Rn == 0b11101U)) {
4340 return PushT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4341 } else if ((op == 0b01U) && (L == 0U)) {
4342 return StmT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4343 } else if ((op == 0b10U) && (L == 0U) && (W_Rn != 0b11101U)) {
4344 return StmdbT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4345 } else if ((op == 0b01U) && (L == 1U) && (W_Rn != 0b11101U)) {
4346 return LdmT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4347 } else if ((op == 0b01U) && (L == 1U) && (W_Rn == 0b11101U)) {
4348 return PopT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4349 }
4350 } else if ((Bm16::ExtractBits1R<10U, 9U>(rinstr.low) == 0b00U) &&
4351 (Bm16::IsolateBit<6U>(rinstr.low) == 0b1U)) {
4352 // ## Load/store dual or exclusive, table branch
4353 // see Armv7-M Architecture Reference Manual Issue E.e p145
4354 const u16 op1 = Bm16::ExtractBits1R<8U, 7U>(rinstr.low);
4355 const u16 op2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.low);
4356 const u16 op3 = Bm16::ExtractBits1R<7U, 4U>(rinstr.high);
4357 if (op1 == 0b00U && op2 == 0b00U) {
4358 return StrexT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4359 } else if (op1 == 0b00U && op2 == 0b01U) {
4360 return LdrexT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4361 } else if ((Bm16::ExtractBits1R<1U, 1U>(op1) == 0b0U) && (op2 == 0b10U)) {
4362 return StrdImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4363 } else if ((Bm16::ExtractBits1R<1U, 1U>(op1) == 0b1U) &&
4364 (Bm16::ExtractBits1R<0U, 0U>(op2) == 0b0U)) {
4365 return StrdImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4366 } else if ((Bm16::ExtractBits1R<1U, 1U>(op1) == 0b0U) && (op2 == 0b11U)) {
4367 return LdrdImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4368 } else if ((Bm16::ExtractBits1R<1U, 1U>(op1) == 0b1U) &&
4369 (Bm16::ExtractBits1R<0U, 0U>(op2) == 0b1U)) {
4370 return LdrdImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4371 } else if ((op1 == 0b01U) && (op2 == 0b01U) && (op3 == 0b0000U)) {
4372 return TbbHT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4373 } else if ((op1 == 0b01U) && (op2 == 0b01U) && (op3 == 0b0001U)) {
4374 return TbbHT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4375 }
4376 }
4377 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4378}
4379template <typename TCpuAccessor, typename TItOps>
4380static Result<Instr> Splitter32bit_op11110(const RawInstr &rinstr, TCpuAccessor &cpua) {
4381 // # 32-bit Thumb instruction encoding
4382 // see Armv7-M Architecture Reference Manual Issue E.e p137
4383 const u16 op1 = Bm16::ExtractBits1R<12U, 11U>(rinstr.low);
4384 const u16 op2 = Bm16::ExtractBits1R<10U, 4U>(rinstr.low);
4385 const u16 op = Bm16::IsolateBit<15U>(rinstr.high);
4386 if ((op1 == 0b10U) && (op == 0b1U)) {
4387 // ## Branches and miscellaneous control
4388 // see Armv7-M Architecture Reference Manual Issue E.e p142
4389 const u16 _op1 = Bm16::ExtractBits1R<14U, 12U>(rinstr.high);
4390 const u16 _op = Bm16::ExtractBits1R<10U, 4U>(rinstr.low);
4391 if ((_op1 == 0b000U || _op1 == 0b010U) && (Bm16::ExtractBits1R<5U, 3U>(_op) != 0b111U)) {
4392 return BT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4393 } else if ((_op1 == 0b000U || _op1 == 0b010U) &&
4394 (Bm16::ExtractBits1R<6U, 1U>(_op) == 0b011100U)) {
4395 return MsrT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4396 } else if ((_op1 == 0b000U || _op1 == 0b010U) &&
4397 (Bm16::ExtractBits1R<6U, 1U>(_op) == 0b011111U)) {
4398 return MrsT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4399 } else if (_op1 == 0b001U || _op1 == 0b011U) { // attention the x in the docs does not mean hex
4400 return BT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4401 } else if (_op1 == 0b101U || _op1 == 0b111U) {
4402 return BlT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4403 } else if ((_op1 == 0b000U || _op1 == 0b010U) && (_op == 0b0111011U)) {
4404 // ### Miscellaneous control instructions
4405 // see Armv7-M Architecture Reference Manual Issue E.e p143
4406 const u16 _opc = Bm16::ExtractBits1R<7U, 4U>(rinstr.high);
4407 // const u16 _option = Bm16::ExtractBits1R<3U, 0U>(rinstr.high);
4408 if (_opc == 0b0101U) {
4409 return DmbT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4410 }
4411 }
4412 } else if ((op1 == 0b10U) && (Bm16::IsolateBit<5U>(op2) == 0b0U) && (op == 0x0U)) {
4413 // ## Data processing (modified immediate)
4414 // see Armv7-M Architecture Reference Manual Issue E.e p138
4415 const u16 _op = Bm16::ExtractBits1R<8U, 4U>(rinstr.low);
4416 const u16 _Rd = Bm16::ExtractBits1R<11U, 8U>(rinstr.high);
4417 const u16 _Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4418 if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0000U) && _Rd == 0b1111U) {
4419 return TstImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4420 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0000U) && _Rd != 0b1111U) {
4421 return AndImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4422 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0010U) && _Rn != 0b1111U) {
4423 return OrrImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4424 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0010U) && _Rn == 0b1111U) {
4425 return MovImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4426 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0011U) && _Rn == 0b1111U) {
4427 return MvnImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4428 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0100U) && _Rd != 0b1111U) {
4429 return EorImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4430 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0100U) && _Rd == 0b1111U) {
4431 return TeqImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4432 } else if (Bm16::ExtractBits1R<4U, 1U>(_op) == 0b0001U) {
4433 return BicImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4434 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1000U) && _Rd != 0b1111U) {
4435 return AddImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4436 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1000U) && _Rd == 0b1111U) {
4437 return CmnImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4438 } else if (Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1010U) {
4439 return AdcImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4440 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1101U) && _Rd != 0b1111U) {
4441 return SubImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4442 } else if ((Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1101U) && _Rd == 0b1111U) {
4443 return CmpImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4444 } else if (Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1011U) {
4445 return SbcImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4446 } else if (Bm16::ExtractBits1R<4U, 1U>(_op) == 0b1110U) {
4447 return RsbImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4448 }
4449 } else if ((op1 == 0b10U) && (Bm16::IsolateBit<5U>(op2) == 0b1U) && (op == 0x0U)) {
4450 // ## Data processing (plain binary immediate)
4451 // see Armv7-M Architecture Reference Manual Issue E.e p141
4452 const u16 _op = Bm16::ExtractBits1R<8U, 4U>(rinstr.low);
4453 const u16 _Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4454 if (_op == 0b00100U) {
4455 return MovImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4456 } else if (_op == 0b00000U && _Rn != 0b1111U) {
4457 return AddImmediateT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4458 } else if (_op == 0b01010U && _Rn != 0b1111U) {
4459 return SubImmediateT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4460 } else if (_op == 0b10110U && _Rn != 0b1111U) {
4461 return BfiT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4462 } else if (_op == 0b11100U) {
4463 return UbfxT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4464 }
4465 }
4466 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4467}
4468template <typename TCpuAccessor, typename TItOps>
4469static Result<Instr> Splitter32bit_op11111(const RawInstr &rinstr, TCpuAccessor &cpua) {
4470 // # 32-bit Thumb instruction encoding
4471 // see Armv7-M Architecture Reference Manual Issue E.e p137
4472 // op1 is set by jump table
4473 const u16 op2 = Bm16::ExtractBits1R<10U, 4U>(rinstr.low);
4474 if ((Bm16::ExtractBits1R<6U, 4U>(op2) == 0b000U) && (Bm16::ExtractBits1R<0U, 0U>(op2) == 0b0U)) {
4475 // ## Store single data item
4476 // see Armv7-M Architecture Reference Manual Issue E.e p149
4477 const u16 _op1 = Bm16::ExtractBits1R<7U, 5U>(rinstr.low);
4478 const u16 _op2 = Bm16::ExtractBits1R<11U, 6U>(rinstr.high);
4479 if (_op1 == 0b100U) {
4480 return StrbImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4481 } else if (_op1 == 0b101U) {
4482 return StrhImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4483 } else if (_op1 == 0b001U && Bm16::IsolateBit<5U>(_op2) == 0b1U) {
4484 return StrhImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4485 } else if (_op1 == 0b000U && Bm16::IsolateBit<5U>(_op2) == 0b1U) {
4486 return StrbImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4487 } else if (_op1 == 0b010U && Bm16::IsolateBit<5U>(_op2) == 0b1U) {
4488 return StrImmediateT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4489 } else if (_op1 == 0b010U && Bm16::IsolateBit<5U>(_op2) == 0b0U) {
4490 return StrRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4491 } else if (_op1 == 0b001U && Bm16::IsolateBit<5U>(_op2) == 0b0U) {
4492 return StrhRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4493 } else if (_op1 == 0b000U && Bm16::IsolateBit<5U>(_op2) == 0b0U) {
4494 return StrbRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4495 } else if (_op1 == 0b110U) {
4496 return StrImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4497 }
4498 } else if ((Bm16::ExtractBits1R<6U, 5U>(op2) == 0b00U) &&
4499 (Bm16::ExtractBits1R<2U, 0U>(op2) == 0b001U)) {
4500 // ## Load byte, memory hints
4501 // see Armv7-M Architecture Reference Manual Issue E.e p148
4502 const u16 _op1 = Bm16::ExtractBits1R<8U, 7U>(rinstr.low);
4503 const u16 _op2 = Bm16::ExtractBits1R<11U, 6U>(rinstr.high);
4504 const u16 _Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4505 const u16 _Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
4506 if (_op1 == 0b01U && _Rn != 0b1111 && _Rt != 0b1111U) {
4507 return LdrbImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4508 } else if (_op1 == 0b00U && (Bm16::IsolateBit<5U>(_op2) == 0b1U) &&
4509 (Bm16::ExtractBits1R<2U, 2U>(_op2) == 0b1U) && _Rn != 0b1111 && _Rt != 0b1111U) {
4510 return LdrbImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4511 } else if (_op1 == 0b00U && Bm16::ExtractBits1R<5U, 2U>(_op2) == 0b1100U && _Rn != 0b1111 &&
4512 _Rt != 0b1111U) {
4513 return LdrbImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4514 } else if (_op1 == 0b11U && _Rn != 0b1111 && _Rt != 0b1111U) {
4515 return LdrsbImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4516 }
4517 } else if ((Bm16::ExtractBits1R<6U, 5U>(op2) == 0b00U) &&
4518 (Bm16::ExtractBits1R<2U, 0U>(op2) == 0b011U)) {
4519 // ## Load halfword, memory hints
4520 // see Armv7-M Architecture Reference Manual Issue E.e p147
4521 const u16 _op1 = Bm16::ExtractBits1R<8U, 7U>(rinstr.low);
4522 const u16 _op2 = Bm16::ExtractBits1R<11U, 6U>(rinstr.high);
4523 const u16 _Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4524 const u16 _Rt = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
4525 if (_op1 == 0b01U && _Rn != 0b1111U && _Rt != 0b1111U) {
4526 return LdrhImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4527 } else if (_op1 == 0b00U && (_op2 == 0b000000U) && _Rn != 0b1111U && _Rt != 0b1111U) {
4528 return LdrhRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4529 } else if (_op1 == 0b11U && _Rn != 0b1111U && _Rt != 0b1111U) {
4530 return LdrshImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4531 } else if (_op1 == 0b00U && Bm16::ExtractBits1R<2U, 2U>(_op2) == 0b1U &&
4532 Bm16::IsolateBit<5U>(_op2) == 0b1U && _Rn != 0b1111U && _Rt != 0b1111U) {
4533 return LdrhImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4534 } else if (_op1 == 0b00U && Bm16::ExtractBits1R<5U, 2U>(_op2) == 0b1100U && _Rn != 0b1111U &&
4535 _Rt != 0b1111U) {
4536 return LdrhImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4537 } else if (_op1 == 0b10U && Bm16::ExtractBits1R<2U, 2U>(_op2) == 0b1U &&
4538 Bm16::IsolateBit<5U>(_op2) == 0b1U && _Rn != 0b1111U && _Rt != 0b1111U) {
4539 return LdrshImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4540 } else if (_op1 == 0b10U && Bm16::ExtractBits1R<5U, 2U>(_op2) == 0b1100U && _Rn != 0b1111U &&
4541 _Rt != 0b1111U) {
4542 return LdrshImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4543 }
4544 } else if ((Bm16::ExtractBits1R<6U, 5U>(op2) == 0b00U) &&
4545 (Bm16::ExtractBits1R<2U, 0U>(op2) == 0b101U)) {
4546 // ## Load word
4547 // see Armv7-M Architecture Reference Manual Issue E.e p146
4548 const u16 _op1 = Bm16::ExtractBits1R<8U, 7U>(rinstr.low);
4549 const u16 _op2 = Bm16::ExtractBits1R<11U, 6U>(rinstr.high);
4550 const u16 _Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4551 if ((Bm16::ExtractBits1R<1U, 1U>(_op1) == 0b0U) && _Rn == 0b1111U) {
4552 return LdrLiteralT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4553 } else if (_op1 == 0b01U && _Rn != 0b1111U) {
4554 return LdrImmediateT3Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4555 } else if (_op1 == 0b00U && Bm16::IsolateBit<5U>(_op2) == 0b1U &&
4556 (Bm16::ExtractBits1R<2U, 2U>(_op2) == 0b1U) && _Rn != 0b1111U) {
4557 return LdrImmediateT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4558 } else if (_op1 == 0b00U && Bm16::ExtractBits1R<5U, 2U>(_op2) == 0b1100U && _Rn != 0b1111U) {
4559 return LdrImmediateT4Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4560 } else if (_op1 == 0b00U && _op2 == 0b000000U && _Rn != 0b1111U) {
4561 return LdrRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4562 }
4563 } else if (Bm16::ExtractBits1R<6U, 4U>(op2) == 0b010U) {
4564 // ## Data processing (register)
4565 // see Armv7-M Architecture Reference Manual Issue E.e p152
4566 const u16 _op1 = Bm16::ExtractBits1R<7U, 4U>(rinstr.low);
4567 const u16 _op2 = Bm16::ExtractBits1R<7U, 4U>(rinstr.high);
4568 const u16 _Rn = Bm16::ExtractBits1R<3U, 0U>(rinstr.low);
4569 if ((Bm16::ExtractBits1R<3U, 1U>(_op1) == 0b000U) && _op2 == 0b0000U) {
4570 return LslRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4571 } else if ((Bm16::ExtractBits1R<3U, 1U>(_op1) == 0b001U) && _op2 == 0b0000U) {
4572 return LsrRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4573 } else if ((Bm16::ExtractBits1R<3U, 1U>(_op1) == 0b010U) && _op2 == 0b0000U) {
4574 return AsrRegisterT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4575 } else if (_op1 == 0b0001U && (Bm16::ExtractBits1R<3U, 3U>(_op2) == 0b1U) && _Rn == 0b1111U) {
4576 return UxthT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4577 } else if (_op1 == 0b0100U && (Bm16::ExtractBits1R<3U, 3U>(_op2) == 0b1U) && _Rn == 0b1111U) {
4578 return SxtbT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4579 } else if (_op1 == 0b0000U && (Bm16::ExtractBits1R<3U, 3U>(_op2) == 0b1U) && _Rn == 0b1111U) {
4580 return SxthT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4581 } else if (_op1 == 0b0101U && (Bm16::ExtractBits1R<3U, 3U>(_op2) == 0b1U) && _Rn == 0b1111U) {
4582 return UxtbT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4583 } else if ((Bm16::ExtractBits1R<3U, 2U>(_op1) == 0b10U) &&
4584 (Bm16::ExtractBits1R<3U, 2U>(_op2) == 0b10U)) {
4585 // ## Miscellaneous operations
4586 // see Armv7-M Architecture Reference Manual Issue E.e p155
4587 const u32 __op1 = Bm16::ExtractBits1R<5U, 4U>(rinstr.low);
4588 const u32 __op2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
4589 if ((__op1 == 0b11U) && (__op2 == 0b00U)) {
4590 return ClzT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4591 }
4592 }
4593 } else if (Bm16::ExtractBits1R<6U, 3U>(op2) == 0b0110U) {
4594 // ## Multiply, multiply accumulate, and absolute difference
4595 // see Armv7-M Architecture Reference Manual Issue E.e p156
4596 const u16 _op1 = Bm16::ExtractBits1R<6U, 4U>(rinstr.low);
4597 const u16 _op2 = Bm16::ExtractBits1R<5U, 4U>(rinstr.high);
4598 const u16 _Ra = Bm16::ExtractBits1R<15U, 12U>(rinstr.high);
4599 if (_op1 == 0b000U && _op2 == 0b00U && _Ra == 0b1111U) {
4600 return MulT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4601 } else if (_op1 == 0b000U && _op2 == 0b00U && _Ra != 0b1111U) {
4602 return MlaT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4603 } else if (_op1 == 0b000U && _op2 == 0b01U) {
4604 return MlsT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4605 }
4606 } else if (Bm16::ExtractBits1R<6U, 3U>(op2) == 0b0111U) {
4607 // ## Long multiply, long multiply accumulate, and divide
4608 // see Armv7-M Architecture Reference Manual Issue E.e p156
4609 const u16 _op1 = Bm16::ExtractBits1R<6U, 4U>(rinstr.low);
4610 const u16 _op2 = Bm16::ExtractBits1R<7U, 4U>(rinstr.high);
4611 if (_op1 == 0b010U && _op2 == 0b0000U) {
4612 return UmullT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4613 } else if (_op1 == 0b000U && _op2 == 0b0000U) {
4614 return SmullT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4615 } else if (_op1 == 0b011U && _op2 == 0b1111U) {
4616 return UdivT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4617 } else if (_op1 == 0b001U && _op2 == 0b1111U) {
4618 return SdivT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4619 } else if (_op1 == 0b110U && _op2 == 0b0000U) {
4620 return UmlalT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4621 }
4622 }
4623 return Err<Instr>(StatusCode::kDecoderUnknownOpCode);
4624}
4625
4626template <typename TCpuAccessor, typename TItOps>
4627static Result<Instr> call_decoder(const RawInstr &rinstr, TCpuAccessor &cpua) {
4629 switch (opc) {
4630 case 0b00000U: {
4631 return Splitter16bit_op00000<TCpuAccessor, TItOps>(rinstr, cpua);
4632 }
4633 case 0b00001U: {
4634 return LsrImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4635 }
4636 case 0b00010U: {
4637 return AsrImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4638 }
4639 case 0b00011U: {
4640 return Splitter16bit_op00011<TCpuAccessor, TItOps>(rinstr, cpua);
4641 }
4642 case 0b00100U: {
4643 return MovImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4644 }
4645 case 0b00101U: {
4646 return CmpImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4647 }
4648 case 0b00110U: {
4649 return AddImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4650 }
4651 case 0b00111U: {
4652 return SubImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4653 }
4654 case 0b01000U: {
4655 return Splitter16bit_op01000<TCpuAccessor, TItOps>(rinstr, cpua);
4656 }
4657 case 0b01001U: {
4658 return LdrLiteralT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4659 }
4660 case 0b01010U: {
4661 return Splitter16bit_op01010<TCpuAccessor, TItOps>(rinstr, cpua);
4662 }
4663 case 0b01011U: {
4664 return Splitter16bit_op01011<TCpuAccessor, TItOps>(rinstr, cpua);
4665 }
4666 case 0b01100U: {
4667 return StrImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4668 }
4669 case 0b01101U: {
4670 return Splitter16bit_op01101<TCpuAccessor, TItOps>(rinstr, cpua);
4671 }
4672 case 0b01110U: {
4673 return StrbImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4674 }
4675 case 0b01111U: {
4676 return LdrbImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4677 }
4678 case 0b10000U: {
4679 return StrhImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4680 }
4681 case 0b10001U: {
4682 return LdrhImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4683 }
4684 case 0b10010U: {
4685 return StrImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4686 }
4687 case 0b10011U: {
4688 return LdrImmediateT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4689 }
4690 case 0b10100U: {
4691 return AddPcPlusImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4692 }
4693 case 0b10101U: {
4694 return AddSpPlusImmediateT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4695 }
4696 case 0b10110U: {
4697 return Splitter16bit_op10110<TCpuAccessor, TItOps>(rinstr, cpua);
4698 }
4699 case 0b10111U: {
4700 return Splitter16bit_op10111<TCpuAccessor, TItOps>(rinstr, cpua);
4701 }
4702 case 0b11000U: {
4703 return StmT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4704 }
4705 case 0b11001U: {
4706 return LdmT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4707 }
4708 case 0b11010U: {
4709 return BT1Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4710 }
4711 case 0b11011U: {
4712 return Splitter16bit_op11011<TCpuAccessor, TItOps>(rinstr, cpua);
4713 }
4714 case 0b11100U: {
4715 return BT2Decoder<TCpuAccessor, TItOps>(rinstr, cpua);
4716 }
4717 case 0b11101U: {
4718 return Splitter32bit_op11101<TCpuAccessor, TItOps>(rinstr, cpua);
4719 }
4720 case 0b11110U: {
4721 return Splitter32bit_op11110<TCpuAccessor, TItOps>(rinstr, cpua);
4722 }
4723 case 0b11111U: {
4724 return Splitter32bit_op11111<TCpuAccessor, TItOps>(rinstr, cpua);
4725 }
4726 default: {
4727 assert(false);
4728 // should not happen
4729 break;
4730 }
4731 }
4732 return InvalidInstrDecoder<TCpuAccessor, TItOps>(rinstr, cpua);
4733};
4734
4735} // namespace libmicroemu::internal
Definition bit_manip.h:11
static U ZeroExtend(const u32 &value)
Definition bit_manip.h:200
static constexpr u32 ExtractBits2R(const u32 &value)
Definition bit_manip.h:188
static U SignExtend(const u32 &value)
Definition bit_manip.h:214
static constexpr u16 ExtractBits1R(const u16 &value)
Definition bit_manip.h:136
static u32 BitCount(const u32 &value)
Definition bit_manip.h:243
static constexpr u16 IsolateBit(const u16 &value)
Definition bit_manip.h:114
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
@ kDecoderUndefined
Decoder encountered an undefined operation.
Definition status_code.h:69
@ kDecoderUnknownOpCode
Decoder encountered an unknown opcode.
Definition status_code.h:61
@ kDecoderUnpredictable
Decoder encountered an unpredictable operation.
Definition status_code.h:66
Contains the Result class which is used to return the result of a function.
#define TRY_ASSIGN(NAME, OUT_TYPE, CALL)
Try to assign a value to a variable and return an error if the assignment fails.
Definition result.h:123
Definition imm_shift_results.h:15
Definition instr.h:279
Definition instr.h:285
Definition instr.h:290
Definition instr.h:714
Definition instr.h:264
Definition instr.h:274
Definition instr.h:269
Definition instr.h:258
Definition instr.h:134
Definition instr.h:110
Definition instr.h:252
Definition instr.h:493
Definition instr.h:231
Definition instr.h:351
Definition instr.h:343
Definition instr.h:726
Definition instr.h:719
Definition instr.h:312
Definition instr.h:106
Definition instr.h:488
Definition instr.h:477
Definition instr.h:190
Definition instr.h:305
Definition instr.h:335
Definition instr.h:482
Definition instr.h:471
Definition instr.h:701
Definition instr.h:709
Definition instr.h:506
Definition instr.h:140
Definition instr.h:147
Definition instr.h:520
Definition instr.h:298
Definition instr.h:319
Definition instr.h:327
Definition instr.h:499
Definition instr.h:513
Definition result.h:15
Definition instr.h:734