2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
23 #define S390_BCR 0x070000000000ULL
24 #define S390_BASR 0x0d0000000000ULL
26 #define S390_LTR 0x120000000000ULL
27 #define S390_LTGR 0xb90200000000ULL
29 #define S390_LCR 0x130000000000ULL
30 #define S390_LCGR 0xb90300000000ULL
32 #define S390_NR 0x140000000000ULL
33 #define S390_NRK 0xb9f400000000ULL
34 #define S390_N 0x540000000000ULL
35 #define S390_NY 0xe30000000054ULL
36 #define S390_NGR 0xb98000000000ULL
37 #define S390_NGRK 0xb9e400000000ULL
38 #define S390_NG 0xe30000000080ULL
39 #define S390_NILL 0xa50700000000ULL
40 #define S390_NILH 0xa50600000000ULL
41 #define S390_NIHL 0xa50500000000ULL
42 #define S390_NIHH 0xa50400000000ULL
43 #define S390_NILF 0xc00b00000000ULL
44 #define S390_NIHF 0xc00a00000000ULL
46 #define S390_CLR 0x150000000000ULL
47 #define S390_CL 0x550000000000ULL
48 #define S390_CLY 0xe30000000055ULL
49 #define S390_CLGR 0xb92100000000ULL
50 #define S390_CLG 0xe30000000021ULL
52 #define S390_OR 0x160000000000ULL
53 #define S390_ORK 0xb9f600000000ULL
54 #define S390_O 0x560000000000ULL
55 #define S390_OY 0xe30000000056ULL
56 #define S390_OGR 0xb98100000000ULL
57 #define S390_OGRK 0xb9e600000000ULL
58 #define S390_OG 0xe30000000081ULL
59 #define S390_OILL 0xa50b00000000ULL
60 #define S390_OILH 0xa50a00000000ULL
61 #define S390_OIHL 0xa50900000000ULL
62 #define S390_OIHH 0xa50800000000ULL
63 #define S390_OILF 0xc00d00000000ULL
64 #define S390_OIHF 0xc00c00000000ULL
66 #define S390_XR 0x170000000000ULL
67 #define S390_XRK 0xb9f700000000ULL
68 #define S390_X 0x570000000000ULL
69 #define S390_XY 0xe30000000057ULL
70 #define S390_XGR 0xb98200000000ULL
71 #define S390_XGRK 0xb9e700000000ULL
72 #define S390_XG 0xe30000000082ULL
73 #define S390_XILF 0xc00700000000ULL
74 #define S390_XIHF 0xc00600000000ULL
76 #define S390_LR 0x180000000000ULL
77 #define S390_L 0x580000000000ULL
78 #define S390_LY 0xe30000000058ULL
79 #define S390_LGR 0xb90400000000ULL
80 #define S390_LG 0xe30000000004ULL
81 #define S390_LHI 0xa70800000000ULL
82 #define S390_LGHI 0xa70900000000ULL
83 #define S390_LGFI 0xc00100000000ULL
84 #define S390_LGFR 0xb91400000000ULL
85 #define S390_LLGCR 0xb98400000000ULL
86 #define S390_LLGC 0xe30000000090ULL
87 #define S390_LLGHR 0xb98500000000ULL
88 #define S390_LLGH 0xe30000000091ULL
89 #define S390_LLGFR 0xb91600000000ULL
90 #define S390_LBR 0xb92600000000ULL
91 #define S390_LB 0xe30000000076ULL
92 #define S390_LGBR 0xb90600000000ULL
93 #define S390_LGB 0xe30000000077ULL
95 #define S390_CR 0x190000000000ULL
96 #define S390_C 0x590000000000ULL
97 #define S390_CY 0xe30000000059ULL
98 #define S390_CGR 0xb92000000000ULL
99 #define S390_CG 0xe30000000020ULL
100 #define S390_CHI 0xa70e00000000ULL
101 #define S390_CGHI 0xa70f00000000ULL
103 #define S390_AR 0x1a0000000000ULL
104 #define S390_ARK 0xb9f800000000ULL
105 #define S390_A 0x5a0000000000ULL
106 #define S390_AY 0xe3000000005aULL
107 #define S390_AGR 0xb90800000000ULL
108 #define S390_AGRK 0xb9e800000000ULL
109 #define S390_AG 0xe30000000008ULL
110 #define S390_AHI 0xa70a00000000ULL
111 #define S390_AGHI 0xa70b00000000ULL
112 #define S390_AGF 0xe30000000018ULL
114 #define S390_SR 0x1b0000000000ULL
115 #define S390_SRK 0xb9f900000000ULL
116 #define S390_S 0x5b0000000000ULL
117 #define S390_SY 0xe3000000005bULL
118 #define S390_SGR 0xb90900000000ULL
119 #define S390_SGRK 0xb9e900000000ULL
120 #define S390_SG 0xe30000000009ULL
122 #define S390_MR 0x1c0000000000ULL
123 #define S390_M 0x5c0000000000ULL
124 #define S390_MFY 0xe3000000005cULL
125 #define S390_MGRK 0xb9ec00000000ULL
126 #define S390_MG 0xe30000000084ULL
127 #define S390_MSR 0xb25200000000ULL
128 #define S390_MS 0x710000000000ULL
129 #define S390_MSY 0xe30000000051ULL
130 #define S390_MSRKC 0xb9fd00000000ULL
131 #define S390_MSC 0xe30000000053ULL
132 #define S390_MSGR 0xb90c00000000ULL
133 #define S390_MSGRKC 0xb9ed00000000ULL
134 #define S390_MSG 0xe3000000000cULL
135 #define S390_MSGC 0xe30000000083ULL
137 #define S390_DR 0x1d0000000000ULL
138 #define S390_DLR 0xb99700000000ULL
139 #define S390_DLGR 0xb98700000000ULL
140 #define S390_DSGR 0xb90d00000000ULL
142 #define S390_ALR 0x1e0000000000ULL
143 #define S390_ALRK 0xb9fa00000000ULL
144 #define S390_AL 0x5e0000000000ULL
145 #define S390_ALY 0xe3000000005eULL
146 #define S390_ALGR 0xb90a00000000ULL
147 #define S390_ALGRK 0xb9ea00000000ULL
148 #define S390_ALG 0xe3000000000aULL
150 #define S390_SLR 0x1f0000000000ULL
151 #define S390_SLRK 0xb9fb00000000ULL
152 #define S390_SL 0x5f0000000000ULL
153 #define S390_SLY 0xe3000000005fULL
154 #define S390_SLGR 0xb90b00000000ULL
155 #define S390_SLGRK 0xb9eb00000000ULL
156 #define S390_SLG 0xe3000000000bULL
158 #define S390_LER 0x380000000000ULL
159 #define S390_LDR 0x280000000000ULL
160 #define S390_LXR 0xb36500000000ULL
161 #define S390_LE 0x780000000000ULL
162 #define S390_LEY 0xed0000000064ULL
163 #define S390_LD 0x680000000000ULL
164 #define S390_LDY 0xed0000000065ULL
166 #define S390_STE 0x700000000000ULL
167 #define S390_STEY 0xed0000000066ULL
168 #define S390_STD 0x600000000000ULL
169 #define S390_STDY 0xed0000000067ULL
171 #define S390_LA 0x410000000000ULL
172 #define S390_LAY 0xe30000000071ULL
174 #define S390_STC 0x420000000000ULL
175 #define S390_STCY 0xe30000000072ULL
176 #define S390_STH 0x400000000000ULL
177 #define S390_STHY 0xe30000000070ULL
178 #define S390_ST 0x500000000000ULL
179 #define S390_STY 0xe30000000050ULL
180 #define S390_STG 0xe30000000024ULL
182 #define S390_IC 0x430000000000ULL
183 #define S390_ICY 0xe30000000073ULL
185 #define S390_LCEBR 0xb30300000000ULL
186 #define S390_LCDBR 0xb31300000000ULL
187 #define S390_LCXBR 0xb34300000000ULL
189 #define S390_CEBR 0xb30900000000ULL
190 #define S390_CDBR 0xb31900000000ULL
191 #define S390_CXBR 0xb34900000000ULL
192 #define S390_CEB 0xed0000000009ULL
193 #define S390_CDB 0xed0000000019ULL
195 #define S390_AEBR 0xb30a00000000ULL
196 #define S390_ADBR 0xb31a00000000ULL
197 #define S390_AXBR 0xb34a00000000ULL
198 #define S390_AEB 0xed000000000aULL
199 #define S390_ADB 0xed000000001aULL
201 #define S390_SEBR 0xb30b00000000ULL
202 #define S390_SDBR 0xb31b00000000ULL
203 #define S390_SXBR 0xb34b00000000ULL
204 #define S390_SEB 0xed000000000bULL
205 #define S390_SDB 0xed000000001bULL
207 #define S390_DEBR 0xb30d00000000ULL
208 #define S390_DDBR 0xb31d00000000ULL
209 #define S390_DXBR 0xb34d00000000ULL
210 #define S390_DEB 0xed000000000dULL
211 #define S390_DDB 0xed000000001dULL
213 #define S390_SQEBR 0xb31400000000ULL
214 #define S390_SQDBR 0xb31500000000ULL
215 #define S390_SQXBR 0xb31600000000ULL
216 #define S390_SQEB 0xed0000000014ULL
217 #define S390_SQDB 0xed0000000015ULL
219 #define S390_MEEBR 0xb31700000000ULL
220 #define S390_MDBR 0xb31c00000000ULL
221 #define S390_MXBR 0xb34c00000000ULL
222 #define S390_MEEB 0xed0000000017ULL
223 #define S390_MDB 0xed000000001cULL
225 #define S390_FIEBR 0xb35700000000ULL
226 #define S390_FIDBR 0xb35f00000000ULL
227 #define S390_FIXBR 0xb34700000000ULL
228 #define S390_FI_ROUND 0x000040000000ULL
229 #define S390_FI_TRUNC 0x000050000000ULL
230 #define S390_FI_CEIL 0x000060000000ULL
231 #define S390_FI_FLOOR 0x000070000000ULL
233 #define S390_CEFBR 0xb39400000000ULL
234 #define S390_CDFBR 0xb39500000000ULL
235 #define S390_CXFBR 0xb39600000000ULL
236 #define S390_CEGBR 0xb3a400000000ULL
237 #define S390_CDGBR 0xb3a500000000ULL
238 #define S390_CXGBR 0xb3a600000000ULL
240 #define S390_CFEBR 0xb39800000000ULL
241 #define S390_CFDBR 0xb39900000000ULL
242 #define S390_CFXBR 0xb39a00000000ULL
243 #define S390_CGEBR 0xb3a800000000ULL
244 #define S390_CGDBR 0xb3a900000000ULL
245 #define S390_CGXBR 0xb3aa00000000ULL
247 #define S390_LHR 0xb92700000000ULL
248 #define S390_LH 0x480000000000ULL
249 #define S390_LHY 0xe30000000078ULL
250 #define S390_LGHR 0xb90700000000ULL
251 #define S390_LGH 0xe30000000015ULL
252 #define S390_LGF 0xe30000000014ULL
253 #define S390_LLGF 0xe30000000016ULL
255 #define S390_RLL 0xeb000000001dULL
256 #define S390_RLLG 0xeb000000001cULL
257 #define S390_SRL 0x880000000000ULL
258 #define S390_SRLK 0xeb00000000deULL
259 #define S390_SRLG 0xeb000000000cULL
260 #define S390_SLL 0x890000000000ULL
261 #define S390_SLLK 0xeb00000000dfULL
262 #define S390_SLLG 0xeb000000000dULL
263 #define S390_SRA 0x8a0000000000ULL
264 #define S390_SRAK 0xeb00000000dcULL
265 #define S390_SRAG 0xeb000000000aULL
266 #define S390_SLA 0x8b0000000000ULL
267 #define S390_SLAK 0xeb00000000ddULL
268 #define S390_SLAG 0xeb000000000bULL
270 #define S390_STM 0x900000000000ULL
271 #define S390_STMY 0xeb0000000090ULL
272 #define S390_STMG 0xeb0000000024ULL
273 #define S390_LM 0x980000000000ULL
274 #define S390_LMY 0xeb0000000098ULL
275 #define S390_LMG 0xeb0000000004ULL
277 #define S390_MVI 0x920000000000ULL
278 #define S390_MVIY 0xeb0000000052ULL
279 #define S390_CLI 0x950000000000ULL
280 #define S390_CLIY 0xeb0000000055ULL
282 #define S390_TMLL 0xa70100000000ULL
283 #define S390_TMLH 0xa70000000000ULL
284 #define S390_TMHL 0xa70300000000ULL
285 #define S390_TMHH 0xa70200000000ULL
287 #define S390_BRC 0xa70400000000ULL
288 #define S390_BRAS 0xa70500000000ULL
289 #define S390_LRVR 0xb91f00000000ULL
290 #define S390_LRVRG 0xb90f00000000ULL
291 #define S390_POPCNT 0xb9e180000000ULL
292 #define S390_LOCR 0xb9f200000000ULL
293 #define S390_LOCGR 0xb9e200000000ULL
294 #define S390_NCRK 0xb9f500000000ULL
295 #define S390_NCGRK 0xb9e500000000ULL
296 #define S390_LOC 0xeb00000000f2ULL
297 #define S390_LOCG 0xeb00000000e2ULL
298 #define S390_BRCL 0xc00400000000ULL
299 #define S390_BRC_OVF 0x1ULL
300 #define S390_BRC_GREATER 0x2ULL
301 #define S390_BRC_LESS 0x4ULL
302 #define S390_BRC_EQ 0x8ULL
304 #define S390_IIHF 0xc00800000000ULL
305 #define S390_IILF 0xc00900000000ULL
307 #define S390_MVC 0xd20000000000ULL
329 static const struct codes codes_cmp = { S390_CR, -1, S390_C, S390_CY, S390_CGR, -1, S390_CG, S390_CHI, S390_CGHI, -1, -1, -1, -1, -1, -1, -1, 0 };
330 static const struct codes codes_cmp_log = { S390_CLR, -1, S390_CL, S390_CLY, S390_CLGR, -1, S390_CLG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
331 static const struct codes codes_ic = { -1, -1, S390_IC, S390_ICY, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
332 static const struct codes codes_load_8 = { S390_LBR, -1, -1, S390_LB, S390_LGBR, -1, S390_LGB, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
333 static const struct codes codes_load_16 = { -1, -1, S390_LH, S390_LHY, S390_LGHR, -1, S390_LGH, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
334 static const struct codes codes_load_32 = { -1, -1, -1, -1, S390_LGFR, -1, S390_LGF, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
335 static const struct codes codes_load_8_unsigned = { -1, -1, -1, -1, S390_LLGCR, -1, S390_LLGC, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
336 static const struct codes codes_load_16_unsigned = { -1, -1, -1, -1, S390_LLGHR, -1, S390_LLGH, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
337 static const struct codes codes_load_32_unsigned = { -1, -1, -1, -1, S390_LLGFR, -1, S390_LLGF, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
338 static const struct codes codes_load = { S390_LR, -1, S390_L, S390_LY, S390_LGR, -1, S390_LG, S390_LHI, S390_LGHI, S390_LGFI, -1, -1, -1, -1, -1, -1, 0 };
339 static const struct codes codes_store_8 = { -1, -1, S390_STC, S390_STCY, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
340 static const struct codes codes_store_16 = { -1, -1, S390_STH, S390_STHY, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
341 static const struct codes codes_store = { -1, -1, S390_ST, S390_STY, -1, -1, S390_STG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 };
343 static const struct codes codes_alu_no_flags[] = {
344 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
345 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
346 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
347 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
348 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
349 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
350 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
351 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
352 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
353 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
354 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
355 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
356 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
357 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
358 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
359 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
360 { S390_MSR, -1, S390_MS, S390_MSY, S390_MSGR, -1, S390_MSG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
363 static const struct codes codes_alu[] = {
364 { S390_AR, S390_ARK, S390_A, S390_AY, S390_AGR, S390_AGRK, S390_AG, S390_AHI, S390_AGHI, -1, -1, -1, -1, -1, -1, -1, 0 },
365 { S390_OR, S390_ORK, S390_O, S390_OY, S390_OGR, S390_OGRK, S390_OG, -1, -1, -1, S390_OILL, S390_OILH, S390_OIHL, S390_OIHH, S390_OILF, S390_OIHF, 0 },
366 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
367 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
368 { S390_NR, S390_NRK, S390_N, S390_NY, S390_NGR, S390_NGRK, S390_NG, -1, -1, -1, S390_NILL, S390_NILH, S390_NIHL, S390_NIHH, S390_NILF, S390_NIHF, 2 },
369 { S390_SR, S390_SRK, S390_S, S390_SY, S390_SGR, S390_SGRK, S390_SG, S390_AHI, S390_AGHI, -1, -1, -1, -1, -1, -1, -1, 1 },
370 { S390_XR, S390_XRK, S390_X, S390_XY, S390_XGR, S390_XGRK, S390_XG, -1, -1, -1, -1, -1, -1, -1, S390_XILF, S390_XIHF, 0 },
371 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
372 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
373 { -1, S390_NCRK, -1, -1, -1, S390_NCGRK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
374 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
375 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
376 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
377 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
378 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
379 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
380 { -1, S390_MSRKC, -1, S390_MSC, -1, S390_MSGRKC, S390_MSGC, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
383 static const struct codes codes_alu_log[] = {
384 { S390_ALR, S390_ALRK, S390_AL, S390_ALY, S390_ALGR, S390_ALGRK, S390_ALG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
385 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
386 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
387 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
388 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
389 { S390_SLR, S390_SLRK, S390_SL, S390_SLY, S390_SLGR, S390_SLGRK, S390_SLG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
392 static const it rot32[9] = {
393 S390_RLL, -1, -1, -1,
394 S390_SLL, S390_SRL, -1, S390_SRA,
398 static const it rot32k[9] = {
399 S390_RLL, -1, -1, -1,
400 S390_SLLK, S390_SRLK, -1, S390_SRAK,
404 static const it rot64[9] = {
405 S390_RLLG, -1, -1, -1,
406 S390_SLLG, S390_SRLG, -1, S390_SRAG,
410 static const int8_t jmp_cond[0x30] = {
411 S390_BRC_OVF, S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ,
413 S390_BRC_EQ, S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_OVF,
417 S390_BRC_LESS, S390_BRC_GREATER | S390_BRC_EQ,
418 S390_BRC_LESS | S390_BRC_EQ, S390_BRC_GREATER,
421 S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ, -1,
430 S390_BRC_LESS, S390_BRC_GREATER | S390_BRC_EQ,
431 S390_BRC_EQ, S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_OVF,
432 S390_BRC_LESS | S390_BRC_EQ, S390_BRC_GREATER,
434 S390_BRC_OVF, S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ,
439 static const int8_t jmp_cond_logical[0x8] = {
441 S390_BRC_LESS, S390_BRC_GREATER | S390_BRC_EQ,
442 S390_BRC_EQ, S390_BRC_GREATER | S390_BRC_LESS,
443 S390_BRC_LESS | S390_BRC_EQ, S390_BRC_GREATER,
454 static const struct fp_alu fp_alus[4] = {
455 { S390_AEBR, S390_ADBR, S390_AXBR, S390_AEB, S390_ADB },
456 { S390_SEBR, S390_SDBR, S390_SXBR, S390_SEB, S390_SDB },
457 { S390_MEEBR, S390_MDBR, S390_MXBR, S390_MEEB, S390_MDB },
458 { S390_DEBR, S390_DDBR, S390_DXBR, S390_DEB, S390_DDB },
461 static const struct fp_alu fp_alu1s[6] = {
462 { S390_LCEBR, S390_LCDBR, S390_LCXBR, -1, -1 },
463 { S390_SQEBR, S390_SQDBR, S390_SQXBR, S390_SQEB, S390_SQDB },
464 { S390_FIEBR | S390_FI_ROUND, S390_FIDBR | S390_FI_ROUND, S390_FIXBR | S390_FI_ROUND, -1, -1 },
465 { S390_FIEBR | S390_FI_FLOOR, S390_FIDBR | S390_FI_FLOOR, S390_FIXBR | S390_FI_FLOOR, -1, -1 },
466 { S390_FIEBR | S390_FI_CEIL, S390_FIDBR | S390_FI_CEIL, S390_FIXBR | S390_FI_CEIL, -1, -1 },
467 { S390_FIEBR | S390_FI_TRUNC, S390_FIDBR | S390_FI_TRUNC, S390_FIXBR | S390_FI_TRUNC, -1, -1 },
470 static const struct fp_alu fp_mov = {
471 S390_LER, S390_LDR, S390_LXR, -1, -1
474 static const struct fp_alu fp_cmp = {
475 S390_CEBR, S390_CDBR, S390_CXBR, S390_CEB, S390_CDB
478 static uint8_t get_jmp_cond(unsigned cond, bool logical)
482 if (unlikely(cond >= n_array_elements(jmp_cond)))
486 if (unlikely(cond >= n_array_elements(jmp_cond_logical)))
488 c = jmp_cond_logical[cond];
490 if (unlikely(c == -1))
494 internal(file_line, "get_jmp_cond: invalid %scondition %x", logical ? "logical " : "", cond);
497 static bool attr_w cgen_s390(struct codegen_context *ctx, it code)
499 unsigned sz = code >> 46;
501 if (unlikely((uint32_t)code))
503 cgen_two(code >> 32);
504 } else if (sz == 1 || sz == 2) {
505 if (unlikely((uint16_t)code))
507 cgen_four(code >> 16);
508 } else if (sz == 3) {
509 cgen_two(code >> 32);
513 internal(file_line, "cgen_s390: invalid insn %"PRIxMAX"", (uintmax_t)code);
518 static bool attr_w cgen_rr_rx(struct codegen_context *ctx, unsigned size, uint8_t *arg1, uint8_t *arg2, uint8_t *arg3, const struct codes *codes)
524 if (size > OP_SIZE_NATIVE)
526 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
528 if (arg3[0] < 0x10) {
531 if (size != OP_SIZE_8) {
533 if (code == (it)-1 || arg1[0] != arg2[0]) {
539 if (code == (it)-1 || arg1[0] != arg2[0]) {
546 code |= (it)arg1[0] << 20;
547 code |= (it)arg2[0] << 16;
548 code |= (it)arg3[0] << 28;
550 code |= (it)arg1[0] << 36;
551 code |= (it)arg3[0] << 32;
552 } else if (sz == 1 || sz == 2) {
553 code |= (it)arg1[0] << 20;
554 code |= (it)arg3[0] << 16;
558 g(cgen_s390(ctx, code));
561 if (unlikely(arg1[0] != arg2[0]))
563 if (arg3[0] == ARG_IMM) {
564 imm = get_imm(&arg3[1]);
565 if (codes->neg_imm == 1)
566 imm = -(uint64_t)imm;
567 if (imm >= -0x8000 && imm < 0x8000) {
568 code = size != OP_SIZE_8 ? codes->ri : codes->rig;
569 if (unlikely(code == (it)-1))
571 code |= (it)arg1[0] << 36;
572 code |= (it)(imm & 0xffff) << 16;
573 } else if (imm >= -0x80000000LL && imm < 0x80000000LL) {
575 if (unlikely(code == (it)-1))
577 code |= (it)arg1[0] << 36;
578 code |= (it)(imm & 0xffffffffLL);
582 g(cgen_s390(ctx, code));
585 if (codes->neg_imm == 2)
587 if (!(imm & ~0xffffULL) && codes->rill != (it)-1) {
589 if (codes->neg_imm == 2)
591 code |= (it)(imm & 0xffffULL) << 16;
592 } else if (!(imm & ~0xffff0000ULL) && codes->rilh != (it)-1) {
594 if (codes->neg_imm == 2)
596 code |= (it)(imm & 0xffff0000ULL);
597 } else if (!(imm & ~0xffff00000000ULL) && codes->rihl != (it)-1) {
599 if (codes->neg_imm == 2)
601 code |= (it)((uint64_t)imm & 0xffff00000000ULL) >> 16;
602 } else if (!(imm & ~0xffff000000000000ULL) && codes->rihh != (it)-1) {
604 if (codes->neg_imm == 2)
606 code |= (it)((uint64_t)imm & 0xffff000000000000ULL) >> 32;
607 } else if (!(imm & ~0xffffffffULL) && codes->rilf != (it)-1) {
609 if (codes->neg_imm == 2)
611 code |= (it)(imm & 0xffffffffLL);
612 } else if (!(imm & ~0xffffffff00000000ULL) && codes->rihf != (it)-1) {
614 if (codes->neg_imm == 2)
616 code |= (it)(((uint64_t)imm & 0xffffffff00000000LL) >> 32);
620 code |= (it)arg1[0] << 36;
621 g(cgen_s390(ctx, code));
623 } else if (arg3[0] == ARG_ADDRESS_0) {
627 } else if (arg3[0] == ARG_ADDRESS_1) {
631 } else if (arg3[0] == ARG_ADDRESS_2) {
640 if (size != OP_SIZE_8) {
641 if (imm >= 0 && imm < 0x1000 && codes->rx != (it)-1) {
643 code |= (it)arg1[0] << 36;
646 code |= (it)(imm & 0xfff) << 16;
647 } else if (imm >= -0x80000 && imm < 0x80000) {
655 if (imm >= -0x80000 && imm < 0x80000) {
657 code |= (it)arg1[0] << 36;
660 code |= (it)(imm & 0xfff) << 16;
661 code |= (it)(imm & 0xff000) >> 4;
667 g(cgen_s390(ctx, code));
670 internal(file_line, "cgen_rr_rx: invalid arguments %u, %02x, %02x, %02x", size, *arg1, *arg2, *arg3);
674 static bool attr_w cgen_fp_mem(struct codegen_context *ctx, unsigned size, uint8_t *arg1, uint8_t *arg2, it e, it ey, it d, it dy)
680 if (size != OP_SIZE_4 && size != OP_SIZE_8)
682 if (unlikely(!reg_is_fp(arg1[0])))
684 if (arg2[0] == ARG_ADDRESS_0) {
688 } else if (arg2[0] == ARG_ADDRESS_1) {
692 } else if (arg2[0] == ARG_ADDRESS_2) {
700 if (imm >= 0 && imm < 4096) {
701 code = size == OP_SIZE_4 ? e : d;
702 } else if (imm >= -0x80000 && imm < 0x80000) {
703 code = size == OP_SIZE_4 ? ey : dy;
704 code |= (it)(imm & 0xff000) >> 4;
708 code |= (it)(arg1[0] & 0xf) << 36;
711 code |= (it)(imm & 0xfff) << 16;
712 g(cgen_s390(ctx, code));
715 internal(file_line, "cgen_fp_mem: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
719 static bool attr_w cgen_fp_op(struct codegen_context *ctx, unsigned size, uint8_t *arg1, uint8_t *arg2, const struct fp_alu *fp_alu)
725 if (size != OP_SIZE_4 && size != OP_SIZE_8 && size != OP_SIZE_16)
727 if (reg_is_fp(arg2[0])) {
729 code = size == OP_SIZE_4 ? fp_alu->err : size == OP_SIZE_8 ? fp_alu->drr : fp_alu->xrr;
732 code |= (it)(arg1[0] & 0xf) << 36;
733 code |= (it)(arg2[0] & 0xf) << 32;
735 code |= (it)(arg1[0] & 0xf) << 20;
736 code |= (it)(arg2[0] & 0xf) << 16;
738 g(cgen_s390(ctx, code));
740 } else if (arg2[0] == ARG_ADDRESS_0) {
744 } else if (arg2[0] == ARG_ADDRESS_1) {
748 } else if (arg2[0] == ARG_ADDRESS_2) {
756 if (unlikely(imm < 0) || unlikely(imm >= 4096))
758 if (unlikely(size == OP_SIZE_16))
760 code = size == OP_SIZE_4 ? fp_alu->erx : fp_alu->drx;
761 code |= (it)(arg1[0] & 0xf) << 36;
764 code |= (it)(imm & 0xfff) << 16;
765 g(cgen_s390(ctx, code));
768 internal(file_line, "cgen_fp_op: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
772 static bool attr_w cgen_xi(struct codegen_context *ctx, uint8_t *arg1, uint8_t *arg2, it xi, it xiy)
778 if (unlikely(arg1[0] == ARG_ADDRESS_0)) {
781 } else if (likely(arg1[0] == ARG_ADDRESS_1) && likely(arg2[0] == ARG_IMM)) {
789 if (likely(arg2[0] == ARG_IMM)) {
790 val = get_imm(&arg2[1]);
795 if (imm >= 0 && imm < 0x1000) {
797 code |= (it)(imm & 0xfff) << 16;
798 } else if (imm >= -0x80000 && imm < 0x80000) {
800 code |= (it)(imm & 0xfff) << 16;
801 code |= (it)(imm & 0xff000) >> 4;
806 code |= (it)(val & 0xff) << 32;
809 g(cgen_s390(ctx, code));
812 internal(file_line, "cgen_xi: invalid arguments %02x, %02x", *arg1, *arg2);
816 static bool attr_w cgen_lm_stm(struct codegen_context *ctx, unsigned size, uint8_t r_start, uint8_t r_end, uint8_t *arg1, it m, it my, it mg)
820 if (unlikely(r_start >= 0x10) || unlikely(r_end >= 0x10) || unlikely(arg1[0] != ARG_ADDRESS_1) || unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
822 imm = get_imm(&arg1[2]);
823 if (size == OP_SIZE_4 && imm >= 0 && imm < 0x1000) {
825 code |= (it)(imm & 0xfff) << 16;
827 if (size == OP_SIZE_4)
831 code |= (it)(imm & 0xfff) << 16;
832 code |= (it)(imm & 0xff000) >> 4;
834 code |= (it)r_start << 36;
835 code |= (it)r_end << 32;
836 code |= (it)arg1[1] << 28;
837 g(cgen_s390(ctx, code));
840 internal(file_line, "cgen_lm_stm: invalid arguments %02x", *arg1);
844 static bool attr_w cgen_s390_push_pop(struct codegen_context *ctx, unsigned size, bool push)
847 arg1 = ctx->code_position;
848 ctx->code_position = arg1 + arg_size(*arg1);
850 g(cgen_lm_stm(ctx, size, R_6, R_15, arg1, S390_LM, S390_LMY, S390_LMG));
852 g(cgen_lm_stm(ctx, size, R_6, R_15, arg1, S390_STM, S390_STMY, S390_STMG));
856 static bool attr_w cgen_call_indirect(struct codegen_context *ctx)
858 uint8_t reg = cget_one(ctx);
860 code |= (it)R_14 << 36;
861 code |= (it)reg << 32;
862 g(cgen_s390(ctx, code));
866 static bool attr_w cgen_branch_imm(struct codegen_context *ctx, uint8_t reg, int64_t imm)
870 code |= (it)reg << 36;
871 code |= (OP_SIZE_NATIVE == OP_SIZE_4 ? (it)4 : (it)6) << 16;
872 g(cgen_s390(ctx, code));
873 if (OP_SIZE_NATIVE == OP_SIZE_4) {
878 code = OP_SIZE_NATIVE == OP_SIZE_4 ? S390_L : S390_LG;
879 code |= (it)reg << 36;
880 code |= (it)reg << 28;
881 g(cgen_s390(ctx, code));
885 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
887 uint8_t *arg1 = ctx->code_position;
888 uint8_t *arg2 = arg1 + arg_size(*arg1);
889 ctx->code_position = arg2 + arg_size(*arg2);
890 if (arg1[0] < 0x10) {
891 if (unlikely(size != OP_SIZE_NATIVE)) {
894 if (unlikely(!cpu_test_feature(CPU_FEATURE_extended_imm)))
896 g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_8_unsigned));
899 if (unlikely(!cpu_test_feature(CPU_FEATURE_extended_imm)))
901 g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_16_unsigned));
904 g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_32_unsigned));
910 if (!cpu_test_feature(CPU_FEATURE_extended_imm) && arg2[0] == ARG_IMM) {
911 int64_t imm = get_imm(&arg2[1]);
912 if (imm < -0x8000 || imm >= 0x8000) {
913 g(cgen_branch_imm(ctx, arg1[0], imm));
917 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_load));
920 if (reg_is_fp(arg1[0])) {
921 if (reg_is_fp(arg2[0])) {
922 g(cgen_fp_op(ctx, size, arg1, arg2, &fp_mov));
925 if (unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
927 g(cgen_fp_mem(ctx, size, arg1, arg2, S390_LE, S390_LEY, S390_LD, S390_LDY));
930 if (arg2[0] < 0x10) {
931 g(cgen_rr_rx(ctx, size, arg2, arg2, arg1, size == OP_SIZE_1 ? &codes_store_8 : size == OP_SIZE_2 ? &codes_store_16 : &codes_store));
934 if (reg_is_fp(arg2[0])) {
935 if (unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
937 g(cgen_fp_mem(ctx, size, arg2, arg1, S390_STE, S390_STEY, S390_STD, S390_STDY));
940 if (size == OP_SIZE_1 && arg1[0] == ARG_ADDRESS_1 && arg2[0] == ARG_IMM) {
941 g(cgen_xi(ctx, arg1, arg2, S390_MVI, S390_MVIY));
945 internal(file_line, "cgen_mov: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
949 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
951 uint8_t *arg1, *arg2;
952 if (unlikely(size == OP_SIZE_NATIVE)) {
953 g(cgen_mov(ctx, size));
956 arg1 = ctx->code_position;
957 arg2 = arg1 + arg_size(*arg1);
958 ctx->code_position = arg2 + arg_size(*arg2);
961 if (arg2[0] >= 0x10 ? !cpu_test_feature(CPU_FEATURE_long_displacement) : !cpu_test_feature(CPU_FEATURE_extended_imm))
963 g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_8));
966 if (arg2[0] < 0x10 && !cpu_test_feature(CPU_FEATURE_extended_imm))
968 g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_16));
971 g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_32));
977 internal(file_line, "cgen_movsx: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
981 static bool attr_w cgen_cmp(struct codegen_context *ctx, unsigned size, unsigned writes_flags)
983 uint8_t *arg1, *arg2;
984 arg1 = ctx->code_position;
985 arg2 = arg1 + arg_size(*arg1);
986 ctx->code_position = arg2 + arg_size(*arg2);
987 if (writes_flags == 1) {
988 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_cmp));
990 } else if (writes_flags == 2) {
991 if (size == OP_SIZE_1 && arg1[0] == ARG_ADDRESS_1 && arg2[0] == ARG_IMM) {
992 g(cgen_xi(ctx, arg1, arg2, S390_CLI, S390_CLIY));
995 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_cmp_log));
998 internal(file_line, "cgen_cmp: invalid arguments %u, %02x, %02x, %u", size, *arg1, *arg2, writes_flags);
1002 static bool attr_w cgen_test(struct codegen_context *ctx, unsigned size)
1005 uint8_t *arg1, *arg2;
1006 arg1 = ctx->code_position;
1007 arg2 = arg1 + arg_size(*arg1);
1008 ctx->code_position = arg2 + arg_size(*arg2);
1009 if (likely(arg1[0] < 0x10) && likely(arg2[0] == ARG_IMM)) {
1011 int64_t imm = get_imm(&arg2[1]);
1012 if (!(imm & ~0xffffULL)) {
1015 } else if (!(imm & ~0xffff0000ULL)) {
1017 m = (uint64_t)imm >> 16;
1018 } else if (!(imm & ~0xffff00000000ULL)) {
1020 m = (uint64_t)imm >> 32;
1021 } else if (!(imm & ~0xffff000000000000ULL)) {
1023 m = (uint64_t)imm >> 48;
1027 code |= (it)m << 16;
1028 code |= (it)arg1[0] << 36;
1029 g(cgen_s390(ctx, code));
1032 if (arg1[0] < 0x10 && arg2[0] == arg1[0]) {
1033 if (size == OP_SIZE_4) {
1035 code |= (it)arg1[0] << 36;
1036 code |= (it)arg1[0] << 32;
1037 } else if (size == OP_SIZE_8) {
1039 code |= (it)arg1[0] << 20;
1040 code |= (it)arg1[0] << 16;
1044 g(cgen_s390(ctx, code));
1048 internal(file_line, "cgen_test: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
1052 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
1054 uint8_t *arg1, *arg2, *arg3;
1055 arg1 = ctx->code_position;
1056 arg2 = arg1 + arg_size(*arg1);
1057 arg3 = arg2 + arg_size(*arg2);
1058 ctx->code_position = arg3 + arg_size(*arg3);
1059 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
1061 if (writes_flags == 0) {
1062 if (unlikely(alu >= n_array_elements(codes_alu_no_flags)))
1064 if (unlikely(codes_alu_no_flags[alu].rr == (it)-1) && unlikely(codes_alu_no_flags[alu].rrk == (it)-1))
1066 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu_no_flags[alu]));
1067 } else if (writes_flags == 1) {
1068 if (unlikely(alu >= n_array_elements(codes_alu)))
1070 if (unlikely(codes_alu[alu].rr == (it)-1) && unlikely(codes_alu[alu].rrk == (it)-1))
1072 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu[alu]));
1073 } else if (writes_flags == 2) {
1074 if (unlikely(alu >= n_array_elements(codes_alu_log)))
1076 if (unlikely(codes_alu_log[alu].rr == (it)-1) && unlikely(codes_alu_log[alu].rrk == (it)-1))
1078 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu_log[alu]));
1084 /*debug("%s", da(ctx->fn,function)->function_name);*/
1085 internal(file_line, "cgen_alu: invalid arguments %u, %u, %02x, %02x, %02x", size, alu, *arg1, *arg2, *arg3);
1089 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
1092 uint8_t *arg1 = ctx->code_position;
1093 uint8_t *arg2 = arg1 + arg_size(*arg1);
1094 ctx->code_position = arg2 + arg_size(*arg2);
1095 if (unlikely(arg1[0] >= 0x10) || (unlikely(arg2[0] != arg1[0]) && (alu == ALU1_INC || alu == ALU1_DEC)))
1099 if (unlikely(writes_flags != 1))
1101 if (size == OP_SIZE_4) {
1103 code |= (it)arg1[0] << 36;
1104 code |= (it)arg2[0] << 32;
1105 } else if (size == OP_SIZE_8) {
1107 code |= (it)arg1[0] << 20;
1108 code |= (it)arg2[0] << 16;
1115 if (unlikely(writes_flags != 1))
1117 if (size == OP_SIZE_4) {
1119 } else if (size == OP_SIZE_8) {
1124 code |= (it)arg1[0] << 36;
1125 if (alu == ALU1_INC)
1126 code |= (it)0x0001 << 16;
1128 code |= (it)0xffff << 16;
1131 if (size == OP_SIZE_4) {
1133 } else if (size == OP_SIZE_8) {
1138 code |= (it)arg1[0] << 20;
1139 code |= (it)arg2[0] << 16;
1142 if (size != OP_SIZE_8)
1145 code |= (it)arg1[0] << 20;
1146 code |= (it)arg2[0] << 16;
1151 g(cgen_s390(ctx, code));
1154 internal(file_line, "cgen_alu1: invalid arguments %u, %u, %02x, %02x", size, alu, *arg1, *arg2);
1158 static bool attr_w cgen_lea3(struct codegen_context *ctx)
1162 uint8_t *arg1, *arg2, *arg3, *arg4;
1163 arg1 = ctx->code_position;
1164 arg2 = arg1 + arg_size(*arg1);
1165 arg3 = arg2 + arg_size(*arg2);
1166 arg4 = arg3 + arg_size(*arg3);
1167 ctx->code_position = arg4 + arg_size(*arg4);
1168 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10) || arg4[0] != ARG_IMM)
1170 imm = get_imm(&arg4[1]);
1171 if (imm >= 0 && imm < 0x1000) {
1175 code |= (it)(imm & 0xff000) >> 4;
1177 code |= (it)arg1[0] << 36;
1178 code |= (it)arg2[0] << 32;
1179 code |= (it)arg3[0] << 28;
1180 code |= (it)(imm & 0xfff) << 16;
1181 g(cgen_s390(ctx, code));
1184 internal(file_line, "cgen_lea3: invalid arguments %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4);
1188 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, unsigned alu)
1192 uint8_t *arg1, *arg2, *arg3;
1193 arg1 = ctx->code_position;
1194 arg2 = arg1 + arg_size(*arg1);
1195 arg3 = arg2 + arg_size(*arg2);
1196 ctx->code_position = arg3 + arg_size(*arg3);
1197 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
1199 if (arg3[0] >= 0x10 && unlikely(arg3[0] != ARG_IMM))
1202 if (size == OP_SIZE_4 && arg1[0] == arg2[0]) {
1204 } else if (size == OP_SIZE_4) {
1206 } else if (size == OP_SIZE_8) {
1212 if (sz == 1 || sz == 2) {
1213 code |= (it)arg1[0] << 36;
1214 } else if (sz == 3) {
1215 code |= (it)arg1[0] << 36;
1216 code |= (it)arg2[0] << 32;
1220 if (arg3[0] == ARG_IMM)
1221 code |= (it)(get_imm(&arg3[1]) & (size == OP_SIZE_4 ? 0x1f : 0x3f)) << 16;
1223 code |= (it)arg3[0] << 28;
1224 g(cgen_s390(ctx, code));
1227 internal(file_line, "cgen_rot: invalid arguments %u, %u, %02x, %02x, %02x", size, alu, *arg1, *arg2, *arg3);
1231 static bool attr_w cgen_mul_l(struct codegen_context *ctx, unsigned size)
1234 uint8_t *arg1, *arg2, *arg3, *arg4;
1235 arg1 = ctx->code_position;
1236 arg2 = arg1 + arg_size(*arg1);
1237 arg3 = arg2 + arg_size(*arg2);
1238 arg4 = arg3 + arg_size(*arg3);
1239 ctx->code_position = arg4 + arg_size(*arg4);
1240 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10) || unlikely(arg4[0] >= 0x10))
1242 if (unlikely(arg2[0] & 1) || unlikely(arg1[0] != arg2[0] + 1) || unlikely(arg3[0] != arg1[0]))
1244 if (size == OP_SIZE_4) {
1246 code |= (it)arg2[0] << 36;
1247 code |= (it)arg4[0] << 32;
1250 code |= (it)arg2[0] << 20;
1251 code |= (it)arg3[0] << 16;
1252 code |= (it)arg4[0] << 28;
1254 g(cgen_s390(ctx, code));
1257 internal(file_line, "cgen_mul_l: invalid arguments %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4);
1261 static bool attr_w cgen_div_l(struct codegen_context *ctx, unsigned size, bool sgn)
1264 uint8_t *arg1, *arg2, *arg3, *arg4, *arg5;
1265 arg1 = ctx->code_position;
1266 arg2 = arg1 + arg_size(*arg1);
1267 arg3 = arg2 + arg_size(*arg2);
1268 arg4 = arg3 + arg_size(*arg3);
1269 arg5 = arg4 + arg_size(*arg4);
1270 ctx->code_position = arg5 + arg_size(*arg5);
1271 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10) || unlikely(arg4[0] >= 0x10) || unlikely(arg5[0] >= 0x10))
1273 if (unlikely(arg1[0] & 1) || unlikely(arg2[0] != arg1[0] + 1))
1275 if (unlikely(arg3[0] != arg1[0]) || unlikely(arg4[0] != arg3[0] + 1))
1278 code = size == OP_SIZE_4 ? S390_DLR : S390_DLGR;
1280 code = size == OP_SIZE_4 ? S390_DR : S390_DSGR;
1282 if (code == S390_DR) {
1283 code |= (it)arg1[0] << 36;
1284 code |= (it)arg5[0] << 32;
1286 code |= (it)arg1[0] << 20;
1287 code |= (it)arg5[0] << 16;
1289 g(cgen_s390(ctx, code));
1292 internal(file_line, "cgen_div_l: invalid arguments %02x, %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4, *arg4);
1296 static bool attr_w cgen_cmov(struct codegen_context *ctx, unsigned size, unsigned cond, bool logical)
1298 uint8_t *arg1 = ctx->code_position;
1299 uint8_t *arg2 = arg1 + arg_size(*arg1);
1300 uint8_t *arg3 = arg2 + arg_size(*arg2);
1301 ctx->code_position = arg3 + arg_size(*arg3);
1302 if (unlikely(arg1[0] != arg2[0]) || arg1[0] >= 0x10)
1305 if (arg3[0] < 0x10) {
1307 code = size == OP_SIZE_4 ? S390_LOCR : S390_LOCGR;
1308 code |= (it)get_jmp_cond(cond, logical) << 28;
1309 code |= (it)arg1[0] << 20;
1310 code |= (it)arg3[0] << 16;
1311 g(cgen_s390(ctx, code));
1313 } else if (arg3[0] == ARG_ADDRESS_1) {
1316 code = size == OP_SIZE_4 ? S390_LOC : S390_LOCG;
1317 code |= (it)get_jmp_cond(cond, logical) << 32;
1318 code |= (it)arg1[0] << 36;
1319 code |= (it)arg3[1] << 28;
1320 imm = get_imm(&arg3[2]);
1321 if (imm < -0x80000 || imm >= 0x80000)
1323 code |= (it)(imm & 0xfff) << 16;
1324 code |= (it)(imm & 0xff000) >> 4;
1325 g(cgen_s390(ctx, code));
1330 internal(file_line, "cgen_cmov: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1333 static bool attr_w cgen_ldp_stp(struct codegen_context *ctx, unsigned size, bool st)
1335 uint8_t *arg1, *arg2, *arg3;
1337 arg2 = ctx->code_position;
1338 arg3 = arg2 + arg_size(*arg2);
1339 arg1 = arg3 + arg_size(*arg3);
1340 ctx->code_position = arg1 + arg_size(*arg1);
1342 arg1 = ctx->code_position;
1343 arg2 = arg1 + arg_size(*arg1);
1344 arg3 = arg2 + arg_size(*arg2);
1345 ctx->code_position = arg3 + arg_size(*arg3);
1347 if (unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10))
1349 if (unlikely(arg2[0] != arg3[0] + 1))
1352 g(cgen_lm_stm(ctx, size, arg3[0], arg2[0], arg1, S390_LM, S390_LMY, S390_LMG));
1354 g(cgen_lm_stm(ctx, size, arg3[0], arg2[0], arg1, S390_STM, S390_STMY, S390_STMG));
1357 internal(file_line, "cgen_ldp_stp: invalid arguments %u, %02x, %02x, %02x", size, *arg1, *arg2, *arg3);
1361 static bool attr_w cgen_ic(struct codegen_context *ctx)
1363 uint8_t *arg1, *arg2, *arg3;
1364 arg1 = ctx->code_position;
1365 arg2 = arg1 + arg_size(*arg1);
1366 arg3 = arg2 + arg_size(*arg2);
1367 ctx->code_position = arg3 + arg_size(*arg3);
1368 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] != arg1[0]))
1370 g(cgen_rr_rx(ctx, OP_SIZE_4, arg1, arg2, arg3, &codes_ic));
1373 internal(file_line, "cgen_ic: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1377 static bool attr_w cgen_mov_mask(struct codegen_context *ctx)
1381 uint8_t *arg1, *arg2, *arg3;
1382 arg1 = ctx->code_position;
1383 arg2 = arg1 + arg_size(*arg1);
1384 arg3 = arg2 + arg_size(*arg2);
1385 ctx->code_position = arg3 + arg_size(*arg3);
1386 if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] != arg1[0]) || unlikely(arg3[0] != ARG_IMM))
1388 imm = get_imm(&arg3[1]);
1390 code |= (it)arg1[1] << 36;
1391 code |= (it)(imm & 0xffffffffLL);
1392 g(cgen_s390(ctx, code));
1395 internal(file_line, "cgen_mov_mask: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1399 static bool attr_w cgen_memcpy(struct codegen_context *ctx)
1402 int64_t disp_dest, disp_src, len;
1403 uint8_t *arg1, *arg2, *arg3;
1404 arg1 = ctx->code_position;
1405 arg2 = arg1 + arg_size(*arg1);
1406 arg3 = arg2 + arg_size(*arg2);
1407 ctx->code_position = arg3 + arg_size(*arg3);
1408 if (unlikely(arg1[0] != ARG_ADDRESS_1) || unlikely(arg2[0] != ARG_ADDRESS_1) || unlikely(arg3[0] != ARG_IMM))
1410 disp_dest = get_imm(&arg1[2]);
1411 disp_src = get_imm(&arg2[2]);
1412 len = get_imm(&arg3[1]);
1414 code |= (it)((len - 1) & 0xff) << 32;
1415 code |= (it)arg1[1] << 28;
1416 code |= (it)(disp_dest & 0xfff) << 16;
1417 code |= (it)arg2[1] << 12;
1418 code |= (it)(disp_src & 0xfff) << 0;
1419 g(cgen_s390(ctx, code));
1422 internal(file_line, "cgen_memcpy: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1426 static bool attr_w cgen_fp_cmp(struct codegen_context *ctx, unsigned size)
1428 uint8_t *arg1 = ctx->code_position;
1429 uint8_t *arg2 = arg1 + arg_size(*arg1);
1430 ctx->code_position = arg2 + arg_size(*arg2);
1431 if (unlikely(!reg_is_fp(arg1[0])))
1433 g(cgen_fp_op(ctx, size, arg1, arg2, &fp_cmp));
1436 internal(file_line, "cgen_fp_cmp: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
1440 static bool attr_w cgen_fp_alu(struct codegen_context *ctx, unsigned size, unsigned aux)
1442 uint8_t *arg1 = ctx->code_position;
1443 uint8_t *arg2 = arg1 + arg_size(*arg1);
1444 uint8_t *arg3 = arg2 + arg_size(*arg2);
1445 ctx->code_position = arg3 + arg_size(*arg3);
1446 if (unlikely(!reg_is_fp(arg1[0])) || unlikely(arg1[0] != arg2[0]))
1448 g(cgen_fp_op(ctx, size, arg1, arg3, &fp_alus[aux]));
1451 internal(file_line, "cgen_fp_alu: invalid arguments %u, %u, %02x, %02x, %02x", size, aux, *arg1, *arg2, *arg3);
1455 static bool attr_w cgen_fp_alu1(struct codegen_context *ctx, unsigned size, unsigned aux)
1457 uint8_t *arg1 = ctx->code_position;
1458 uint8_t *arg2 = arg1 + arg_size(*arg1);
1459 ctx->code_position = arg2 + arg_size(*arg2);
1460 if (unlikely(!reg_is_fp(arg1[0])))
1462 g(cgen_fp_op(ctx, size, arg1, arg2, &fp_alu1s[aux]));
1465 internal(file_line, "cgen_fp_alu1: invalid arguments %u, %u, %02x, %02x", size, aux, *arg1, *arg2);
1469 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1472 uint8_t *arg1 = ctx->code_position;
1473 uint8_t *arg2 = arg1 + arg_size(*arg1);
1474 ctx->code_position = arg2 + arg_size(*arg2);
1475 if (unlikely(arg1[0] >= 0x10) || unlikely(!reg_is_fp(arg2[0])))
1477 switch (fp_op_size) {
1479 code = int_op_size == OP_SIZE_4 ? S390_CFEBR : S390_CGEBR;
1482 code = int_op_size == OP_SIZE_4 ? S390_CFDBR : S390_CGDBR;
1485 code = int_op_size == OP_SIZE_4 ? S390_CFXBR : S390_CGXBR;
1490 code |= (it)5 << 28;
1491 code |= (it)arg1[0] << 20;
1492 code |= (it)(arg2[0] & 0xf) << 16;
1493 g(cgen_s390(ctx, code));
1496 internal(file_line, "cgen_fp_to_int: invalid arguments %u, %u, %02x, %02x", int_op_size, fp_op_size, *arg1, *arg2);
1500 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1503 uint8_t *arg1 = ctx->code_position;
1504 uint8_t *arg2 = arg1 + arg_size(*arg1);
1505 ctx->code_position = arg2 + arg_size(*arg2);
1506 if (unlikely(!reg_is_fp(arg1[0])) || unlikely(arg2[0] >= 0x10))
1508 switch (fp_op_size) {
1510 code = int_op_size == OP_SIZE_4 ? S390_CEFBR : S390_CEGBR;
1513 code = int_op_size == OP_SIZE_4 ? S390_CDFBR : S390_CDGBR;
1516 code = int_op_size == OP_SIZE_4 ? S390_CXFBR : S390_CXGBR;
1521 code |= (it)(arg1[0] & 0xf) << 20;
1522 code |= (it)arg2[0] << 16;
1523 g(cgen_s390(ctx, code));
1526 internal(file_line, "cgen_fp_from_int: invalid arguments %u, %u, %02x, %02x", int_op_size, fp_op_size, *arg1, *arg2);
1530 static bool attr_w cgen_jmp_cond(struct codegen_context *ctx, bool lng, unsigned aux, bool logical)
1534 g(add_relocation(ctx, JMP_SHORTEST, 0, NULL));
1536 } else if (USE_BRCL) {
1537 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1540 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1542 code |= (it)R_OFFSET_IMM << 36;
1543 code |= (it)4 << 16;
1544 g(cgen_s390(ctx, code));
1546 #if defined(ARCH_S390_32)
1551 code |= (it)R_CONST_IMM << 36;
1552 code |= (it)R_OFFSET_IMM << 28;
1553 g(cgen_s390(ctx, code));
1555 code |= (it)R_OFFSET_IMM << 36;
1556 code |= (it)R_OFFSET_IMM << 32;
1557 code |= (it)R_CONST_IMM << 28;
1558 g(cgen_s390(ctx, code));
1560 code |= (it)R_OFFSET_IMM << 32;
1561 code |= (it)get_jmp_cond(aux, logical) << 36;
1562 g(cgen_s390(ctx, code));
1565 code |= (it)get_jmp_cond(aux, logical) << 36;
1566 g(cgen_s390(ctx, code));
1570 static bool attr_w cgen_jmp_indirect(struct codegen_context *ctx)
1572 uint8_t reg = cget_one(ctx);
1574 code |= (it)(S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ) << 36;
1575 code |= (it)reg << 32;
1576 g(cgen_s390(ctx, code));
1580 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1582 int64_t offs = ((int64_t)ctx->label_to_pos[reloc->label_id] - (int64_t)(reloc->position)) / 2;
1583 switch (reloc->length) {
1584 case JMP_SHORTEST: {
1586 if (unlikely(offs < -0x8000) || unlikely(offs >= 0x8000))
1589 memcpy(ctx->mcode + reloc->position + 2, &i16, 2);
1595 if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
1598 memcpy(ctx->mcode + reloc->position + 2, &i32, 4);
1603 if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
1606 memcpy(ctx->mcode + reloc->position + 4, &i32, 4);
1611 internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1617 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1619 /*debug("insn: %08x", insn);*/
1620 switch (insn_opcode(insn)) {
1628 g(cgen_s390(ctx, S390_BCR | ((it)(S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ) << 36) | ((it)R_14 << 32)));
1630 case INSN_S390_PUSH:
1631 g(cgen_s390_push_pop(ctx, insn_op_size(insn), true));
1634 g(cgen_s390_push_pop(ctx, insn_op_size(insn), false));
1636 case INSN_CALL_INDIRECT:
1637 g(cgen_call_indirect(ctx));
1640 g(cgen_mov(ctx, insn_op_size(insn)));
1643 g(cgen_movsx(ctx, insn_op_size(insn)));
1646 g(cgen_cmp(ctx, insn_op_size(insn), insn_writes_flags(insn)));
1649 if (unlikely(!insn_writes_flags(insn)))
1651 g(cgen_test(ctx, insn_op_size(insn)));
1654 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1656 g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1658 case INSN_ALU_PARTIAL:
1659 if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1661 g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1664 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1666 g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1668 case INSN_ALU1_PARTIAL:
1669 if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1671 g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1674 if (unlikely(insn_op_size(insn) != OP_SIZE_ADDRESS))
1676 if (unlikely(insn_aux(insn) != 0))
1681 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1683 g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1685 case INSN_ROT_PARTIAL:
1686 if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1688 g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1691 if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1693 g(cgen_mul_l(ctx, insn_op_size(insn)));
1696 g(cgen_div_l(ctx, insn_op_size(insn), insn_aux(insn)));
1700 if (unlikely(!cpu_test_feature(CPU_FEATURE_misc_45)))
1702 g(cgen_cmov(ctx, insn_op_size(insn), insn_aux(insn), insn_opcode(insn) == INSN_CMOV_XCC));
1705 if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1707 g(cgen_ldp_stp(ctx, insn_op_size(insn), true));
1710 if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1712 g(cgen_ldp_stp(ctx, insn_op_size(insn), false));
1715 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1717 if (insn_aux(insn) == MOV_MASK_0_8) {
1719 } else if (insn_aux(insn) == MOV_MASK_32_64) {
1720 g(cgen_mov_mask(ctx));
1726 g(cgen_memcpy(ctx));
1729 g(cgen_fp_cmp(ctx, insn_op_size(insn)));
1732 g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1735 g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1737 case INSN_FP_TO_INT32:
1738 g(cgen_fp_to_int(ctx, OP_SIZE_4, insn_op_size(insn)));
1740 case INSN_FP_TO_INT64:
1741 g(cgen_fp_to_int(ctx, OP_SIZE_8, insn_op_size(insn)));
1743 case INSN_FP_FROM_INT32:
1744 g(cgen_fp_from_int(ctx, OP_SIZE_4, insn_op_size(insn)));
1746 case INSN_FP_FROM_INT64:
1747 g(cgen_fp_from_int(ctx, OP_SIZE_8, insn_op_size(insn)));
1750 g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, COND_ALWAYS, false));
1753 g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, insn_aux(insn), false));
1755 case INSN_JMP_COND_LOGICAL:
1756 g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, insn_aux(insn), true));
1758 case INSN_JMP_INDIRECT:
1759 g(cgen_jmp_indirect(ctx));
1763 internal(file_line, "cgen_insn: invalid insn %08x", insn);