Ajla 0.1.0
[ajla.git] / c2-s390.inc
blob8c95a6d57c14a58fee4e25da001a9abb18535713
1 /*
2  * Copyright (C) 2024 Mikulas Patocka
3  *
4  * This file is part of Ajla.
5  *
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
9  * version.
10  *
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.
14  *
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/>.
17  */
19 typedef uint64_t it;
21 #define USE_BRCL                Z
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_CEFBR              0xb39400000000ULL
226 #define S390_CDFBR              0xb39500000000ULL
227 #define S390_CXFBR              0xb39600000000ULL
228 #define S390_CEGBR              0xb3a400000000ULL
229 #define S390_CDGBR              0xb3a500000000ULL
230 #define S390_CXGBR              0xb3a600000000ULL
232 #define S390_CFEBR              0xb39800000000ULL
233 #define S390_CFDBR              0xb39900000000ULL
234 #define S390_CFXBR              0xb39a00000000ULL
235 #define S390_CGEBR              0xb3a800000000ULL
236 #define S390_CGDBR              0xb3a900000000ULL
237 #define S390_CGXBR              0xb3aa00000000ULL
239 #define S390_LHR                0xb92700000000ULL
240 #define S390_LH                 0x480000000000ULL
241 #define S390_LHY                0xe30000000078ULL
242 #define S390_LGHR               0xb90700000000ULL
243 #define S390_LGH                0xe30000000015ULL
244 #define S390_LGF                0xe30000000014ULL
245 #define S390_LLGF               0xe30000000016ULL
247 #define S390_RLL                0xeb000000001dULL
248 #define S390_RLLG               0xeb000000001cULL
249 #define S390_SRL                0x880000000000ULL
250 #define S390_SRLK               0xeb00000000deULL
251 #define S390_SRLG               0xeb000000000cULL
252 #define S390_SLL                0x890000000000ULL
253 #define S390_SLLK               0xeb00000000dfULL
254 #define S390_SLLG               0xeb000000000dULL
255 #define S390_SRA                0x8a0000000000ULL
256 #define S390_SRAK               0xeb00000000dcULL
257 #define S390_SRAG               0xeb000000000aULL
258 #define S390_SLA                0x8b0000000000ULL
259 #define S390_SLAK               0xeb00000000ddULL
260 #define S390_SLAG               0xeb000000000bULL
262 #define S390_STM                0x900000000000ULL
263 #define S390_STMY               0xeb0000000090ULL
264 #define S390_STMG               0xeb0000000024ULL
265 #define S390_LM                 0x980000000000ULL
266 #define S390_LMY                0xeb0000000098ULL
267 #define S390_LMG                0xeb0000000004ULL
269 #define S390_MVI                0x920000000000ULL
270 #define S390_MVIY               0xeb0000000052ULL
271 #define S390_CLI                0x950000000000ULL
272 #define S390_CLIY               0xeb0000000055ULL
274 #define S390_TMLL               0xa70100000000ULL
275 #define S390_TMLH               0xa70000000000ULL
276 #define S390_TMHL               0xa70300000000ULL
277 #define S390_TMHH               0xa70200000000ULL
279 #define S390_BRC                0xa70400000000ULL
280 #define S390_BRAS               0xa70500000000ULL
281 #define S390_LRVR               0xb91f00000000ULL
282 #define S390_LRVRG              0xb90f00000000ULL
283 #define S390_POPCNT             0xb9e180000000ULL
284 #define S390_LOCR               0xb9f200000000ULL
285 #define S390_LOCGR              0xb9e200000000ULL
286 #define S390_NCRK               0xb9f500000000ULL
287 #define S390_NCGRK              0xb9e500000000ULL
288 #define S390_LOC                0xeb00000000f2ULL
289 #define S390_LOCG               0xeb00000000e2ULL
290 #define S390_BRCL               0xc00400000000ULL
291 #define  S390_BRC_OVF                   0x1ULL
292 #define  S390_BRC_GREATER               0x2ULL
293 #define  S390_BRC_LESS                  0x4ULL
294 #define  S390_BRC_EQ                    0x8ULL
296 #define S390_IIHF               0xc00800000000ULL
297 #define S390_IILF               0xc00900000000ULL
299 #define S390_MVC                0xd20000000000ULL
301 struct codes {
302         it rr;
303         it rrk;
304         it rx;
305         it rxy;
306         it rrg;
307         it rrgk;
308         it rxg;
309         it ri;
310         it rig;
311         it rig32;
312         it rill;
313         it rilh;
314         it rihl;
315         it rihh;
316         it rilf;
317         it rihf;
318         int neg_imm;
321 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 };
322 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 };
323 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 };
324 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 };
325 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 };
326 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 };
327 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 };
328 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 };
329 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 };
330 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 };
331 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 };
332 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 };
333 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 };
335 static const struct codes codes_alu_no_flags[] = {
336         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
337         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
338         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
339         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
340         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
341         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
342         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
343         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
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         { S390_MSR, -1, S390_MS, S390_MSY, S390_MSGR, -1, S390_MSG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
355 static const struct codes codes_alu[] = {
356         { 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 },
357         { 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 },
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_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 },
361         { 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 },
362         { 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 },
363         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
364         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
365         { -1, S390_NCRK, -1, -1, -1, S390_NCGRK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 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         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
369         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
370         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
371         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
372         { -1, S390_MSRKC, -1, S390_MSC, -1, S390_MSGRKC, S390_MSGC, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
375 static const struct codes codes_alu_log[] = {
376         { S390_ALR, S390_ALRK, S390_AL, S390_ALY, S390_ALGR, S390_ALGRK, S390_ALG, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
381         { S390_SLR, S390_SLRK, S390_SL, S390_SLY, S390_SLGR, S390_SLGRK, S390_SLG, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
384 static const it rot32[9] = {
385         S390_RLL, -1, -1, -1,
386         S390_SLL, S390_SRL, -1, S390_SRA,
387         S390_SLA,
390 static const it rot32k[9] = {
391         S390_RLL, -1, -1, -1,
392         S390_SLLK, S390_SRLK, -1, S390_SRAK,
393         S390_SLAK,
396 static const it rot64[9] = {
397         S390_RLLG, -1, -1, -1,
398         S390_SLLG, S390_SRLG, -1, S390_SRAG,
399         S390_SLAG,
402 static const int8_t jmp_cond[0x30] = {
403         S390_BRC_OVF,                   S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ,
404         -1,                             -1,
405         S390_BRC_EQ,                    S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_OVF,
406         -1,                             -1,
407         -1,                             -1,
408         -1,                             -1,
409         S390_BRC_LESS,                  S390_BRC_GREATER | S390_BRC_EQ,
410         S390_BRC_LESS | S390_BRC_EQ,    S390_BRC_GREATER,
412         -1,                             -1,
413         S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ, -1,
414         -1,                             -1,
415         -1,                             -1,
416         -1,                             -1,
417         -1,                             -1,
418         -1,                             -1,
419         -1,                             -1,
421         -1,                             -1,
422         S390_BRC_LESS,                  S390_BRC_GREATER | S390_BRC_EQ,
423         S390_BRC_EQ,                    S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_OVF,
424         S390_BRC_LESS | S390_BRC_EQ,    S390_BRC_GREATER,
425         -1,                             -1,
426         S390_BRC_OVF,                   S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ,
427         -1,                             -1,
428         -1,                             -1,
431 static const int8_t jmp_cond_logical[0x8] = {
432         -1,                             -1,
433         S390_BRC_LESS,                  S390_BRC_GREATER | S390_BRC_EQ,
434         S390_BRC_EQ,                    S390_BRC_GREATER | S390_BRC_LESS,
435         S390_BRC_LESS | S390_BRC_EQ,    S390_BRC_GREATER,
438 struct fp_alu {
439         it err;
440         it drr;
441         it xrr;
442         it erx;
443         it drx;
446 static const struct fp_alu fp_alus[4] = {
447         { S390_AEBR, S390_ADBR, S390_AXBR, S390_AEB, S390_ADB },
448         { S390_SEBR, S390_SDBR, S390_SXBR, S390_SEB, S390_SDB },
449         { S390_MEEBR, S390_MDBR, S390_MXBR, S390_MEEB, S390_MDB },
450         { S390_DEBR, S390_DDBR, S390_DXBR, S390_DEB, S390_DDB },
453 static const struct fp_alu fp_alu1s[2] = {
454         { S390_LCEBR, S390_LCDBR, S390_LCXBR, -1, -1 },
455         { S390_SQEBR, S390_SQDBR, S390_SQXBR, S390_SQEB, S390_SQDB },
458 static const struct fp_alu fp_cmp = {
459         S390_CEBR, S390_CDBR, S390_CXBR, S390_CEB, S390_CDB
462 static uint8_t get_jmp_cond(unsigned cond, bool logical)
464         int8_t c;
465         if (!logical) {
466                 if (unlikely(cond >= n_array_elements(jmp_cond)))
467                         goto invl;
468                 c = jmp_cond[cond];
469         } else {
470                 if (unlikely(cond >= n_array_elements(jmp_cond_logical)))
471                         goto invl;
472                 c = jmp_cond_logical[cond];
473         }
474         if (unlikely(c == -1))
475                 goto invl;
476         return (uint8_t)c;
477 invl:
478         internal(file_line, "get_jmp_cond: invalid %scondition %x", logical ? "logical " : "", cond);
481 static bool attr_w cgen_s390(struct codegen_context *ctx, it code)
483         unsigned sz = code >> 46;
484         if (sz == 0) {
485                 if (unlikely((uint32_t)code))
486                         goto invl;
487                 cgen_two(code >> 32);
488         } else if (sz == 1 || sz == 2) {
489                 if (unlikely((uint16_t)code))
490                         goto invl;
491                 cgen_four(code >> 16);
492         } else if (sz == 3) {
493                 cgen_two(code >> 32);
494                 cgen_four(code);
495         } else {
496 invl:
497                 internal(file_line, "cgen_s390: invalid insn %"PRIxMAX"", (uintmax_t)code);
498         }
499         return true;
502 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)
504         it code;
505         uint8_t b, x;
506         uint8_t *disp;
507         int64_t imm;
508         if (size > OP_SIZE_NATIVE)
509                 goto invl;
510         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
511                 goto invl;
512         if (arg3[0] < 0x10) {
513                 unsigned sz;
514                 bool k = false;
515                 if (size != OP_SIZE_8) {
516                         code = codes->rr;
517                         if (code == (it)-1 || arg1[0] != arg2[0]) {
518                                 code = codes->rrk;
519                                 k = true;
520                         }
521                 } else {
522                         code = codes->rrg;
523                         if (code == (it)-1 || arg1[0] != arg2[0]) {
524                                 code = codes->rrgk;
525                                 k = true;
526                         }
527                 }
528                 sz = code >> 46;
529                 if (k) {
530                         code |= (it)arg1[0] << 20;
531                         code |= (it)arg2[0] << 16;
532                         code |= (it)arg3[0] << 28;
533                 } else if (!sz) {
534                         code |= (it)arg1[0] << 36;
535                         code |= (it)arg3[0] << 32;
536                 } else if (sz == 1 || sz == 2) {
537                         code |= (it)arg1[0] << 20;
538                         code |= (it)arg3[0] << 16;
539                 } else {
540                         goto invl;
541                 }
542                 g(cgen_s390(ctx, code));
543                 return true;
544         }
545         if (unlikely(arg1[0] != arg2[0]))
546                 goto invl;
547         if (arg3[0] == ARG_IMM) {
548                 imm = get_imm(&arg3[1]);
549                 if (codes->neg_imm == 1)
550                         imm = -(uint64_t)imm;
551                 if (imm >= -0x8000 && imm < 0x8000) {
552                         code = size != OP_SIZE_8 ? codes->ri : codes->rig;
553                         if (unlikely(code == (it)-1))
554                                 goto log_op;
555                         code |= (it)arg1[0] << 36;
556                         code |= (it)(imm & 0xffff) << 16;
557                 } else if (imm >= -0x80000000LL && imm < 0x80000000LL) {
558                         code = codes->rig32;
559                         if (unlikely(code == (it)-1))
560                                 goto log_op;
561                         code |= (it)arg1[0] << 36;
562                         code |= (it)(imm & 0xffffffffLL);
563                 } else {
564                         goto log_op;
565                 }
566                 g(cgen_s390(ctx, code));
567                 return true;
568 log_op:
569                 if (codes->neg_imm == 2)
570                         imm = ~imm;
571                 if (!(imm & ~0xffffULL) && codes->rill != (it)-1) {
572                         code = codes->rill;
573                         if (codes->neg_imm == 2)
574                                 imm = ~imm;
575                         code |= (it)(imm & 0xffffULL) << 16;
576                 } else if (!(imm & ~0xffff0000ULL) && codes->rilh != (it)-1) {
577                         code = codes->rilh;
578                         if (codes->neg_imm == 2)
579                                 imm = ~imm;
580                         code |= (it)(imm & 0xffff0000ULL);
581                 } else if (!(imm & ~0xffff00000000ULL) && codes->rihl != (it)-1) {
582                         code = codes->rihl;
583                         if (codes->neg_imm == 2)
584                                 imm = ~imm;
585                         code |= (it)((uint64_t)imm & 0xffff00000000ULL) >> 16;
586                 } else if (!(imm & ~0xffff000000000000ULL) && codes->rihh != (it)-1) {
587                         code = codes->rihh;
588                         if (codes->neg_imm == 2)
589                                 imm = ~imm;
590                         code |= (it)((uint64_t)imm & 0xffff000000000000ULL) >> 32;
591                 } else if (!(imm & ~0xffffffffULL) && codes->rilf != (it)-1) {
592                         code = codes->rilf;
593                         if (codes->neg_imm == 2)
594                                 imm = ~imm;
595                         code |= (it)(imm & 0xffffffffLL);
596                 } else if (!(imm & ~0xffffffff00000000ULL) && codes->rihf != (it)-1) {
597                         code = codes->rihf;
598                         if (codes->neg_imm == 2)
599                                 imm = ~imm;
600                         code |= (it)(((uint64_t)imm & 0xffffffff00000000LL) >> 32);
601                 } else {
602                         goto invl;
603                 }
604                 code |= (it)arg1[0] << 36;
605                 g(cgen_s390(ctx, code));
606                 return true;
607         } else if (arg3[0] == ARG_ADDRESS_0) {
608                 b = 0;
609                 x = 0;
610                 disp = &arg3[1];
611         } else if (arg3[0] == ARG_ADDRESS_1) {
612                 b = arg3[1];
613                 x = 0;
614                 disp = &arg3[2];
615         } else if (arg3[0] == ARG_ADDRESS_2) {
616                 b = arg3[1];
617                 x = arg3[2];
618                 disp = &arg3[3];
619         } else {
620                 goto invl;
621         }
623         imm = get_imm(disp);
624         if (size != OP_SIZE_8) {
625                 if (imm >= 0 && imm < 0x1000 && codes->rx != (it)-1) {
626                         code = codes->rx;
627                         code |= (it)arg1[0] << 36;
628                         code |= (it)x << 32;
629                         code |= (it)b << 28;
630                         code |= (it)(imm & 0xfff) << 16;
631                 } else if (imm >= -0x80000 && imm < 0x80000) {
632                         code = codes->rxy;
633                         goto rxya;
634                 } else {
635                         goto invl;
636                 }
637         } else {
638                 code = codes->rxg;
639                 if (imm >= -0x80000 && imm < 0x80000) {
640 rxya:
641                         code |= (it)arg1[0] << 36;
642                         code |= (it)x << 32;
643                         code |= (it)b << 28;
644                         code |= (it)(imm & 0xfff) << 16;
645                         code |= (it)(imm & 0xff000) >> 4;
646                 } else {
647                         goto invl;
648                 }
650         }
651         g(cgen_s390(ctx, code));
652         return true;
653 invl:
654         internal(file_line, "cgen_rr_rx: invalid arguments %u, %02x, %02x, %02x", size, *arg1, *arg2, *arg3);
655         return false;
658 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)
660         it code;
661         uint8_t b, x;
662         uint8_t *disp;
663         int64_t imm;
664         if (size != OP_SIZE_4 && size != OP_SIZE_8)
665                 goto invl;
666         if (unlikely(!reg_is_fp(arg1[0])))
667                 goto invl;
668         if (arg2[0] == ARG_ADDRESS_0) {
669                 b = 0;
670                 x = 0;
671                 disp = &arg2[1];
672         } else if (arg2[0] == ARG_ADDRESS_1) {
673                 b = arg2[1];
674                 x = 0;
675                 disp = &arg2[2];
676         } else if (arg2[0] == ARG_ADDRESS_2) {
677                 b = arg2[1];
678                 x = arg2[2];
679                 disp = &arg2[3];
680         } else {
681                 goto invl;
682         }
683         imm = get_imm(disp);
684         if (imm >= 0 && imm < 4096) {
685                 code = size == OP_SIZE_4 ? e : d;
686         } else if (imm >= -0x80000 && imm < 0x80000) {
687                 code = size == OP_SIZE_4 ? ey : dy;
688                 code |= (it)(imm & 0xff000) >> 4;
689         } else {
690                 goto invl;
691         }
692         code |= (it)(arg1[0] & 0xf) << 36;
693         code |= (it)x << 32;
694         code |= (it)b << 28;
695         code |= (it)(imm & 0xfff) << 16;
696         g(cgen_s390(ctx, code));
697         return true;
698 invl:
699         internal(file_line, "cgen_fp_mem: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
700         return false;
703 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)
705         it code;
706         uint8_t b, x;
707         uint8_t *disp;
708         int64_t imm;
709         if (size != OP_SIZE_4 && size != OP_SIZE_8 && size != OP_SIZE_16)
710                 goto invl;
711         if (reg_is_fp(arg2[0])) {
712                 code = size == OP_SIZE_4 ? fp_alu->err : size == OP_SIZE_8 ? fp_alu->drr : fp_alu->xrr;
713                 code |= (it)(arg1[0] & 0xf) << 20;
714                 code |= (it)(arg2[0] & 0xf) << 16;
715                 g(cgen_s390(ctx, code));
716                 return true;
717         } else if (arg2[0] == ARG_ADDRESS_0) {
718                 b = 0;
719                 x = 0;
720                 disp = &arg2[1];
721         } else if (arg2[0] == ARG_ADDRESS_1) {
722                 b = arg2[1];
723                 x = 0;
724                 disp = &arg2[2];
725         } else if (arg2[0] == ARG_ADDRESS_2) {
726                 b = arg2[1];
727                 x = arg2[2];
728                 disp = &arg2[3];
729         } else {
730                 goto invl;
731         }
732         imm = get_imm(disp);
733         if (unlikely(imm < 0) || unlikely(imm >= 4096))
734                 goto invl;
735         if (unlikely(size == OP_SIZE_16))
736                 goto invl;
737         code = size == OP_SIZE_4 ? fp_alu->erx : fp_alu->drx;
738         code |= (it)(arg1[0] & 0xf) << 36;
739         code |= (it)x << 32;
740         code |= (it)b << 28;
741         code |= (it)(imm & 0xfff) << 16;
742         g(cgen_s390(ctx, code));
743         return true;
744 invl:
745         internal(file_line, "cgen_fp_op: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
746         return false;
749 static bool attr_w cgen_xi(struct codegen_context *ctx, uint8_t *arg1, uint8_t *arg2, it xi, it xiy)
751         it code;
752         uint8_t b;
753         uint8_t *disp;
754         int64_t val, imm;
755         if (unlikely(arg1[0] == ARG_ADDRESS_0)) {
756                 b = 0;
757                 disp = &arg1[1];
758         } else if (likely(arg1[0] == ARG_ADDRESS_1) && likely(arg2[0] == ARG_IMM)) {
759                 b = arg1[1];
760                 disp = &arg1[2];
761         } else {
762                 goto invl;
763         }
765         imm = get_imm(disp);
766         if (likely(arg2[0] == ARG_IMM)) {
767                 val = get_imm(&arg2[1]);
768         } else {
769                 goto invl;
770         }
772         if (imm >= 0 && imm < 0x1000) {
773                 code = xi;
774                 code |= (it)(imm & 0xfff) << 16;
775         } else if (imm >= -0x80000 && imm < 0x80000) {
776                 code = xiy;
777                 code |= (it)(imm & 0xfff) << 16;
778                 code |= (it)(imm & 0xff000) >> 4;
779         } else {
780                 goto invl;
781         }
783         code |= (it)(val & 0xff) << 32;
784         code |= (it)b << 28;
786         g(cgen_s390(ctx, code));
787         return true;
788 invl:
789         internal(file_line, "cgen_xi: invalid arguments %02x, %02x", *arg1, *arg2);
790         return false;
793 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)
795         it code;
796         int64_t imm;
797         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))
798                 goto invl;
799         imm = get_imm(&arg1[2]);
800         if (size == OP_SIZE_4 && imm >= 0 && imm < 0x1000) {
801                 code = m;
802                 code |= (it)(imm & 0xfff) << 16;
803         } else {
804                 if (size == OP_SIZE_4)
805                         code = my;
806                 else
807                         code = mg;
808                 code |= (it)(imm & 0xfff) << 16;
809                 code |= (it)(imm & 0xff000) >> 4;
810         }
811         code |= (it)r_start << 36;
812         code |= (it)r_end << 32;
813         code |= (it)arg1[1] << 28;
814         g(cgen_s390(ctx, code));
815         return true;
816 invl:
817         internal(file_line, "cgen_lm_stm: invalid arguments %02x", *arg1);
818         return false;
821 static bool attr_w cgen_s390_push_pop(struct codegen_context *ctx, unsigned size, bool push)
823         uint8_t *arg1;
824         arg1 = ctx->code_position;
825         ctx->code_position = arg1 + arg_size(*arg1);
826         if (!push)
827                 g(cgen_lm_stm(ctx, size, R_6, R_15, arg1, S390_LM, S390_LMY, S390_LMG));
828         else
829                 g(cgen_lm_stm(ctx, size, R_6, R_15, arg1, S390_STM, S390_STMY, S390_STMG));
830         return true;
833 static bool attr_w cgen_call_indirect(struct codegen_context *ctx)
835         uint8_t reg = cget_one(ctx);
836         it code = S390_BASR;
837         code |= (it)R_14 << 36;
838         code |= (it)reg << 32;
839         g(cgen_s390(ctx, code));
840         return true;
843 static bool attr_w cgen_branch_imm(struct codegen_context *ctx, uint8_t reg, int64_t imm)
845         it code;
846         code = S390_BRAS;
847         code |= (it)reg << 36;
848         code |= (OP_SIZE_NATIVE == OP_SIZE_4 ? (it)4 : (it)6) << 16;
849         g(cgen_s390(ctx, code));
850         if (OP_SIZE_NATIVE == OP_SIZE_4) {
851                 cgen_four(imm);
852         } else {
853                 cgen_eight(imm);
854         }
855         code = OP_SIZE_NATIVE == OP_SIZE_4 ? S390_L : S390_LG;
856         code |= (it)reg << 36;
857         code |= (it)reg << 28;
858         g(cgen_s390(ctx, code));
859         return true;
862 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
864         uint8_t *arg1 = ctx->code_position;
865         uint8_t *arg2 = arg1 + arg_size(*arg1);
866         ctx->code_position = arg2 + arg_size(*arg2);
867         if (arg1[0] < 0x10) {
868                 if (unlikely(size != OP_SIZE_NATIVE)) {
869                         switch (size) {
870                                 case OP_SIZE_1:
871                                         if (unlikely(!cpu_test_feature(CPU_FEATURE_extended_imm)))
872                                                 goto invl;
873                                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_8_unsigned));
874                                         return true;
875                                 case OP_SIZE_2:
876                                         if (unlikely(!cpu_test_feature(CPU_FEATURE_extended_imm)))
877                                                 goto invl;
878                                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_16_unsigned));
879                                         return true;
880                                 case OP_SIZE_4:
881                                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_32_unsigned));
882                                         return true;
883                                 default:
884                                         goto invl;
885                         }
886                 }
887                 if (!cpu_test_feature(CPU_FEATURE_extended_imm) && arg2[0] == ARG_IMM) {
888                         int64_t imm = get_imm(&arg2[1]);
889                         if (imm < -0x8000 || imm >= 0x8000) {
890                                 g(cgen_branch_imm(ctx, arg1[0], imm));
891                                 return true;
892                         }
893                 }
894                 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_load));
895                 return true;
896         }
897         if (arg1[0] < 0x20) {
898                 if (unlikely(arg2[0] < 0x20))
899                         goto invl;
900                 if (unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
901                         goto invl;
902                 g(cgen_fp_mem(ctx, size, arg1, arg2, S390_LE, S390_LEY, S390_LD, S390_LDY));
903                 return true;
904         }
905         if (arg2[0] < 0x10) {
906                 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));
907                 return true;
908         }
909         if (arg2[0] < 0x20) {
910                 if (unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
911                         goto invl;
912                 g(cgen_fp_mem(ctx, size, arg2, arg1, S390_STE, S390_STEY, S390_STD, S390_STDY));
913                 return true;
914         }
915         if (size == OP_SIZE_1 && arg1[0] == ARG_ADDRESS_1 && arg2[0] == ARG_IMM) {
916                 g(cgen_xi(ctx, arg1, arg2, S390_MVI, S390_MVIY));
917                 return true;
918         }
919 invl:
920         internal(file_line, "cgen_mov: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
921         return false;
924 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
926         uint8_t *arg1, *arg2;
927         if (unlikely(size == OP_SIZE_NATIVE)) {
928                 g(cgen_mov(ctx, size));
929                 return true;
930         }
931         arg1 = ctx->code_position;
932         arg2 = arg1 + arg_size(*arg1);
933         ctx->code_position = arg2 + arg_size(*arg2);
934         switch (size) {
935                 case OP_SIZE_1:
936                         if (arg2[0] >= 0x10 ? !cpu_test_feature(CPU_FEATURE_long_displacement) : !cpu_test_feature(CPU_FEATURE_extended_imm))
937                                 goto invl;
938                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_8));
939                         return true;
940                 case OP_SIZE_2:
941                         if (arg2[0] < 0x10 && !cpu_test_feature(CPU_FEATURE_extended_imm))
942                                 goto invl;
943                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_16));
944                         return true;
945                 case OP_SIZE_4:
946                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_32));
947                         return true;
948                 default:
949                         goto invl;
950         }
951 invl:
952         internal(file_line, "cgen_movsx: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
953         return false;
956 static bool attr_w cgen_cmp(struct codegen_context *ctx, unsigned size, unsigned writes_flags)
958         uint8_t *arg1, *arg2;
959         arg1 = ctx->code_position;
960         arg2 = arg1 + arg_size(*arg1);
961         ctx->code_position = arg2 + arg_size(*arg2);
962         if (writes_flags == 1) {
963                 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_cmp));
964                 return true;
965         } else if (writes_flags == 2) {
966                 if (size == OP_SIZE_1 && arg1[0] == ARG_ADDRESS_1 && arg2[0] == ARG_IMM) {
967                         g(cgen_xi(ctx, arg1, arg2, S390_CLI, S390_CLIY));
968                         return true;
969                 }
970                 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_cmp_log));
971                 return true;
972         }
973         internal(file_line, "cgen_cmp: invalid arguments %u, %02x, %02x, %u", size, *arg1, *arg2, writes_flags);
974         return false;
977 static bool attr_w cgen_test(struct codegen_context *ctx, unsigned size)
979         it code;
980         uint8_t *arg1, *arg2;
981         arg1 = ctx->code_position;
982         arg2 = arg1 + arg_size(*arg1);
983         ctx->code_position = arg2 + arg_size(*arg2);
984         if (likely(arg1[0] < 0x10) && likely(arg2[0] == ARG_IMM)) {
985                 uint16_t m;
986                 int64_t imm = get_imm(&arg2[1]);
987                 if (!(imm & ~0xffffULL)) {
988                         code = S390_TMLL;
989                         m = (uint64_t)imm;
990                 } else if (!(imm & ~0xffff0000ULL)) {
991                         code = S390_TMLH;
992                         m = (uint64_t)imm >> 16;
993                 } else if (!(imm & ~0xffff00000000ULL)) {
994                         code = S390_TMHL;
995                         m = (uint64_t)imm >> 32;
996                 } else if (!(imm & ~0xffff000000000000ULL)) {
997                         code = S390_TMHH;
998                         m = (uint64_t)imm >> 48;
999                 } else {
1000                         goto invl;
1001                 }
1002                 code |= (it)m << 16;
1003                 code |= (it)arg1[0] << 36;
1004                 g(cgen_s390(ctx, code));
1005                 return true;
1006         }
1007         if (arg1[0] < 0x10 && arg2[0] == arg1[0]) {
1008                 if (size == OP_SIZE_4) {
1009                         code = S390_LTR;
1010                         code |= (it)arg1[0] << 36;
1011                         code |= (it)arg1[0] << 32;
1012                 } else if (size == OP_SIZE_8) {
1013                         code = S390_LTGR;
1014                         code |= (it)arg1[0] << 20;
1015                         code |= (it)arg1[0] << 16;
1016                 } else {
1017                         goto invl;
1018                 }
1019                 g(cgen_s390(ctx, code));
1020                 return true;
1021         }
1022 invl:
1023         internal(file_line, "cgen_test: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
1024         return false;
1027 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
1029         uint8_t *arg1, *arg2, *arg3;
1030         arg1 = ctx->code_position;
1031         arg2 = arg1 + arg_size(*arg1);
1032         arg3 = arg2 + arg_size(*arg2);
1033         ctx->code_position = arg3 + arg_size(*arg3);
1034         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
1035                 goto invl;
1036         if (writes_flags == 0) {
1037                 if (unlikely(alu >= n_array_elements(codes_alu_no_flags)))
1038                         goto invl;
1039                 if (unlikely(codes_alu_no_flags[alu].rr == (it)-1) && unlikely(codes_alu_no_flags[alu].rrk == (it)-1))
1040                         goto invl;
1041                 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu_no_flags[alu]));
1042         } else if (writes_flags == 1) {
1043                 if (unlikely(alu >= n_array_elements(codes_alu)))
1044                         goto invl;
1045                 if (unlikely(codes_alu[alu].rr == (it)-1) && unlikely(codes_alu[alu].rrk == (it)-1))
1046                         goto invl;
1047                 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu[alu]));
1048         } else if (writes_flags == 2) {
1049                 if (unlikely(alu >= n_array_elements(codes_alu_log)))
1050                         goto invl;
1051                 if (unlikely(codes_alu_log[alu].rr == (it)-1) && unlikely(codes_alu_log[alu].rrk == (it)-1))
1052                         goto invl;
1053                 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu_log[alu]));
1054         } else {
1055                 goto invl;
1056         }
1057         return true;
1058 invl:
1059         /*debug("%s", da(ctx->fn,function)->function_name);*/
1060         internal(file_line, "cgen_alu: invalid arguments %u, %u, %02x, %02x, %02x", size, alu, *arg1, *arg2, *arg3);
1061         return false;
1064 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
1066         it code;
1067         uint8_t *arg1 = ctx->code_position;
1068         uint8_t *arg2 = arg1 + arg_size(*arg1);
1069         ctx->code_position = arg2 + arg_size(*arg2);
1070         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] != arg1[0]))
1071                 goto invl;
1072         switch (alu) {
1073                 case ALU1_NEG:
1074                         if (unlikely(writes_flags != 1))
1075                                 goto invl;
1076                         if (size == OP_SIZE_4) {
1077                                 code = S390_LCR;
1078                                 code |= (it)arg1[0] << 36;
1079                                 code |= (it)arg2[0] << 32;
1080                         } else if (size == OP_SIZE_8) {
1081                                 code = S390_LCGR;
1082                                 code |= (it)arg1[0] << 20;
1083                                 code |= (it)arg2[0] << 16;
1084                         } else {
1085                                 goto invl;
1086                         }
1087                         break;
1088                 case ALU1_INC:
1089                 case ALU1_DEC:
1090                         if (unlikely(writes_flags != 1))
1091                                 goto invl;
1092                         if (size == OP_SIZE_4) {
1093                                 code = S390_AHI;
1094                         } else if (size == OP_SIZE_8) {
1095                                 code = S390_AGHI;
1096                         } else {
1097                                 goto invl;
1098                         }
1099                         code |= (it)arg1[0] << 36;
1100                         if (alu == ALU1_INC)
1101                                 code |= (it)0x0001 << 16;
1102                         else
1103                                 code |= (it)0xffff << 16;
1104                         break;
1105                 case ALU1_BSWAP:
1106                         if (size == OP_SIZE_4) {
1107                                 code = S390_LRVR;
1108                         } else if (size == OP_SIZE_8) {
1109                                 code = S390_LRVRG;
1110                         } else {
1111                                 goto invl;
1112                         }
1113                         code |= (it)arg1[0] << 20;
1114                         code |= (it)arg2[0] << 16;
1115                         break;
1116                 case ALU1_POPCNT:
1117                         if (size != OP_SIZE_8)
1118                                 goto invl;
1119                         code = S390_POPCNT;
1120                         code |= (it)arg1[0] << 20;
1121                         code |= (it)arg2[0] << 16;
1122                         break;
1123                 default:
1124                         goto invl;
1125         }
1126         g(cgen_s390(ctx, code));
1127         return true;
1128 invl:
1129         internal(file_line, "cgen_alu1: invalid arguments %u, %u, %02x, %02x", size, alu, *arg1, *arg2);
1130         return false;
1133 static bool attr_w cgen_lea3(struct codegen_context *ctx)
1135         it code;
1136         int64_t imm;
1137         uint8_t *arg1, *arg2, *arg3, *arg4;
1138         arg1 = ctx->code_position;
1139         arg2 = arg1 + arg_size(*arg1);
1140         arg3 = arg2 + arg_size(*arg2);
1141         arg4 = arg3 + arg_size(*arg3);
1142         ctx->code_position = arg4 + arg_size(*arg4);
1143         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10) || arg4[0] != ARG_IMM)
1144                 goto invl;
1145         imm = get_imm(&arg4[1]);
1146         if (imm >= 0 && imm < 0x1000) {
1147                 code = S390_LA;
1148         } else {
1149                 code = S390_LAY;
1150                 code |= (it)(imm & 0xff000) >> 4;
1151         }
1152         code |= (it)arg1[0] << 36;
1153         code |= (it)arg2[0] << 32;
1154         code |= (it)arg3[0] << 28;
1155         code |= (it)(imm & 0xfff) << 16;
1156         g(cgen_s390(ctx, code));
1157         return true;
1158 invl:
1159         internal(file_line, "cgen_lea3: invalid arguments %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4);
1160         return false;
1163 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, unsigned alu)
1165         it code;
1166         unsigned sz;
1167         uint8_t *arg1, *arg2, *arg3;
1168         arg1 = ctx->code_position;
1169         arg2 = arg1 + arg_size(*arg1);
1170         arg3 = arg2 + arg_size(*arg2);
1171         ctx->code_position = arg3 + arg_size(*arg3);
1172         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
1173                 goto invl;
1174         if (arg3[0] >= 0x10 && unlikely(arg3[0] != ARG_IMM))
1175                 goto invl;
1177         if (size == OP_SIZE_4 && arg1[0] == arg2[0]) {
1178                 code = rot32[alu];
1179         } else if (size == OP_SIZE_4) {
1180                 code = rot32k[alu];
1181         } else if (size == OP_SIZE_8) {
1182                 code = rot64[alu];
1183         } else {
1184                 goto invl;
1185         }
1186         sz = code >> 46;
1187         if (sz == 1 || sz == 2) {
1188                 code |= (it)arg1[0] << 36;
1189         } else if (sz == 3) {
1190                 code |= (it)arg1[0] << 36;
1191                 code |= (it)arg2[0] << 32;
1192         } else {
1193                 goto invl;
1194         }
1195         if (arg3[0] == ARG_IMM)
1196                 code |= (it)(get_imm(&arg3[1]) & (size == OP_SIZE_4 ? 0x1f : 0x3f)) << 16;
1197         else
1198                 code |= (it)arg3[0] << 28;
1199         g(cgen_s390(ctx, code));
1200         return true;
1201 invl:
1202         internal(file_line, "cgen_rot: invalid arguments %u, %u, %02x, %02x, %02x", size, alu, *arg1, *arg2, *arg3);
1203         return false;
1206 static bool attr_w cgen_mul_l(struct codegen_context *ctx, unsigned size)
1208         it code;
1209         uint8_t *arg1, *arg2, *arg3, *arg4;
1210         arg1 = ctx->code_position;
1211         arg2 = arg1 + arg_size(*arg1);
1212         arg3 = arg2 + arg_size(*arg2);
1213         arg4 = arg3 + arg_size(*arg3);
1214         ctx->code_position = arg4 + arg_size(*arg4);
1215         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10) || unlikely(arg4[0] >= 0x10))
1216                 goto invl;
1217         if (unlikely(arg2[0] & 1) || unlikely(arg1[0] != arg2[0] + 1) || unlikely(arg3[0] != arg1[0]))
1218                 goto invl;
1219         if (size == OP_SIZE_4) {
1220                 code = S390_MR;
1221                 code |= (it)arg2[0] << 36;
1222                 code |= (it)arg4[0] << 32;
1223         } else {
1224                 code = S390_MGRK;
1225                 code |= (it)arg2[0] << 20;
1226                 code |= (it)arg3[0] << 16;
1227                 code |= (it)arg4[0] << 28;
1228         }
1229         g(cgen_s390(ctx, code));
1230         return true;
1231 invl:
1232         internal(file_line, "cgen_mul_l: invalid arguments %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4);
1233         return false;
1236 static bool attr_w cgen_div_l(struct codegen_context *ctx, unsigned size, bool sgn)
1238         it code;
1239         uint8_t *arg1, *arg2, *arg3, *arg4, *arg5;
1240         arg1 = ctx->code_position;
1241         arg2 = arg1 + arg_size(*arg1);
1242         arg3 = arg2 + arg_size(*arg2);
1243         arg4 = arg3 + arg_size(*arg3);
1244         arg5 = arg4 + arg_size(*arg4);
1245         ctx->code_position = arg5 + arg_size(*arg5);
1246         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10) || unlikely(arg4[0] >= 0x10) || unlikely(arg5[0] >= 0x10))
1247                 goto invl;
1248         if (unlikely(arg1[0] & 1) || unlikely(arg2[0] != arg1[0] + 1))
1249                 goto invl;
1250         if (unlikely(arg3[0] != arg1[0]) || unlikely(arg4[0] != arg3[0] + 1))
1251                 goto invl;
1252         if (!sgn) {
1253                 code = size == OP_SIZE_4 ? S390_DLR : S390_DLGR;
1254         } else {
1255                 code = size == OP_SIZE_4 ? S390_DR : S390_DSGR;
1256         }
1257         if (code == S390_DR) {
1258                 code |= (it)arg1[0] << 36;
1259                 code |= (it)arg5[0] << 32;
1260         } else {
1261                 code |= (it)arg1[0] << 20;
1262                 code |= (it)arg5[0] << 16;
1263         }
1264         g(cgen_s390(ctx, code));
1265         return true;
1266 invl:
1267         internal(file_line, "cgen_div_l: invalid arguments %02x, %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4, *arg4);
1268         return false;
1271 static bool attr_w cgen_cmov(struct codegen_context *ctx, unsigned size, unsigned cond, bool logical)
1273         uint8_t *arg1 = ctx->code_position;
1274         uint8_t *arg2 = arg1 + arg_size(*arg1);
1275         uint8_t *arg3 = arg2 + arg_size(*arg2);
1276         ctx->code_position = arg3 + arg_size(*arg3);
1277         if (unlikely(arg1[0] != arg2[0]) || arg1[0] >= 0x10)
1278                 goto invl;
1280         if (arg3[0] < 0x10) {
1281                 it code;
1282                 code = size == OP_SIZE_4 ? S390_LOCR : S390_LOCGR;
1283                 code |= (it)get_jmp_cond(cond, logical) << 28;
1284                 code |= (it)arg1[0] << 20;
1285                 code |= (it)arg3[0] << 16;
1286                 g(cgen_s390(ctx, code));
1287                 return true;
1288         } else if (arg3[0] == ARG_ADDRESS_1) {
1289                 it code;
1290                 int64_t imm;
1291                 code = size == OP_SIZE_4 ? S390_LOC : S390_LOCG;
1292                 code |= (it)get_jmp_cond(cond, logical) << 32;
1293                 code |= (it)arg1[0] << 36;
1294                 code |= (it)arg3[1] << 28;
1295                 imm = get_imm(&arg3[2]);
1296                 if (imm < -0x80000 || imm >= 0x80000)
1297                         goto invl;
1298                 code |= (it)(imm & 0xfff) << 16;
1299                 code |= (it)(imm & 0xff000) >> 4;
1300                 g(cgen_s390(ctx, code));
1301                 return true;
1302         }
1304 invl:
1305         internal(file_line, "cgen_cmov: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1308 static bool attr_w cgen_ldp_stp(struct codegen_context *ctx, unsigned size, bool st)
1310         uint8_t *arg1, *arg2, *arg3;
1311         if (!st) {
1312                 arg2 = ctx->code_position;
1313                 arg3 = arg2 + arg_size(*arg2);
1314                 arg1 = arg3 + arg_size(*arg3);
1315                 ctx->code_position = arg1 + arg_size(*arg1);
1316         } else {
1317                 arg1 = ctx->code_position;
1318                 arg2 = arg1 + arg_size(*arg1);
1319                 arg3 = arg2 + arg_size(*arg2);
1320                 ctx->code_position = arg3 + arg_size(*arg3);
1321         }
1322         if (unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10))
1323                 goto invl;
1324         if (unlikely(arg2[0] != arg3[0] + 1))
1325                 goto invl;
1326         if (!st)
1327                 g(cgen_lm_stm(ctx, size, arg3[0], arg2[0], arg1, S390_LM, S390_LMY, S390_LMG));
1328         else
1329                 g(cgen_lm_stm(ctx, size, arg3[0], arg2[0], arg1, S390_STM, S390_STMY, S390_STMG));
1330         return true;
1331 invl:
1332         internal(file_line, "cgen_ldp_stp: invalid arguments %u, %02x, %02x, %02x", size, *arg1, *arg2, *arg3);
1333         return false;
1336 static bool attr_w cgen_ic(struct codegen_context *ctx)
1338         uint8_t *arg1, *arg2, *arg3;
1339         arg1 = ctx->code_position;
1340         arg2 = arg1 + arg_size(*arg1);
1341         arg3 = arg2 + arg_size(*arg2);
1342         ctx->code_position = arg3 + arg_size(*arg3);
1343         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] != arg1[0]))
1344                 goto invl;
1345         g(cgen_rr_rx(ctx, OP_SIZE_4, arg1, arg2, arg3, &codes_ic));
1346         return true;
1347 invl:
1348         internal(file_line, "cgen_ic: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1349         return false;
1352 static bool attr_w cgen_mov_mask(struct codegen_context *ctx)
1354         it code;
1355         int64_t imm;
1356         uint8_t *arg1, *arg2, *arg3;
1357         arg1 = ctx->code_position;
1358         arg2 = arg1 + arg_size(*arg1);
1359         arg3 = arg2 + arg_size(*arg2);
1360         ctx->code_position = arg3 + arg_size(*arg3);
1361         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] != arg1[0]) || unlikely(arg3[0] != ARG_IMM))
1362                 goto invl;
1363         imm = get_imm(&arg3[1]);
1364         code = S390_IIHF;
1365         code |= (it)arg1[1] << 36;
1366         code |= (it)(imm & 0xffffffffLL);
1367         g(cgen_s390(ctx, code));
1368         return true;
1369 invl:
1370         internal(file_line, "cgen_mov_mask: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1371         return false;
1374 static bool attr_w cgen_memcpy(struct codegen_context *ctx)
1376         it code;
1377         int64_t disp_dest, disp_src, len;
1378         uint8_t *arg1, *arg2, *arg3;
1379         arg1 = ctx->code_position;
1380         arg2 = arg1 + arg_size(*arg1);
1381         arg3 = arg2 + arg_size(*arg2);
1382         ctx->code_position = arg3 + arg_size(*arg3);
1383         if (unlikely(arg1[0] != ARG_ADDRESS_1) || unlikely(arg2[0] != ARG_ADDRESS_1) || unlikely(arg3[0] != ARG_IMM))
1384                 goto invl;
1385         disp_dest = get_imm(&arg1[2]);
1386         disp_src = get_imm(&arg2[2]);
1387         len = get_imm(&arg3[1]);
1388         code = S390_MVC;
1389         code |= (it)((len - 1) & 0xff) << 32;
1390         code |= (it)arg1[1] << 28;
1391         code |= (it)(disp_dest & 0xfff) << 16;
1392         code |= (it)arg2[1] << 12;
1393         code |= (it)(disp_src & 0xfff) << 0;
1394         g(cgen_s390(ctx, code));
1395         return true;
1396 invl:
1397         internal(file_line, "cgen_memcpy: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1398         return false;
1401 static bool attr_w cgen_fp_cmp(struct codegen_context *ctx, unsigned size)
1403         uint8_t *arg1 = ctx->code_position;
1404         uint8_t *arg2 = arg1 + arg_size(*arg1);
1405         ctx->code_position = arg2 + arg_size(*arg2);
1406         if (unlikely(!reg_is_fp(arg1[0])))
1407                 goto invl;
1408         g(cgen_fp_op(ctx, size, arg1, arg2, &fp_cmp));
1409         return true;
1410 invl:
1411         internal(file_line, "cgen_fp_cmp: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
1412         return false;
1415 static bool attr_w cgen_fp_alu(struct codegen_context *ctx, unsigned size, unsigned aux)
1417         uint8_t *arg1 = ctx->code_position;
1418         uint8_t *arg2 = arg1 + arg_size(*arg1);
1419         uint8_t *arg3 = arg2 + arg_size(*arg2);
1420         ctx->code_position = arg3 + arg_size(*arg3);
1421         if (unlikely(!reg_is_fp(arg1[0])) || unlikely(arg1[0] != arg2[0]))
1422                 goto invl;
1423         g(cgen_fp_op(ctx, size, arg1, arg3, &fp_alus[aux]));
1424         return true;
1425 invl:
1426         internal(file_line, "cgen_fp_alu: invalid arguments %u, %u, %02x, %02x, %02x", size, aux, *arg1, *arg2, *arg3);
1427         return false;
1430 static bool attr_w cgen_fp_alu1(struct codegen_context *ctx, unsigned size, unsigned aux)
1432         uint8_t *arg1 = ctx->code_position;
1433         uint8_t *arg2 = arg1 + arg_size(*arg1);
1434         ctx->code_position = arg2 + arg_size(*arg2);
1435         if (unlikely(!reg_is_fp(arg1[0])))
1436                 goto invl;
1437         g(cgen_fp_op(ctx, size, arg1, arg2, &fp_alu1s[aux]));
1438         return true;
1439 invl:
1440         internal(file_line, "cgen_fp_alu1: invalid arguments %u, %u, %02x, %02x", size, aux, *arg1, *arg2);
1441         return false;
1444 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1446         it code;
1447         uint8_t *arg1 = ctx->code_position;
1448         uint8_t *arg2 = arg1 + arg_size(*arg1);
1449         ctx->code_position = arg2 + arg_size(*arg2);
1450         if (unlikely(arg1[0] >= 0x10) || unlikely(!reg_is_fp(arg2[0])))
1451                 goto invl;
1452         switch (fp_op_size) {
1453                 case OP_SIZE_4:
1454                         code = int_op_size == OP_SIZE_4 ? S390_CFEBR : S390_CGEBR;
1455                         break;
1456                 case OP_SIZE_8:
1457                         code = int_op_size == OP_SIZE_4 ? S390_CFDBR : S390_CGDBR;
1458                         break;
1459                 case OP_SIZE_16:
1460                         code = int_op_size == OP_SIZE_4 ? S390_CFXBR : S390_CGXBR;
1461                         break;
1462                 default:
1463                         goto invl;
1464         }
1465         code |= (it)5 << 28;
1466         code |= (it)arg1[0] << 20;
1467         code |= (it)(arg2[0] & 0xf) << 16;
1468         g(cgen_s390(ctx, code));
1469         return true;
1470 invl:
1471         internal(file_line, "cgen_fp_to_int: invalid arguments %u, %u, %02x, %02x", int_op_size, fp_op_size, *arg1, *arg2);
1472         return false;
1475 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1477         it code;
1478         uint8_t *arg1 = ctx->code_position;
1479         uint8_t *arg2 = arg1 + arg_size(*arg1);
1480         ctx->code_position = arg2 + arg_size(*arg2);
1481         if (unlikely(!reg_is_fp(arg1[0])) || unlikely(arg2[0] >= 0x10))
1482                 goto invl;
1483         switch (fp_op_size) {
1484                 case OP_SIZE_4:
1485                         code = int_op_size == OP_SIZE_4 ? S390_CEFBR : S390_CEGBR;
1486                         break;
1487                 case OP_SIZE_8:
1488                         code = int_op_size == OP_SIZE_4 ? S390_CDFBR : S390_CDGBR;
1489                         break;
1490                 case OP_SIZE_16:
1491                         code = int_op_size == OP_SIZE_4 ? S390_CXFBR : S390_CXGBR;
1492                         break;
1493                 default:
1494                         goto invl;
1495         }
1496         code |= (it)(arg1[0] & 0xf) << 20;
1497         code |= (it)arg2[0] << 16;
1498         g(cgen_s390(ctx, code));
1499         return true;
1500 invl:
1501         internal(file_line, "cgen_fp_from_int: invalid arguments %u, %u, %02x, %02x", int_op_size, fp_op_size, *arg1, *arg2);
1502         return false;
1505 static bool attr_w cgen_jmp_cond(struct codegen_context *ctx, bool lng, unsigned aux, bool logical)
1507         it code;
1508         if (!lng) {
1509                 g(add_relocation(ctx, JMP_SHORTEST, 0, NULL));
1510                 code = S390_BRC;
1511         } else if (USE_BRCL) {
1512                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1513                 code = S390_BRCL;
1514         } else {
1515                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1516                 code = S390_BRAS;
1517                 code |= (it)R_OFFSET_IMM << 36;
1518                 code |= (it)4 << 16;
1519                 g(cgen_s390(ctx, code));
1520                 cgen_four(0);
1521 #if defined(ARCH_S390_32)
1522                 code = S390_L;
1523 #else
1524                 code = S390_LGF;
1525 #endif
1526                 code |= (it)R_CONST_IMM << 36;
1527                 code |= (it)R_OFFSET_IMM << 28;
1528                 g(cgen_s390(ctx, code));
1529                 code = S390_LA;
1530                 code |= (it)R_OFFSET_IMM << 36;
1531                 code |= (it)R_OFFSET_IMM << 32;
1532                 code |= (it)R_CONST_IMM << 28;
1533                 g(cgen_s390(ctx, code));
1534                 code = S390_BCR;
1535                 code |= (it)R_OFFSET_IMM << 32;
1536                 code |= (it)get_jmp_cond(aux, logical) << 36;
1537                 g(cgen_s390(ctx, code));
1538                 return true;
1539         }
1540         code |= (it)get_jmp_cond(aux, logical) << 36;
1541         g(cgen_s390(ctx, code));
1542         return true;
1545 static bool attr_w cgen_jmp_indirect(struct codegen_context *ctx)
1547         uint8_t reg = cget_one(ctx);
1548         it code = S390_BCR;
1549         code |= (it)(S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ) << 36;
1550         code |= (it)reg << 32;
1551         g(cgen_s390(ctx, code));
1552         return true;
1555 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1557         int64_t offs = ((int64_t)ctx->label_to_pos[reloc->label_id] - (int64_t)(reloc->position)) / 2;
1558         switch (reloc->length) {
1559                 case JMP_SHORTEST: {
1560                         int16_t i16;
1561                         if (unlikely(offs < -0x8000) || unlikely(offs >= 0x8000))
1562                                 return false;
1563                         i16 = offs;
1564                         memcpy(ctx->mcode + reloc->position + 2, &i16, 2);
1565                         return true;
1566                 }
1567                 case JMP_SHORT: {
1568                         int32_t i32;
1569                         if (USE_BRCL) {
1570                                 if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
1571                                         return false;
1572                                 i32 = offs;
1573                                 memcpy(ctx->mcode + reloc->position + 2, &i32, 4);
1574                                 return true;
1575                         } else {
1576                                 offs *= 2;
1577                                 offs -= 4;
1578                                 if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
1579                                         return false;
1580                                 i32 = offs;
1581                                 memcpy(ctx->mcode + reloc->position + 4, &i32, 4);
1582                                 return true;
1583                         }
1584                 }
1585                 default: {
1586                         internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1587                         return false;
1588                 }
1589         }
1592 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1594         /*debug("insn: %08x", insn);*/
1595         switch (insn_opcode(insn)) {
1596                 case INSN_ENTRY:
1597                         g(cgen_entry(ctx));
1598                         return true;
1599                 case INSN_AFTER_ENTRY:
1600                         g(cgen_after_entry(ctx));
1601                         return true;
1602                 case INSN_LABEL:
1603                         g(cgen_label(ctx));
1604                         return true;
1605                 case INSN_RET:
1606                         g(cgen_s390(ctx, S390_BCR | ((it)(S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ) << 36) | ((it)R_14 << 32)));
1607                         return true;
1608                 case INSN_S390_PUSH:
1609                         g(cgen_s390_push_pop(ctx, insn_op_size(insn), true));
1610                         return true;
1611                 case INSN_S390_POP:
1612                         g(cgen_s390_push_pop(ctx, insn_op_size(insn), false));
1613                         return true;
1614                 case INSN_CALL_INDIRECT:
1615                         g(cgen_call_indirect(ctx));
1616                         return true;
1617                 case INSN_MOV:
1618                         g(cgen_mov(ctx, insn_op_size(insn)));
1619                         return true;
1620                 case INSN_MOVSX:
1621                         g(cgen_movsx(ctx, insn_op_size(insn)));
1622                         return true;
1623                 case INSN_CMP:
1624                         g(cgen_cmp(ctx, insn_op_size(insn), insn_writes_flags(insn)));
1625                         return true;
1626                 case INSN_TEST:
1627                         if (unlikely(!insn_writes_flags(insn)))
1628                                 goto invalid_insn;
1629                         g(cgen_test(ctx, insn_op_size(insn)));
1630                         return true;
1631                 case INSN_ALU:
1632                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1633                                 goto invalid_insn;
1634                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1635                         return true;
1636                 case INSN_ALU_PARTIAL:
1637                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1638                                 goto invalid_insn;
1639                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1640                         return true;
1641                 case INSN_ALU1:
1642                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1643                                 goto invalid_insn;
1644                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1645                         return true;
1646                 case INSN_ALU1_PARTIAL:
1647                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1648                                 goto invalid_insn;
1649                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1650                         return true;
1651                 case INSN_LEA3:
1652                         if (unlikely(insn_op_size(insn) != OP_SIZE_ADDRESS))
1653                                 goto invalid_insn;
1654                         if (unlikely(insn_aux(insn) != 0))
1655                                 goto invalid_insn;
1656                         g(cgen_lea3(ctx));
1657                         return true;
1658                 case INSN_ROT:
1659                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1660                                 goto invalid_insn;
1661                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1662                         return true;
1663                 case INSN_ROT_PARTIAL:
1664                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1665                                 goto invalid_insn;
1666                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1667                         return true;
1668                 case INSN_MUL_L:
1669                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1670                                 goto invalid_insn;
1671                         g(cgen_mul_l(ctx, insn_op_size(insn)));
1672                         return true;
1673                 case INSN_DIV_L:
1674                         g(cgen_div_l(ctx, insn_op_size(insn), insn_aux(insn)));
1675                         return true;
1676                 case INSN_CMOV:
1677                 case INSN_CMOV_XCC:
1678                         if (unlikely(!cpu_test_feature(CPU_FEATURE_misc_45)))
1679                                 goto invalid_insn;
1680                         g(cgen_cmov(ctx, insn_op_size(insn), insn_aux(insn), insn_opcode(insn) == INSN_CMOV_XCC));
1681                         return true;
1682                 case INSN_STP:
1683                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1684                                 goto invalid_insn;
1685                         g(cgen_ldp_stp(ctx, insn_op_size(insn), true));
1686                         return true;
1687                 case INSN_LDP:
1688                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1689                                 goto invalid_insn;
1690                         g(cgen_ldp_stp(ctx, insn_op_size(insn), false));
1691                         return true;
1692                 case INSN_MOV_MASK:
1693                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1694                                 goto invalid_insn;
1695                         if (insn_aux(insn) == MOV_MASK_0_8) {
1696                                 g(cgen_ic(ctx));
1697                         } else if (insn_aux(insn) == MOV_MASK_32_64) {
1698                                 g(cgen_mov_mask(ctx));
1699                         } else {
1700                                 goto invalid_insn;
1701                         }
1702                         return true;
1703                 case INSN_MEMCPY:
1704                         g(cgen_memcpy(ctx));
1705                         return true;
1706                 case INSN_FP_CMP:
1707                         g(cgen_fp_cmp(ctx, insn_op_size(insn)));
1708                         return true;
1709                 case INSN_FP_ALU:
1710                         g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1711                         return true;
1712                 case INSN_FP_ALU1:
1713                         g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1714                         return true;
1715                 case INSN_FP_TO_INT32:
1716                         g(cgen_fp_to_int(ctx, OP_SIZE_4, insn_op_size(insn)));
1717                         return true;
1718                 case INSN_FP_TO_INT64:
1719                         g(cgen_fp_to_int(ctx, OP_SIZE_8, insn_op_size(insn)));
1720                         return true;
1721                 case INSN_FP_FROM_INT32:
1722                         g(cgen_fp_from_int(ctx, OP_SIZE_4, insn_op_size(insn)));
1723                         return true;
1724                 case INSN_FP_FROM_INT64:
1725                         g(cgen_fp_from_int(ctx, OP_SIZE_8, insn_op_size(insn)));
1726                         return true;
1727                 case INSN_JMP:
1728                         g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, COND_ALWAYS, false));
1729                         return true;
1730                 case INSN_JMP_COND:
1731                         g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, insn_aux(insn), false));
1732                         return true;
1733                 case INSN_JMP_COND_LOGICAL:
1734                         g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, insn_aux(insn), true));
1735                         return true;
1736                 case INSN_JMP_INDIRECT:
1737                         g(cgen_jmp_indirect(ctx));
1738                         return true;
1739                 default:
1740                 invalid_insn:
1741                         internal(file_line, "cgen_insn: invalid insn %08x", insn);
1742                         return false;
1743         }