1*f6dc9357SAndroid Build Coastguard Worker /* Bra.c -- Branch converters for RISC code
2*f6dc9357SAndroid Build Coastguard Worker 2024-01-20 : Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker
4*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
5*f6dc9357SAndroid Build Coastguard Worker
6*f6dc9357SAndroid Build Coastguard Worker #include "Bra.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "RotateDefs.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "CpuArch.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_SIZEOF_POINTER) \
11*f6dc9357SAndroid Build Coastguard Worker && ( MY_CPU_SIZEOF_POINTER == 4 \
12*f6dc9357SAndroid Build Coastguard Worker || MY_CPU_SIZEOF_POINTER == 8)
13*f6dc9357SAndroid Build Coastguard Worker #define BR_CONV_USE_OPT_PC_PTR
14*f6dc9357SAndroid Build Coastguard Worker #endif
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #ifdef BR_CONV_USE_OPT_PC_PTR
17*f6dc9357SAndroid Build Coastguard Worker #define BR_PC_INIT pc -= (UInt32)(SizeT)p;
18*f6dc9357SAndroid Build Coastguard Worker #define BR_PC_GET (pc + (UInt32)(SizeT)p)
19*f6dc9357SAndroid Build Coastguard Worker #else
20*f6dc9357SAndroid Build Coastguard Worker #define BR_PC_INIT pc += (UInt32)size;
21*f6dc9357SAndroid Build Coastguard Worker #define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p))
22*f6dc9357SAndroid Build Coastguard Worker // #define BR_PC_INIT
23*f6dc9357SAndroid Build Coastguard Worker // #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data))
24*f6dc9357SAndroid Build Coastguard Worker #endif
25*f6dc9357SAndroid Build Coastguard Worker
26*f6dc9357SAndroid Build Coastguard Worker #define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;
27*f6dc9357SAndroid Build Coastguard Worker // #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker #define Z7_BRANCH_CONV(name) z7_ ## name
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker #define Z7_BRANCH_FUNC_MAIN(name) \
32*f6dc9357SAndroid Build Coastguard Worker static \
33*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE \
34*f6dc9357SAndroid Build Coastguard Worker Z7_ATTRIB_NO_VECTOR \
35*f6dc9357SAndroid Build Coastguard Worker Byte *Z7_BRANCH_CONV(name)(Byte *p, SizeT size, UInt32 pc, int encoding)
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker #define Z7_BRANCH_FUNC_IMP(name, m, encoding) \
38*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE \
39*f6dc9357SAndroid Build Coastguard Worker Z7_ATTRIB_NO_VECTOR \
40*f6dc9357SAndroid Build Coastguard Worker Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
41*f6dc9357SAndroid Build Coastguard Worker { return Z7_BRANCH_CONV(name)(data, size, pc, encoding); } \
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_EXTRACT_ONLY
44*f6dc9357SAndroid Build Coastguard Worker #define Z7_BRANCH_FUNCS_IMP(name) \
45*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0)
46*f6dc9357SAndroid Build Coastguard Worker #else
47*f6dc9357SAndroid Build Coastguard Worker #define Z7_BRANCH_FUNCS_IMP(name) \
48*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \
49*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1)
50*f6dc9357SAndroid Build Coastguard Worker #endif
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker #if defined(__clang__)
53*f6dc9357SAndroid Build Coastguard Worker #define BR_EXTERNAL_FOR
54*f6dc9357SAndroid Build Coastguard Worker #define BR_NEXT_ITERATION continue;
55*f6dc9357SAndroid Build Coastguard Worker #else
56*f6dc9357SAndroid Build Coastguard Worker #define BR_EXTERNAL_FOR for (;;)
57*f6dc9357SAndroid Build Coastguard Worker #define BR_NEXT_ITERATION break;
58*f6dc9357SAndroid Build Coastguard Worker #endif
59*f6dc9357SAndroid Build Coastguard Worker
60*f6dc9357SAndroid Build Coastguard Worker #if defined(__clang__) && (__clang_major__ >= 8) \
61*f6dc9357SAndroid Build Coastguard Worker || defined(__GNUC__) && (__GNUC__ >= 1000) \
62*f6dc9357SAndroid Build Coastguard Worker // GCC is not good for __builtin_expect() here
63*f6dc9357SAndroid Build Coastguard Worker /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */
64*f6dc9357SAndroid Build Coastguard Worker // #define Z7_unlikely [[unlikely]]
65*f6dc9357SAndroid Build Coastguard Worker // #define Z7_LIKELY(x) (__builtin_expect((x), 1))
66*f6dc9357SAndroid Build Coastguard Worker #define Z7_UNLIKELY(x) (__builtin_expect((x), 0))
67*f6dc9357SAndroid Build Coastguard Worker // #define Z7_likely [[likely]]
68*f6dc9357SAndroid Build Coastguard Worker #else
69*f6dc9357SAndroid Build Coastguard Worker // #define Z7_LIKELY(x) (x)
70*f6dc9357SAndroid Build Coastguard Worker #define Z7_UNLIKELY(x) (x)
71*f6dc9357SAndroid Build Coastguard Worker // #define Z7_likely
72*f6dc9357SAndroid Build Coastguard Worker #endif
73*f6dc9357SAndroid Build Coastguard Worker
74*f6dc9357SAndroid Build Coastguard Worker
Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64)75*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64)
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker // Byte *p = data;
78*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
79*f6dc9357SAndroid Build Coastguard Worker const UInt32 flag = (UInt32)1 << (24 - 4);
80*f6dc9357SAndroid Build Coastguard Worker const UInt32 mask = ((UInt32)1 << 24) - (flag << 1);
81*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)3;
82*f6dc9357SAndroid Build Coastguard Worker // if (size == 0) return p;
83*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
84*f6dc9357SAndroid Build Coastguard Worker BR_PC_INIT
85*f6dc9357SAndroid Build Coastguard Worker pc -= 4; // because (p) will point to next instruction
86*f6dc9357SAndroid Build Coastguard Worker
87*f6dc9357SAndroid Build Coastguard Worker BR_EXTERNAL_FOR
88*f6dc9357SAndroid Build Coastguard Worker {
89*f6dc9357SAndroid Build Coastguard Worker // Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
90*f6dc9357SAndroid Build Coastguard Worker for (;;)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker UInt32 v;
93*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p == lim)
94*f6dc9357SAndroid Build Coastguard Worker return p;
95*f6dc9357SAndroid Build Coastguard Worker v = GetUi32a(p);
96*f6dc9357SAndroid Build Coastguard Worker p += 4;
97*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(((v - 0x94000000) & 0xfc000000) == 0)
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker UInt32 c = BR_PC_GET >> 2;
100*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(v, c)
101*f6dc9357SAndroid Build Coastguard Worker v &= 0x03ffffff;
102*f6dc9357SAndroid Build Coastguard Worker v |= 0x94000000;
103*f6dc9357SAndroid Build Coastguard Worker SetUi32a(p - 4, v)
104*f6dc9357SAndroid Build Coastguard Worker BR_NEXT_ITERATION
105*f6dc9357SAndroid Build Coastguard Worker }
106*f6dc9357SAndroid Build Coastguard Worker // v = rotlFixed(v, 8); v += (flag << 8) - 0x90; if Z7_UNLIKELY((v & ((mask << 8) + 0x9f)) == 0)
107*f6dc9357SAndroid Build Coastguard Worker v -= 0x90000000; if Z7_UNLIKELY((v & 0x9f000000) == 0)
108*f6dc9357SAndroid Build Coastguard Worker {
109*f6dc9357SAndroid Build Coastguard Worker UInt32 z, c;
110*f6dc9357SAndroid Build Coastguard Worker // v = rotrFixed(v, 8);
111*f6dc9357SAndroid Build Coastguard Worker v += flag; if Z7_UNLIKELY(v & mask) continue;
112*f6dc9357SAndroid Build Coastguard Worker z = (v & 0xffffffe0) | (v >> 26);
113*f6dc9357SAndroid Build Coastguard Worker c = (BR_PC_GET >> (12 - 3)) & ~(UInt32)7;
114*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(z, c)
115*f6dc9357SAndroid Build Coastguard Worker v &= 0x1f;
116*f6dc9357SAndroid Build Coastguard Worker v |= 0x90000000;
117*f6dc9357SAndroid Build Coastguard Worker v |= z << 26;
118*f6dc9357SAndroid Build Coastguard Worker v |= 0x00ffffe0 & ((z & (((flag << 1) - 1))) - flag);
119*f6dc9357SAndroid Build Coastguard Worker SetUi32a(p - 4, v)
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker }
122*f6dc9357SAndroid Build Coastguard Worker }
123*f6dc9357SAndroid Build Coastguard Worker }
124*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64)
125*f6dc9357SAndroid Build Coastguard Worker
126*f6dc9357SAndroid Build Coastguard Worker
Z7_BRANCH_FUNC_MAIN(BranchConv_ARM)127*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_MAIN(BranchConv_ARM)
128*f6dc9357SAndroid Build Coastguard Worker {
129*f6dc9357SAndroid Build Coastguard Worker // Byte *p = data;
130*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
131*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)3;
132*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
133*f6dc9357SAndroid Build Coastguard Worker BR_PC_INIT
134*f6dc9357SAndroid Build Coastguard Worker /* in ARM: branch offset is relative to the +2 instructions from current instruction.
135*f6dc9357SAndroid Build Coastguard Worker (p) will point to next instruction */
136*f6dc9357SAndroid Build Coastguard Worker pc += 8 - 4;
137*f6dc9357SAndroid Build Coastguard Worker
138*f6dc9357SAndroid Build Coastguard Worker for (;;)
139*f6dc9357SAndroid Build Coastguard Worker {
140*f6dc9357SAndroid Build Coastguard Worker for (;;)
141*f6dc9357SAndroid Build Coastguard Worker {
142*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break;
143*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break;
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker UInt32 v = GetUi32a(p - 4);
147*f6dc9357SAndroid Build Coastguard Worker UInt32 c = BR_PC_GET >> 2;
148*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(v, c)
149*f6dc9357SAndroid Build Coastguard Worker v &= 0x00ffffff;
150*f6dc9357SAndroid Build Coastguard Worker v |= 0xeb000000;
151*f6dc9357SAndroid Build Coastguard Worker SetUi32a(p - 4, v)
152*f6dc9357SAndroid Build Coastguard Worker }
153*f6dc9357SAndroid Build Coastguard Worker }
154*f6dc9357SAndroid Build Coastguard Worker }
155*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNCS_IMP(BranchConv_ARM)
156*f6dc9357SAndroid Build Coastguard Worker
157*f6dc9357SAndroid Build Coastguard Worker
Z7_BRANCH_FUNC_MAIN(BranchConv_PPC)158*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_MAIN(BranchConv_PPC)
159*f6dc9357SAndroid Build Coastguard Worker {
160*f6dc9357SAndroid Build Coastguard Worker // Byte *p = data;
161*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
162*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)3;
163*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
164*f6dc9357SAndroid Build Coastguard Worker BR_PC_INIT
165*f6dc9357SAndroid Build Coastguard Worker pc -= 4; // because (p) will point to next instruction
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker for (;;)
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker UInt32 v;
170*f6dc9357SAndroid Build Coastguard Worker for (;;)
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p == lim)
173*f6dc9357SAndroid Build Coastguard Worker return p;
174*f6dc9357SAndroid Build Coastguard Worker // v = GetBe32a(p);
175*f6dc9357SAndroid Build Coastguard Worker v = *(UInt32 *)(void *)p;
176*f6dc9357SAndroid Build Coastguard Worker p += 4;
177*f6dc9357SAndroid Build Coastguard Worker // if ((v & 0xfc000003) == 0x48000001) break;
178*f6dc9357SAndroid Build Coastguard Worker // if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) break;
179*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(
180*f6dc9357SAndroid Build Coastguard Worker ((v - Z7_CONV_BE_TO_NATIVE_CONST32(0x48000001))
181*f6dc9357SAndroid Build Coastguard Worker & Z7_CONV_BE_TO_NATIVE_CONST32(0xfc000003)) == 0) break;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker {
184*f6dc9357SAndroid Build Coastguard Worker v = Z7_CONV_NATIVE_TO_BE_32(v);
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker UInt32 c = BR_PC_GET;
187*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(v, c)
188*f6dc9357SAndroid Build Coastguard Worker }
189*f6dc9357SAndroid Build Coastguard Worker v &= 0x03ffffff;
190*f6dc9357SAndroid Build Coastguard Worker v |= 0x48000000;
191*f6dc9357SAndroid Build Coastguard Worker SetBe32a(p - 4, v)
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker }
195*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNCS_IMP(BranchConv_PPC)
196*f6dc9357SAndroid Build Coastguard Worker
197*f6dc9357SAndroid Build Coastguard Worker
198*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_CPU_FAST_ROTATE_SUPPORTED
199*f6dc9357SAndroid Build Coastguard Worker #define BR_SPARC_USE_ROTATE
200*f6dc9357SAndroid Build Coastguard Worker #endif
201*f6dc9357SAndroid Build Coastguard Worker
Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC)202*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC)
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker // Byte *p = data;
205*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
206*f6dc9357SAndroid Build Coastguard Worker const UInt32 flag = (UInt32)1 << 22;
207*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)3;
208*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
209*f6dc9357SAndroid Build Coastguard Worker BR_PC_INIT
210*f6dc9357SAndroid Build Coastguard Worker pc -= 4; // because (p) will point to next instruction
211*f6dc9357SAndroid Build Coastguard Worker for (;;)
212*f6dc9357SAndroid Build Coastguard Worker {
213*f6dc9357SAndroid Build Coastguard Worker UInt32 v;
214*f6dc9357SAndroid Build Coastguard Worker for (;;)
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p == lim)
217*f6dc9357SAndroid Build Coastguard Worker return p;
218*f6dc9357SAndroid Build Coastguard Worker /* // the code without GetBe32a():
219*f6dc9357SAndroid Build Coastguard Worker { const UInt32 v = GetUi16a(p) & 0xc0ff; p += 4; if (v == 0x40 || v == 0xc07f) break; }
220*f6dc9357SAndroid Build Coastguard Worker */
221*f6dc9357SAndroid Build Coastguard Worker v = GetBe32a(p);
222*f6dc9357SAndroid Build Coastguard Worker p += 4;
223*f6dc9357SAndroid Build Coastguard Worker #ifdef BR_SPARC_USE_ROTATE
224*f6dc9357SAndroid Build Coastguard Worker v = rotlFixed(v, 2);
225*f6dc9357SAndroid Build Coastguard Worker v += (flag << 2) - 1;
226*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY((v & (3 - (flag << 3))) == 0)
227*f6dc9357SAndroid Build Coastguard Worker #else
228*f6dc9357SAndroid Build Coastguard Worker v += (UInt32)5 << 29;
229*f6dc9357SAndroid Build Coastguard Worker v ^= (UInt32)7 << 29;
230*f6dc9357SAndroid Build Coastguard Worker v += flag;
231*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY((v & (0 - (flag << 1))) == 0)
232*f6dc9357SAndroid Build Coastguard Worker #endif
233*f6dc9357SAndroid Build Coastguard Worker break;
234*f6dc9357SAndroid Build Coastguard Worker }
235*f6dc9357SAndroid Build Coastguard Worker {
236*f6dc9357SAndroid Build Coastguard Worker // UInt32 v = GetBe32a(p - 4);
237*f6dc9357SAndroid Build Coastguard Worker #ifndef BR_SPARC_USE_ROTATE
238*f6dc9357SAndroid Build Coastguard Worker v <<= 2;
239*f6dc9357SAndroid Build Coastguard Worker #endif
240*f6dc9357SAndroid Build Coastguard Worker {
241*f6dc9357SAndroid Build Coastguard Worker UInt32 c = BR_PC_GET;
242*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(v, c)
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker v &= (flag << 3) - 1;
245*f6dc9357SAndroid Build Coastguard Worker #ifdef BR_SPARC_USE_ROTATE
246*f6dc9357SAndroid Build Coastguard Worker v -= (flag << 2) - 1;
247*f6dc9357SAndroid Build Coastguard Worker v = rotrFixed(v, 2);
248*f6dc9357SAndroid Build Coastguard Worker #else
249*f6dc9357SAndroid Build Coastguard Worker v -= (flag << 2);
250*f6dc9357SAndroid Build Coastguard Worker v >>= 2;
251*f6dc9357SAndroid Build Coastguard Worker v |= (UInt32)1 << 30;
252*f6dc9357SAndroid Build Coastguard Worker #endif
253*f6dc9357SAndroid Build Coastguard Worker SetBe32a(p - 4, v)
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker }
256*f6dc9357SAndroid Build Coastguard Worker }
257*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC)
258*f6dc9357SAndroid Build Coastguard Worker
259*f6dc9357SAndroid Build Coastguard Worker
Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT)260*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT)
261*f6dc9357SAndroid Build Coastguard Worker {
262*f6dc9357SAndroid Build Coastguard Worker // Byte *p = data;
263*f6dc9357SAndroid Build Coastguard Worker Byte *lim;
264*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)1;
265*f6dc9357SAndroid Build Coastguard Worker // if (size == 0) return p;
266*f6dc9357SAndroid Build Coastguard Worker if (size <= 2) return p;
267*f6dc9357SAndroid Build Coastguard Worker size -= 2;
268*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
269*f6dc9357SAndroid Build Coastguard Worker BR_PC_INIT
270*f6dc9357SAndroid Build Coastguard Worker /* in ARM: branch offset is relative to the +2 instructions from current instruction.
271*f6dc9357SAndroid Build Coastguard Worker (p) will point to the +2 instructions from current instruction */
272*f6dc9357SAndroid Build Coastguard Worker // pc += 4 - 4;
273*f6dc9357SAndroid Build Coastguard Worker // if (encoding) pc -= 0xf800 << 1; else pc += 0xf800 << 1;
274*f6dc9357SAndroid Build Coastguard Worker // #define ARMT_TAIL_PROC { goto armt_tail; }
275*f6dc9357SAndroid Build Coastguard Worker #define ARMT_TAIL_PROC { return p; }
276*f6dc9357SAndroid Build Coastguard Worker
277*f6dc9357SAndroid Build Coastguard Worker do
278*f6dc9357SAndroid Build Coastguard Worker {
279*f6dc9357SAndroid Build Coastguard Worker /* in MSVC 32-bit x86 compilers:
280*f6dc9357SAndroid Build Coastguard Worker UInt32 version : it loads value from memory with movzx
281*f6dc9357SAndroid Build Coastguard Worker Byte version : it loads value to 8-bit register (AL/CL)
282*f6dc9357SAndroid Build Coastguard Worker movzx version is slightly faster in some cpus
283*f6dc9357SAndroid Build Coastguard Worker */
284*f6dc9357SAndroid Build Coastguard Worker unsigned b1;
285*f6dc9357SAndroid Build Coastguard Worker // Byte / unsigned
286*f6dc9357SAndroid Build Coastguard Worker b1 = p[1];
287*f6dc9357SAndroid Build Coastguard Worker // optimized version to reduce one (p >= lim) check:
288*f6dc9357SAndroid Build Coastguard Worker // unsigned a1 = p[1]; b1 = p[3]; p += 2; if Z7_LIKELY((b1 & (a1 ^ 8)) < 0xf8)
289*f6dc9357SAndroid Build Coastguard Worker for (;;)
290*f6dc9357SAndroid Build Coastguard Worker {
291*f6dc9357SAndroid Build Coastguard Worker unsigned b3; // Byte / UInt32
292*f6dc9357SAndroid Build Coastguard Worker /* (Byte)(b3) normalization can use low byte computations in MSVC.
293*f6dc9357SAndroid Build Coastguard Worker It gives smaller code, and no loss of speed in some compilers/cpus.
294*f6dc9357SAndroid Build Coastguard Worker But new MSVC 32-bit x86 compilers use more slow load
295*f6dc9357SAndroid Build Coastguard Worker from memory to low byte register in that case.
296*f6dc9357SAndroid Build Coastguard Worker So we try to use full 32-bit computations for faster code.
297*f6dc9357SAndroid Build Coastguard Worker */
298*f6dc9357SAndroid Build Coastguard Worker // if (p >= lim) { ARMT_TAIL_PROC } b3 = b1 + 8; b1 = p[3]; p += 2; if ((b3 & b1) >= 0xf8) break;
299*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b3 = p[3]; p += 2; if Z7_UNLIKELY((b3 & (b1 ^ 8)) >= 0xf8) break;
300*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b1 = p[3]; p += 2; if Z7_UNLIKELY((b1 & (b3 ^ 8)) >= 0xf8) break;
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker {
303*f6dc9357SAndroid Build Coastguard Worker /* we can adjust pc for (0xf800) to rid of (& 0x7FF) operation.
304*f6dc9357SAndroid Build Coastguard Worker But gcc/clang for arm64 can use bfi instruction for full code here */
305*f6dc9357SAndroid Build Coastguard Worker UInt32 v =
306*f6dc9357SAndroid Build Coastguard Worker ((UInt32)GetUi16a(p - 2) << 11) |
307*f6dc9357SAndroid Build Coastguard Worker ((UInt32)GetUi16a(p) & 0x7FF);
308*f6dc9357SAndroid Build Coastguard Worker /*
309*f6dc9357SAndroid Build Coastguard Worker UInt32 v =
310*f6dc9357SAndroid Build Coastguard Worker ((UInt32)p[1 - 2] << 19)
311*f6dc9357SAndroid Build Coastguard Worker + (((UInt32)p[1] & 0x7) << 8)
312*f6dc9357SAndroid Build Coastguard Worker + (((UInt32)p[-2] << 11))
313*f6dc9357SAndroid Build Coastguard Worker + (p[0]);
314*f6dc9357SAndroid Build Coastguard Worker */
315*f6dc9357SAndroid Build Coastguard Worker p += 2;
316*f6dc9357SAndroid Build Coastguard Worker {
317*f6dc9357SAndroid Build Coastguard Worker UInt32 c = BR_PC_GET >> 1;
318*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(v, c)
319*f6dc9357SAndroid Build Coastguard Worker }
320*f6dc9357SAndroid Build Coastguard Worker SetUi16a(p - 4, (UInt16)(((v >> 11) & 0x7ff) | 0xf000))
321*f6dc9357SAndroid Build Coastguard Worker SetUi16a(p - 2, (UInt16)(v | 0xf800))
322*f6dc9357SAndroid Build Coastguard Worker /*
323*f6dc9357SAndroid Build Coastguard Worker p[-4] = (Byte)(v >> 11);
324*f6dc9357SAndroid Build Coastguard Worker p[-3] = (Byte)(0xf0 | ((v >> 19) & 0x7));
325*f6dc9357SAndroid Build Coastguard Worker p[-2] = (Byte)v;
326*f6dc9357SAndroid Build Coastguard Worker p[-1] = (Byte)(0xf8 | (v >> 8));
327*f6dc9357SAndroid Build Coastguard Worker */
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker }
330*f6dc9357SAndroid Build Coastguard Worker while (p < lim);
331*f6dc9357SAndroid Build Coastguard Worker return p;
332*f6dc9357SAndroid Build Coastguard Worker // armt_tail:
333*f6dc9357SAndroid Build Coastguard Worker // if ((Byte)((lim[1] & 0xf8)) != 0xf0) { lim += 2; } return lim;
334*f6dc9357SAndroid Build Coastguard Worker // return (Byte *)(lim + ((Byte)((lim[1] ^ 0xf0) & 0xf8) == 0 ? 0 : 2));
335*f6dc9357SAndroid Build Coastguard Worker // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2));
336*f6dc9357SAndroid Build Coastguard Worker // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2));
337*f6dc9357SAndroid Build Coastguard Worker }
338*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT)
339*f6dc9357SAndroid Build Coastguard Worker
340*f6dc9357SAndroid Build Coastguard Worker
341*f6dc9357SAndroid Build Coastguard Worker // #define BR_IA64_NO_INLINE
342*f6dc9357SAndroid Build Coastguard Worker
Z7_BRANCH_FUNC_MAIN(BranchConv_IA64)343*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNC_MAIN(BranchConv_IA64)
344*f6dc9357SAndroid Build Coastguard Worker {
345*f6dc9357SAndroid Build Coastguard Worker // Byte *p = data;
346*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
347*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)15;
348*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
349*f6dc9357SAndroid Build Coastguard Worker pc -= 1 << 4;
350*f6dc9357SAndroid Build Coastguard Worker pc >>= 4 - 1;
351*f6dc9357SAndroid Build Coastguard Worker // pc -= 1 << 1;
352*f6dc9357SAndroid Build Coastguard Worker
353*f6dc9357SAndroid Build Coastguard Worker for (;;)
354*f6dc9357SAndroid Build Coastguard Worker {
355*f6dc9357SAndroid Build Coastguard Worker unsigned m;
356*f6dc9357SAndroid Build Coastguard Worker for (;;)
357*f6dc9357SAndroid Build Coastguard Worker {
358*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p == lim)
359*f6dc9357SAndroid Build Coastguard Worker return p;
360*f6dc9357SAndroid Build Coastguard Worker m = (unsigned)((UInt32)0x334b0000 >> (*p & 0x1e));
361*f6dc9357SAndroid Build Coastguard Worker p += 16;
362*f6dc9357SAndroid Build Coastguard Worker pc += 1 << 1;
363*f6dc9357SAndroid Build Coastguard Worker if (m &= 3)
364*f6dc9357SAndroid Build Coastguard Worker break;
365*f6dc9357SAndroid Build Coastguard Worker }
366*f6dc9357SAndroid Build Coastguard Worker {
367*f6dc9357SAndroid Build Coastguard Worker p += (ptrdiff_t)m * 5 - 20; // negative value is expected here.
368*f6dc9357SAndroid Build Coastguard Worker do
369*f6dc9357SAndroid Build Coastguard Worker {
370*f6dc9357SAndroid Build Coastguard Worker const UInt32 t =
371*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_X86_OR_AMD64)
372*f6dc9357SAndroid Build Coastguard Worker // we use 32-bit load here to reduce code size on x86:
373*f6dc9357SAndroid Build Coastguard Worker GetUi32(p);
374*f6dc9357SAndroid Build Coastguard Worker #else
375*f6dc9357SAndroid Build Coastguard Worker GetUi16(p);
376*f6dc9357SAndroid Build Coastguard Worker #endif
377*f6dc9357SAndroid Build Coastguard Worker UInt32 z = GetUi32(p + 1) >> m;
378*f6dc9357SAndroid Build Coastguard Worker p += 5;
379*f6dc9357SAndroid Build Coastguard Worker if (((t >> m) & (0x70 << 1)) == 0
380*f6dc9357SAndroid Build Coastguard Worker && ((z - (0x5000000 << 1)) & (0xf000000 << 1)) == 0)
381*f6dc9357SAndroid Build Coastguard Worker {
382*f6dc9357SAndroid Build Coastguard Worker UInt32 v = (UInt32)((0x8fffff << 1) | 1) & z;
383*f6dc9357SAndroid Build Coastguard Worker z ^= v;
384*f6dc9357SAndroid Build Coastguard Worker #ifdef BR_IA64_NO_INLINE
385*f6dc9357SAndroid Build Coastguard Worker v |= (v & ((UInt32)1 << (23 + 1))) >> 3;
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker UInt32 c = pc;
388*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL(v, c)
389*f6dc9357SAndroid Build Coastguard Worker }
390*f6dc9357SAndroid Build Coastguard Worker v &= (0x1fffff << 1) | 1;
391*f6dc9357SAndroid Build Coastguard Worker #else
392*f6dc9357SAndroid Build Coastguard Worker {
393*f6dc9357SAndroid Build Coastguard Worker if (encoding)
394*f6dc9357SAndroid Build Coastguard Worker {
395*f6dc9357SAndroid Build Coastguard Worker // pc &= ~(0xc00000 << 1); // we just need to clear at least 2 bits
396*f6dc9357SAndroid Build Coastguard Worker pc &= (0x1fffff << 1) | 1;
397*f6dc9357SAndroid Build Coastguard Worker v += pc;
398*f6dc9357SAndroid Build Coastguard Worker }
399*f6dc9357SAndroid Build Coastguard Worker else
400*f6dc9357SAndroid Build Coastguard Worker {
401*f6dc9357SAndroid Build Coastguard Worker // pc |= 0xc00000 << 1; // we need to set at least 2 bits
402*f6dc9357SAndroid Build Coastguard Worker pc |= ~(UInt32)((0x1fffff << 1) | 1);
403*f6dc9357SAndroid Build Coastguard Worker v -= pc;
404*f6dc9357SAndroid Build Coastguard Worker }
405*f6dc9357SAndroid Build Coastguard Worker }
406*f6dc9357SAndroid Build Coastguard Worker v &= ~(UInt32)(0x600000 << 1);
407*f6dc9357SAndroid Build Coastguard Worker #endif
408*f6dc9357SAndroid Build Coastguard Worker v += (0x700000 << 1);
409*f6dc9357SAndroid Build Coastguard Worker v &= (0x8fffff << 1) | 1;
410*f6dc9357SAndroid Build Coastguard Worker z |= v;
411*f6dc9357SAndroid Build Coastguard Worker z <<= m;
412*f6dc9357SAndroid Build Coastguard Worker SetUi32(p + 1 - 5, z)
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker m++;
415*f6dc9357SAndroid Build Coastguard Worker }
416*f6dc9357SAndroid Build Coastguard Worker while (m &= 3); // while (m < 4);
417*f6dc9357SAndroid Build Coastguard Worker }
418*f6dc9357SAndroid Build Coastguard Worker }
419*f6dc9357SAndroid Build Coastguard Worker }
Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)420*f6dc9357SAndroid Build Coastguard Worker Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)
421*f6dc9357SAndroid Build Coastguard Worker
422*f6dc9357SAndroid Build Coastguard Worker
423*f6dc9357SAndroid Build Coastguard Worker #define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET;
424*f6dc9357SAndroid Build Coastguard Worker #define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET;
425*f6dc9357SAndroid Build Coastguard Worker
426*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(MY_CPU_LE_UNALIGN)
427*f6dc9357SAndroid Build Coastguard Worker #define RISCV_USE_UNALIGNED_LOAD
428*f6dc9357SAndroid Build Coastguard Worker #endif
429*f6dc9357SAndroid Build Coastguard Worker
430*f6dc9357SAndroid Build Coastguard Worker #ifdef RISCV_USE_UNALIGNED_LOAD
431*f6dc9357SAndroid Build Coastguard Worker #define RISCV_GET_UI32(p) GetUi32(p)
432*f6dc9357SAndroid Build Coastguard Worker #define RISCV_SET_UI32(p, v) { SetUi32(p, v) }
433*f6dc9357SAndroid Build Coastguard Worker #else
434*f6dc9357SAndroid Build Coastguard Worker #define RISCV_GET_UI32(p) \
435*f6dc9357SAndroid Build Coastguard Worker ((UInt32)GetUi16a(p) + \
436*f6dc9357SAndroid Build Coastguard Worker ((UInt32)GetUi16a((p) + 2) << 16))
437*f6dc9357SAndroid Build Coastguard Worker #define RISCV_SET_UI32(p, v) { \
438*f6dc9357SAndroid Build Coastguard Worker SetUi16a(p, (UInt16)(v)) \
439*f6dc9357SAndroid Build Coastguard Worker SetUi16a((p) + 2, (UInt16)(v >> 16)) }
440*f6dc9357SAndroid Build Coastguard Worker #endif
441*f6dc9357SAndroid Build Coastguard Worker
442*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(MY_CPU_LE)
443*f6dc9357SAndroid Build Coastguard Worker #define RISCV_USE_16BIT_LOAD
444*f6dc9357SAndroid Build Coastguard Worker #endif
445*f6dc9357SAndroid Build Coastguard Worker
446*f6dc9357SAndroid Build Coastguard Worker #ifdef RISCV_USE_16BIT_LOAD
447*f6dc9357SAndroid Build Coastguard Worker #define RISCV_LOAD_VAL(p) GetUi16a(p)
448*f6dc9357SAndroid Build Coastguard Worker #else
449*f6dc9357SAndroid Build Coastguard Worker #define RISCV_LOAD_VAL(p) (*(p))
450*f6dc9357SAndroid Build Coastguard Worker #endif
451*f6dc9357SAndroid Build Coastguard Worker
452*f6dc9357SAndroid Build Coastguard Worker #define RISCV_INSTR_SIZE 2
453*f6dc9357SAndroid Build Coastguard Worker #define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE)
454*f6dc9357SAndroid Build Coastguard Worker #define RISCV_STEP_2 4
455*f6dc9357SAndroid Build Coastguard Worker #define RISCV_REG_VAL (2 << 7)
456*f6dc9357SAndroid Build Coastguard Worker #define RISCV_CMD_VAL 3
457*f6dc9357SAndroid Build Coastguard Worker #if 1
458*f6dc9357SAndroid Build Coastguard Worker // for code size optimization:
459*f6dc9357SAndroid Build Coastguard Worker #define RISCV_DELTA_7F 0x7f
460*f6dc9357SAndroid Build Coastguard Worker #else
461*f6dc9357SAndroid Build Coastguard Worker #define RISCV_DELTA_7F 0
462*f6dc9357SAndroid Build Coastguard Worker #endif
463*f6dc9357SAndroid Build Coastguard Worker
464*f6dc9357SAndroid Build Coastguard Worker #define RISCV_CHECK_1(v, b) \
465*f6dc9357SAndroid Build Coastguard Worker (((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)
466*f6dc9357SAndroid Build Coastguard Worker
467*f6dc9357SAndroid Build Coastguard Worker #if 1
468*f6dc9357SAndroid Build Coastguard Worker #define RISCV_CHECK_2(v, r) \
469*f6dc9357SAndroid Build Coastguard Worker ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \
470*f6dc9357SAndroid Build Coastguard Worker << 18) \
471*f6dc9357SAndroid Build Coastguard Worker < ((r) & 0x1d))
472*f6dc9357SAndroid Build Coastguard Worker #else
473*f6dc9357SAndroid Build Coastguard Worker // this branch gives larger code, because
474*f6dc9357SAndroid Build Coastguard Worker // compilers generate larger code for big constants.
475*f6dc9357SAndroid Build Coastguard Worker #define RISCV_CHECK_2(v, r) \
476*f6dc9357SAndroid Build Coastguard Worker ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
477*f6dc9357SAndroid Build Coastguard Worker & ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
478*f6dc9357SAndroid Build Coastguard Worker < ((r) & 0x1d))
479*f6dc9357SAndroid Build Coastguard Worker #endif
480*f6dc9357SAndroid Build Coastguard Worker
481*f6dc9357SAndroid Build Coastguard Worker
482*f6dc9357SAndroid Build Coastguard Worker #define RISCV_SCAN_LOOP \
483*f6dc9357SAndroid Build Coastguard Worker Byte *lim; \
484*f6dc9357SAndroid Build Coastguard Worker size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \
485*f6dc9357SAndroid Build Coastguard Worker if (size <= 6) return p; \
486*f6dc9357SAndroid Build Coastguard Worker size -= 6; \
487*f6dc9357SAndroid Build Coastguard Worker lim = p + size; \
488*f6dc9357SAndroid Build Coastguard Worker BR_PC_INIT \
489*f6dc9357SAndroid Build Coastguard Worker for (;;) \
490*f6dc9357SAndroid Build Coastguard Worker { \
491*f6dc9357SAndroid Build Coastguard Worker UInt32 a, v; \
492*f6dc9357SAndroid Build Coastguard Worker /* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \
493*f6dc9357SAndroid Build Coastguard Worker for (;;) \
494*f6dc9357SAndroid Build Coastguard Worker { \
495*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p >= lim) { return p; } \
496*f6dc9357SAndroid Build Coastguard Worker a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \
497*f6dc9357SAndroid Build Coastguard Worker if ((a & 0x77) == 0) break; \
498*f6dc9357SAndroid Build Coastguard Worker a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \
499*f6dc9357SAndroid Build Coastguard Worker p += RISCV_INSTR_SIZE * 2; \
500*f6dc9357SAndroid Build Coastguard Worker if ((a & 0x77) == 0) \
501*f6dc9357SAndroid Build Coastguard Worker { \
502*f6dc9357SAndroid Build Coastguard Worker p -= RISCV_INSTR_SIZE; \
503*f6dc9357SAndroid Build Coastguard Worker if Z7_UNLIKELY(p >= lim) { return p; } \
504*f6dc9357SAndroid Build Coastguard Worker break; \
505*f6dc9357SAndroid Build Coastguard Worker } \
506*f6dc9357SAndroid Build Coastguard Worker }
507*f6dc9357SAndroid Build Coastguard Worker // (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL
508*f6dc9357SAndroid Build Coastguard Worker // (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL
509*f6dc9357SAndroid Build Coastguard Worker // (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC
510*f6dc9357SAndroid Build Coastguard Worker // (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC
511*f6dc9357SAndroid Build Coastguard Worker
512*f6dc9357SAndroid Build Coastguard Worker Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker RISCV_SCAN_LOOP
515*f6dc9357SAndroid Build Coastguard Worker v = a;
516*f6dc9357SAndroid Build Coastguard Worker a = RISCV_GET_UI32(p);
517*f6dc9357SAndroid Build Coastguard Worker #ifndef RISCV_USE_16BIT_LOAD
518*f6dc9357SAndroid Build Coastguard Worker v += (UInt32)p[1] << 8;
519*f6dc9357SAndroid Build Coastguard Worker #endif
520*f6dc9357SAndroid Build Coastguard Worker
521*f6dc9357SAndroid Build Coastguard Worker if ((v & 8) == 0) // JAL
522*f6dc9357SAndroid Build Coastguard Worker {
523*f6dc9357SAndroid Build Coastguard Worker if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)
524*f6dc9357SAndroid Build Coastguard Worker {
525*f6dc9357SAndroid Build Coastguard Worker p += RISCV_INSTR_SIZE;
526*f6dc9357SAndroid Build Coastguard Worker continue;
527*f6dc9357SAndroid Build Coastguard Worker }
528*f6dc9357SAndroid Build Coastguard Worker {
529*f6dc9357SAndroid Build Coastguard Worker v = ((a & 1u << 31) >> 11)
530*f6dc9357SAndroid Build Coastguard Worker | ((a & 0x3ff << 21) >> 20)
531*f6dc9357SAndroid Build Coastguard Worker | ((a & 1 << 20) >> 9)
532*f6dc9357SAndroid Build Coastguard Worker | (a & 0xff << 12);
533*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL_ENC(v)
534*f6dc9357SAndroid Build Coastguard Worker // ((v & 1) == 0)
535*f6dc9357SAndroid Build Coastguard Worker // v: bits [1 : 20] contain offset bits
536*f6dc9357SAndroid Build Coastguard Worker #if 0 && defined(RISCV_USE_UNALIGNED_LOAD)
537*f6dc9357SAndroid Build Coastguard Worker a &= 0xfff;
538*f6dc9357SAndroid Build Coastguard Worker a |= ((UInt32)(v << 23))
539*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)(v << 7) & ((UInt32)0xff << 16))
540*f6dc9357SAndroid Build Coastguard Worker | ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8));
541*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p, a)
542*f6dc9357SAndroid Build Coastguard Worker #else // aligned
543*f6dc9357SAndroid Build Coastguard Worker #if 0
544*f6dc9357SAndroid Build Coastguard Worker SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))
545*f6dc9357SAndroid Build Coastguard Worker #else
546*f6dc9357SAndroid Build Coastguard Worker p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));
547*f6dc9357SAndroid Build Coastguard Worker #endif
548*f6dc9357SAndroid Build Coastguard Worker
549*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
550*f6dc9357SAndroid Build Coastguard Worker v <<= 15;
551*f6dc9357SAndroid Build Coastguard Worker v = Z7_BSWAP32(v);
552*f6dc9357SAndroid Build Coastguard Worker SetUi16a(p + 2, (UInt16)v)
553*f6dc9357SAndroid Build Coastguard Worker #else
554*f6dc9357SAndroid Build Coastguard Worker p[2] = (Byte)(v >> 9);
555*f6dc9357SAndroid Build Coastguard Worker p[3] = (Byte)(v >> 1);
556*f6dc9357SAndroid Build Coastguard Worker #endif
557*f6dc9357SAndroid Build Coastguard Worker #endif // aligned
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker p += 4;
560*f6dc9357SAndroid Build Coastguard Worker continue;
561*f6dc9357SAndroid Build Coastguard Worker } // JAL
562*f6dc9357SAndroid Build Coastguard Worker
563*f6dc9357SAndroid Build Coastguard Worker {
564*f6dc9357SAndroid Build Coastguard Worker // AUIPC
565*f6dc9357SAndroid Build Coastguard Worker if (v & 0xe80) // (not x0) and (not x2)
566*f6dc9357SAndroid Build Coastguard Worker {
567*f6dc9357SAndroid Build Coastguard Worker const UInt32 b = RISCV_GET_UI32(p + 4);
568*f6dc9357SAndroid Build Coastguard Worker if (RISCV_CHECK_1(v, b))
569*f6dc9357SAndroid Build Coastguard Worker {
570*f6dc9357SAndroid Build Coastguard Worker {
571*f6dc9357SAndroid Build Coastguard Worker const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);
572*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p, temp)
573*f6dc9357SAndroid Build Coastguard Worker }
574*f6dc9357SAndroid Build Coastguard Worker a &= 0xfffff000;
575*f6dc9357SAndroid Build Coastguard Worker {
576*f6dc9357SAndroid Build Coastguard Worker #if 1
577*f6dc9357SAndroid Build Coastguard Worker const int t = -1 >> 1;
578*f6dc9357SAndroid Build Coastguard Worker if (t != -1)
579*f6dc9357SAndroid Build Coastguard Worker a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation
580*f6dc9357SAndroid Build Coastguard Worker else
581*f6dc9357SAndroid Build Coastguard Worker #endif
582*f6dc9357SAndroid Build Coastguard Worker a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).
583*f6dc9357SAndroid Build Coastguard Worker }
584*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL_ENC(a)
585*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
586*f6dc9357SAndroid Build Coastguard Worker a = Z7_BSWAP32(a);
587*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p + 4, a)
588*f6dc9357SAndroid Build Coastguard Worker #else
589*f6dc9357SAndroid Build Coastguard Worker SetBe32(p + 4, a)
590*f6dc9357SAndroid Build Coastguard Worker #endif
591*f6dc9357SAndroid Build Coastguard Worker p += 8;
592*f6dc9357SAndroid Build Coastguard Worker }
593*f6dc9357SAndroid Build Coastguard Worker else
594*f6dc9357SAndroid Build Coastguard Worker p += RISCV_STEP_1;
595*f6dc9357SAndroid Build Coastguard Worker }
596*f6dc9357SAndroid Build Coastguard Worker else
597*f6dc9357SAndroid Build Coastguard Worker {
598*f6dc9357SAndroid Build Coastguard Worker UInt32 r = a >> 27;
599*f6dc9357SAndroid Build Coastguard Worker if (RISCV_CHECK_2(v, r))
600*f6dc9357SAndroid Build Coastguard Worker {
601*f6dc9357SAndroid Build Coastguard Worker v = RISCV_GET_UI32(p + 4);
602*f6dc9357SAndroid Build Coastguard Worker r = (r << 7) + 0x17 + (v & 0xfffff000);
603*f6dc9357SAndroid Build Coastguard Worker a = (a >> 12) | (v << 20);
604*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p, r)
605*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p + 4, a)
606*f6dc9357SAndroid Build Coastguard Worker p += 8;
607*f6dc9357SAndroid Build Coastguard Worker }
608*f6dc9357SAndroid Build Coastguard Worker else
609*f6dc9357SAndroid Build Coastguard Worker p += RISCV_STEP_2;
610*f6dc9357SAndroid Build Coastguard Worker }
611*f6dc9357SAndroid Build Coastguard Worker }
612*f6dc9357SAndroid Build Coastguard Worker } // for
613*f6dc9357SAndroid Build Coastguard Worker }
614*f6dc9357SAndroid Build Coastguard Worker
615*f6dc9357SAndroid Build Coastguard Worker
616*f6dc9357SAndroid Build Coastguard Worker Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)
617*f6dc9357SAndroid Build Coastguard Worker {
618*f6dc9357SAndroid Build Coastguard Worker RISCV_SCAN_LOOP
619*f6dc9357SAndroid Build Coastguard Worker #ifdef RISCV_USE_16BIT_LOAD
620*f6dc9357SAndroid Build Coastguard Worker if ((a & 8) == 0)
621*f6dc9357SAndroid Build Coastguard Worker {
622*f6dc9357SAndroid Build Coastguard Worker #else
623*f6dc9357SAndroid Build Coastguard Worker v = a;
624*f6dc9357SAndroid Build Coastguard Worker a += (UInt32)p[1] << 8;
625*f6dc9357SAndroid Build Coastguard Worker if ((v & 8) == 0)
626*f6dc9357SAndroid Build Coastguard Worker {
627*f6dc9357SAndroid Build Coastguard Worker #endif
628*f6dc9357SAndroid Build Coastguard Worker // JAL
629*f6dc9357SAndroid Build Coastguard Worker a -= 0x100 - RISCV_DELTA_7F;
630*f6dc9357SAndroid Build Coastguard Worker if (a & 0xd80)
631*f6dc9357SAndroid Build Coastguard Worker {
632*f6dc9357SAndroid Build Coastguard Worker p += RISCV_INSTR_SIZE;
633*f6dc9357SAndroid Build Coastguard Worker continue;
634*f6dc9357SAndroid Build Coastguard Worker }
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;
637*f6dc9357SAndroid Build Coastguard Worker #if 0 // unaligned
638*f6dc9357SAndroid Build Coastguard Worker a = GetUi32(p);
639*f6dc9357SAndroid Build Coastguard Worker v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)
640*f6dc9357SAndroid Build Coastguard Worker | (UInt32)(a >> 7) & ((UInt32)0xff << 9)
641*f6dc9357SAndroid Build Coastguard Worker #elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
642*f6dc9357SAndroid Build Coastguard Worker v = GetUi16a(p + 2);
643*f6dc9357SAndroid Build Coastguard Worker v = Z7_BSWAP32(v) >> 15
644*f6dc9357SAndroid Build Coastguard Worker #else
645*f6dc9357SAndroid Build Coastguard Worker v = (UInt32)p[3] << 1
646*f6dc9357SAndroid Build Coastguard Worker | (UInt32)p[2] << 9
647*f6dc9357SAndroid Build Coastguard Worker #endif
648*f6dc9357SAndroid Build Coastguard Worker | (UInt32)((a & 0xf000) << 5);
649*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL_DEC(v)
650*f6dc9357SAndroid Build Coastguard Worker a = a_old
651*f6dc9357SAndroid Build Coastguard Worker | (v << 11 & 1u << 31)
652*f6dc9357SAndroid Build Coastguard Worker | (v << 20 & 0x3ff << 21)
653*f6dc9357SAndroid Build Coastguard Worker | (v << 9 & 1 << 20)
654*f6dc9357SAndroid Build Coastguard Worker | (v & 0xff << 12);
655*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p, a)
656*f6dc9357SAndroid Build Coastguard Worker }
657*f6dc9357SAndroid Build Coastguard Worker p += 4;
658*f6dc9357SAndroid Build Coastguard Worker continue;
659*f6dc9357SAndroid Build Coastguard Worker } // JAL
660*f6dc9357SAndroid Build Coastguard Worker
661*f6dc9357SAndroid Build Coastguard Worker {
662*f6dc9357SAndroid Build Coastguard Worker // AUIPC
663*f6dc9357SAndroid Build Coastguard Worker v = a;
664*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(RISCV_USE_UNALIGNED_LOAD)
665*f6dc9357SAndroid Build Coastguard Worker a = GetUi32(p);
666*f6dc9357SAndroid Build Coastguard Worker #else
667*f6dc9357SAndroid Build Coastguard Worker a |= (UInt32)GetUi16a(p + 2) << 16;
668*f6dc9357SAndroid Build Coastguard Worker #endif
669*f6dc9357SAndroid Build Coastguard Worker if ((v & 0xe80) == 0) // x0/x2
670*f6dc9357SAndroid Build Coastguard Worker {
671*f6dc9357SAndroid Build Coastguard Worker const UInt32 r = a >> 27;
672*f6dc9357SAndroid Build Coastguard Worker if (RISCV_CHECK_2(v, r))
673*f6dc9357SAndroid Build Coastguard Worker {
674*f6dc9357SAndroid Build Coastguard Worker UInt32 b;
675*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
676*f6dc9357SAndroid Build Coastguard Worker b = RISCV_GET_UI32(p + 4);
677*f6dc9357SAndroid Build Coastguard Worker b = Z7_BSWAP32(b);
678*f6dc9357SAndroid Build Coastguard Worker #else
679*f6dc9357SAndroid Build Coastguard Worker b = GetBe32(p + 4);
680*f6dc9357SAndroid Build Coastguard Worker #endif
681*f6dc9357SAndroid Build Coastguard Worker v = a >> 12;
682*f6dc9357SAndroid Build Coastguard Worker BR_CONVERT_VAL_DEC(b)
683*f6dc9357SAndroid Build Coastguard Worker a = (r << 7) + 0x17;
684*f6dc9357SAndroid Build Coastguard Worker a += (b + 0x800) & 0xfffff000;
685*f6dc9357SAndroid Build Coastguard Worker v |= b << 20;
686*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p, a)
687*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p + 4, v)
688*f6dc9357SAndroid Build Coastguard Worker p += 8;
689*f6dc9357SAndroid Build Coastguard Worker }
690*f6dc9357SAndroid Build Coastguard Worker else
691*f6dc9357SAndroid Build Coastguard Worker p += RISCV_STEP_2;
692*f6dc9357SAndroid Build Coastguard Worker }
693*f6dc9357SAndroid Build Coastguard Worker else
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker const UInt32 b = RISCV_GET_UI32(p + 4);
696*f6dc9357SAndroid Build Coastguard Worker if (!RISCV_CHECK_1(v, b))
697*f6dc9357SAndroid Build Coastguard Worker p += RISCV_STEP_1;
698*f6dc9357SAndroid Build Coastguard Worker else
699*f6dc9357SAndroid Build Coastguard Worker {
700*f6dc9357SAndroid Build Coastguard Worker v = (a & 0xfffff000) | (b >> 20);
701*f6dc9357SAndroid Build Coastguard Worker a = (b << 12) | (0x17 + RISCV_REG_VAL);
702*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p, a)
703*f6dc9357SAndroid Build Coastguard Worker RISCV_SET_UI32(p + 4, v)
704*f6dc9357SAndroid Build Coastguard Worker p += 8;
705*f6dc9357SAndroid Build Coastguard Worker }
706*f6dc9357SAndroid Build Coastguard Worker }
707*f6dc9357SAndroid Build Coastguard Worker }
708*f6dc9357SAndroid Build Coastguard Worker } // for
709*f6dc9357SAndroid Build Coastguard Worker }
710