1 /* This file is part of the dynarmic project.
2 * Copyright (c) 2019 MerryMage
3 * SPDX-License-Identifier: 0BSD
4 */
5
6 #include "frontend/A32/translate/impl/translate_arm.h"
7
8 namespace Dynarmic::A32 {
9
10 // It's considered constrained UNPREDICTABLE behavior if either
11 // CRC32 instruction variant is executed with a condition code
12 // that is *not* 0xE (Always execute). ARM defines one of the following
13 // as being a requirement in this case. Either:
14 //
15 // 1. The instruction is undefined.
16 // 2. The instruction executes as a NOP.
17 // 3. The instruction executes unconditionally.
18 // 4. The instruction executes conditionally.
19 //
20 // It's also considered constrained UNPREDICTABLE behavior if
21 // either CRC32 instruction variant is executed with a size specifier
22 // of 64-bit (sz -> 0b11)
23 //
24 // In this case, either:
25 //
26 // 1. The instruction is undefined
27 // 2. The instruction executes as a NOP.
28 // 3. The instruction executes with the additional decode: size = 32.
29 //
30 // In both cases, we treat as unpredictable, to allow
31 // library users to provide their own intended behavior
32 // in the unpredictable exception handler.
33
34 namespace {
35 enum class CRCType {
36 Castagnoli,
37 ISO,
38 };
39
CRC32Variant(ArmTranslatorVisitor & v,Cond cond,Imm<2> sz,Reg n,Reg d,Reg m,CRCType type)40 bool CRC32Variant(ArmTranslatorVisitor& v, Cond cond, Imm<2> sz, Reg n, Reg d, Reg m, CRCType type) {
41 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
42 return v.UnpredictableInstruction();
43 }
44
45 if (sz == 0b11) {
46 return v.UnpredictableInstruction();
47 }
48
49 if (cond != Cond::AL) {
50 return v.UnpredictableInstruction();
51 }
52
53 const IR::U32 result = [m, n, sz, type, &v] {
54 const IR::U32 accumulator = v.ir.GetRegister(n);
55 const IR::U32 data = v.ir.GetRegister(m);
56
57 if (type == CRCType::ISO) {
58 switch (sz.ZeroExtend()) {
59 case 0b00:
60 return v.ir.CRC32ISO8(accumulator, data);
61 case 0b01:
62 return v.ir.CRC32ISO16(accumulator, data);
63 case 0b10:
64 return v.ir.CRC32ISO32(accumulator, data);
65 }
66 } else {
67 switch (sz.ZeroExtend()) {
68 case 0b00:
69 return v.ir.CRC32Castagnoli8(accumulator, data);
70 case 0b01:
71 return v.ir.CRC32Castagnoli16(accumulator, data);
72 case 0b10:
73 return v.ir.CRC32Castagnoli32(accumulator, data);
74 }
75 }
76
77 UNREACHABLE();
78 }();
79
80 v.ir.SetRegister(d, result);
81 return true;
82 }
83 } // Anonymous namespace
84
85 // CRC32{B,H,W}{<q>} <Rd>, <Rn>, <Rm>
arm_CRC32(Cond cond,Imm<2> sz,Reg n,Reg d,Reg m)86 bool ArmTranslatorVisitor::arm_CRC32(Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
87 return CRC32Variant(*this, cond, sz, n, d, m, CRCType::ISO);
88 }
89
90 // CRC32C{B,H,W}{<q>} <Rd>, <Rn>, <Rm>
arm_CRC32C(Cond cond,Imm<2> sz,Reg n,Reg d,Reg m)91 bool ArmTranslatorVisitor::arm_CRC32C(Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
92 return CRC32Variant(*this, cond, sz, n, d, m, CRCType::Castagnoli);
93 }
94
95 } // namespace Dynarmic::A32
96