1 /* This file is part of the dynarmic project.
2 * Copyright (c) 2018 MerryMage
3 * SPDX-License-Identifier: 0BSD
4 */
5
6 #include "common/bit_util.h"
7 #include "frontend/A64/translate/impl/impl.h"
8
9 namespace Dynarmic::A64 {
10
DUP_elt_1(Imm<5> imm5,Vec Vn,Vec Vd)11 bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
12 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
13 if (size > 3) {
14 return ReservedValue();
15 }
16
17 const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
18 const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
19 const size_t esize = 8 << size;
20
21 const IR::U128 operand = V(idxdsize, Vn);
22 const IR::UAny element = ir.VectorGetElement(esize, operand, index);
23 const IR::U128 result = ir.ZeroExtendToQuad(element);
24 V(128, Vd, result);
25 return true;
26 }
27
DUP_elt_2(bool Q,Imm<5> imm5,Vec Vn,Vec Vd)28 bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
29 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
30 if (size > 3) {
31 return ReservedValue();
32 }
33
34 if (size == 3 && !Q) {
35 return ReservedValue();
36 }
37
38 const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
39 const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
40 const size_t esize = 8 << size;
41 const size_t datasize = Q ? 128 : 64;
42
43 const IR::U128 operand = V(idxdsize, Vn);
44 const IR::UAny element = ir.VectorGetElement(esize, operand, index);
45 const IR::U128 result = Q ? ir.VectorBroadcast(esize, element) : ir.VectorBroadcastLower(esize, element);
46 V(datasize, Vd, result);
47 return true;
48 }
49
DUP_gen(bool Q,Imm<5> imm5,Reg Rn,Vec Vd)50 bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
51 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
52 if (size > 3) {
53 return ReservedValue();
54 }
55
56 if (size == 3 && !Q) {
57 return ReservedValue();
58 }
59
60 const size_t esize = 8 << size;
61 const size_t datasize = Q ? 128 : 64;
62
63 const IR::UAny element = X(esize, Rn);
64
65 const IR::U128 result = Q ? ir.VectorBroadcast(esize, element) : ir.VectorBroadcastLower(esize, element);
66
67 V(datasize, Vd, result);
68
69 return true;
70 }
71
SMOV(bool Q,Imm<5> imm5,Vec Vn,Reg Rd)72 bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
73 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
74 if (size == 2 && !Q) {
75 return UnallocatedEncoding();
76 }
77
78 if (size > 2) {
79 return ReservedValue();
80 }
81
82 const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
83 const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
84 const size_t esize = 8 << size;
85 const size_t datasize = Q ? 64 : 32;
86
87 const IR::U128 operand = V(idxdsize, Vn);
88
89 const IR::UAny elem = ir.VectorGetElement(esize, operand, index);
90 X(datasize, Rd, SignExtend(elem, datasize));
91
92 return true;
93 }
94
UMOV(bool Q,Imm<5> imm5,Vec Vn,Reg Rd)95 bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
96 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
97 if (size < 3 && Q) {
98 return UnallocatedEncoding();
99 }
100
101 if (size == 3 && !Q) {
102 return UnallocatedEncoding();
103 }
104
105 if (size > 3) {
106 return ReservedValue();
107 }
108
109 const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
110 const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
111 const size_t esize = 8 << size;
112 const size_t datasize = Q ? 64 : 32;
113
114 const IR::U128 operand = V(idxdsize, Vn);
115
116 const IR::UAny elem = ir.VectorGetElement(esize, operand, index);
117 X(datasize, Rd, ZeroExtend(elem, datasize));
118
119 return true;
120 }
121
INS_gen(Imm<5> imm5,Reg Rn,Vec Vd)122 bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
123 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
124 if (size > 3) {
125 return ReservedValue();
126 }
127
128 const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
129 const size_t esize = 8 << size;
130 const size_t datasize = 128;
131
132 const IR::UAny element = X(esize, Rn);
133 const IR::U128 result = ir.VectorSetElement(esize, V(datasize, Vd), index, element);
134 V(datasize, Vd, result);
135
136 return true;
137 }
138
INS_elt(Imm<5> imm5,Imm<4> imm4,Vec Vn,Vec Vd)139 bool TranslatorVisitor::INS_elt(Imm<5> imm5, Imm<4> imm4, Vec Vn, Vec Vd) {
140 const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
141 if (size > 3) {
142 return ReservedValue();
143 }
144
145 const size_t dst_index = imm5.ZeroExtend<size_t>() >> (size + 1);
146 const size_t src_index = imm4.ZeroExtend<size_t>() >> size;
147 const size_t idxdsize = imm4.Bit<3>() ? 128 : 64;
148 const size_t esize = 8 << size;
149
150 const IR::U128 operand = V(idxdsize, Vn);
151 const IR::UAny elem = ir.VectorGetElement(esize, operand, src_index);
152 const IR::U128 result = ir.VectorSetElement(esize, V(128, Vd), dst_index, elem);
153 V(128, Vd, result);
154
155 return true;
156 }
157
158 } // namespace Dynarmic::A64
159