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