codegen: introduce cg-spill.inc
[ajla.git] / c2-s390.inc
blob4b36c8c128f56a7bb5fecc6d4f62c10d4ba104be
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_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
309 struct codes {
310         it rr;
311         it rrk;
312         it rx;
313         it rxy;
314         it rrg;
315         it rrgk;
316         it rxg;
317         it ri;
318         it rig;
319         it rig32;
320         it rill;
321         it rilh;
322         it rihl;
323         it rihh;
324         it rilf;
325         it rihf;
326         int neg_imm;
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,
395         S390_SLA,
398 static const it rot32k[9] = {
399         S390_RLL, -1, -1, -1,
400         S390_SLLK, S390_SRLK, -1, S390_SRAK,
401         S390_SLAK,
404 static const it rot64[9] = {
405         S390_RLLG, -1, -1, -1,
406         S390_SLLG, S390_SRLG, -1, S390_SRAG,
407         S390_SLAG,
410 static const int8_t jmp_cond[0x30] = {
411         S390_BRC_OVF,                   S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ,
412         -1,                             -1,
413         S390_BRC_EQ,                    S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_OVF,
414         -1,                             -1,
415         -1,                             -1,
416         -1,                             -1,
417         S390_BRC_LESS,                  S390_BRC_GREATER | S390_BRC_EQ,
418         S390_BRC_LESS | S390_BRC_EQ,    S390_BRC_GREATER,
420         -1,                             -1,
421         S390_BRC_OVF | S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ, -1,
422         -1,                             -1,
423         -1,                             -1,
424         -1,                             -1,
425         -1,                             -1,
426         -1,                             -1,
427         -1,                             -1,
429         -1,                             -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,
433         -1,                             -1,
434         S390_BRC_OVF,                   S390_BRC_GREATER | S390_BRC_LESS | S390_BRC_EQ,
435         -1,                             -1,
436         -1,                             -1,
439 static const int8_t jmp_cond_logical[0x8] = {
440         -1,                             -1,
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,
446 struct fp_alu {
447         it err;
448         it drr;
449         it xrr;
450         it erx;
451         it drx;
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)
480         int8_t c;
481         if (!logical) {
482                 if (unlikely(cond >= n_array_elements(jmp_cond)))
483                         goto invl;
484                 c = jmp_cond[cond];
485         } else {
486                 if (unlikely(cond >= n_array_elements(jmp_cond_logical)))
487                         goto invl;
488                 c = jmp_cond_logical[cond];
489         }
490         if (unlikely(c == -1))
491                 goto invl;
492         return (uint8_t)c;
493 invl:
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;
500         if (sz == 0) {
501                 if (unlikely((uint32_t)code))
502                         goto invl;
503                 cgen_two(code >> 32);
504         } else if (sz == 1 || sz == 2) {
505                 if (unlikely((uint16_t)code))
506                         goto invl;
507                 cgen_four(code >> 16);
508         } else if (sz == 3) {
509                 cgen_two(code >> 32);
510                 cgen_four(code);
511         } else {
512 invl:
513                 internal(file_line, "cgen_s390: invalid insn %"PRIxMAX"", (uintmax_t)code);
514         }
515         return true;
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)
520         it code;
521         uint8_t b, x;
522         uint8_t *disp;
523         int64_t imm;
524         if (size > OP_SIZE_NATIVE)
525                 goto invl;
526         if (unlikely(arg1[0] >= 0x10) || unlikely(arg2[0] >= 0x10))
527                 goto invl;
528         if (arg3[0] < 0x10) {
529                 unsigned sz;
530                 bool k = false;
531                 if (size != OP_SIZE_8) {
532                         code = codes->rr;
533                         if (code == (it)-1 || arg1[0] != arg2[0]) {
534                                 code = codes->rrk;
535                                 k = true;
536                         }
537                 } else {
538                         code = codes->rrg;
539                         if (code == (it)-1 || arg1[0] != arg2[0]) {
540                                 code = codes->rrgk;
541                                 k = true;
542                         }
543                 }
544                 sz = code >> 46;
545                 if (k) {
546                         code |= (it)arg1[0] << 20;
547                         code |= (it)arg2[0] << 16;
548                         code |= (it)arg3[0] << 28;
549                 } else if (!sz) {
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;
555                 } else {
556                         goto invl;
557                 }
558                 g(cgen_s390(ctx, code));
559                 return true;
560         }
561         if (unlikely(arg1[0] != arg2[0]))
562                 goto invl;
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))
570                                 goto log_op;
571                         code |= (it)arg1[0] << 36;
572                         code |= (it)(imm & 0xffff) << 16;
573                 } else if (imm >= -0x80000000LL && imm < 0x80000000LL) {
574                         code = codes->rig32;
575                         if (unlikely(code == (it)-1))
576                                 goto log_op;
577                         code |= (it)arg1[0] << 36;
578                         code |= (it)(imm & 0xffffffffLL);
579                 } else {
580                         goto log_op;
581                 }
582                 g(cgen_s390(ctx, code));
583                 return true;
584 log_op:
585                 if (codes->neg_imm == 2)
586                         imm = ~imm;
587                 if (!(imm & ~0xffffULL) && codes->rill != (it)-1) {
588                         code = codes->rill;
589                         if (codes->neg_imm == 2)
590                                 imm = ~imm;
591                         code |= (it)(imm & 0xffffULL) << 16;
592                 } else if (!(imm & ~0xffff0000ULL) && codes->rilh != (it)-1) {
593                         code = codes->rilh;
594                         if (codes->neg_imm == 2)
595                                 imm = ~imm;
596                         code |= (it)(imm & 0xffff0000ULL);
597                 } else if (!(imm & ~0xffff00000000ULL) && codes->rihl != (it)-1) {
598                         code = codes->rihl;
599                         if (codes->neg_imm == 2)
600                                 imm = ~imm;
601                         code |= (it)((uint64_t)imm & 0xffff00000000ULL) >> 16;
602                 } else if (!(imm & ~0xffff000000000000ULL) && codes->rihh != (it)-1) {
603                         code = codes->rihh;
604                         if (codes->neg_imm == 2)
605                                 imm = ~imm;
606                         code |= (it)((uint64_t)imm & 0xffff000000000000ULL) >> 32;
607                 } else if (!(imm & ~0xffffffffULL) && codes->rilf != (it)-1) {
608                         code = codes->rilf;
609                         if (codes->neg_imm == 2)
610                                 imm = ~imm;
611                         code |= (it)(imm & 0xffffffffLL);
612                 } else if (!(imm & ~0xffffffff00000000ULL) && codes->rihf != (it)-1) {
613                         code = codes->rihf;
614                         if (codes->neg_imm == 2)
615                                 imm = ~imm;
616                         code |= (it)(((uint64_t)imm & 0xffffffff00000000LL) >> 32);
617                 } else {
618                         goto invl;
619                 }
620                 code |= (it)arg1[0] << 36;
621                 g(cgen_s390(ctx, code));
622                 return true;
623         } else if (arg3[0] == ARG_ADDRESS_0) {
624                 b = 0;
625                 x = 0;
626                 disp = &arg3[1];
627         } else if (arg3[0] == ARG_ADDRESS_1) {
628                 b = arg3[1];
629                 x = 0;
630                 disp = &arg3[2];
631         } else if (arg3[0] == ARG_ADDRESS_2) {
632                 b = arg3[1];
633                 x = arg3[2];
634                 disp = &arg3[3];
635         } else {
636                 goto invl;
637         }
639         imm = get_imm(disp);
640         if (size != OP_SIZE_8) {
641                 if (imm >= 0 && imm < 0x1000 && codes->rx != (it)-1) {
642                         code = codes->rx;
643                         code |= (it)arg1[0] << 36;
644                         code |= (it)x << 32;
645                         code |= (it)b << 28;
646                         code |= (it)(imm & 0xfff) << 16;
647                 } else if (imm >= -0x80000 && imm < 0x80000) {
648                         code = codes->rxy;
649                         goto rxya;
650                 } else {
651                         goto invl;
652                 }
653         } else {
654                 code = codes->rxg;
655                 if (imm >= -0x80000 && imm < 0x80000) {
656 rxya:
657                         code |= (it)arg1[0] << 36;
658                         code |= (it)x << 32;
659                         code |= (it)b << 28;
660                         code |= (it)(imm & 0xfff) << 16;
661                         code |= (it)(imm & 0xff000) >> 4;
662                 } else {
663                         goto invl;
664                 }
666         }
667         g(cgen_s390(ctx, code));
668         return true;
669 invl:
670         internal(file_line, "cgen_rr_rx: invalid arguments %u, %02x, %02x, %02x", size, *arg1, *arg2, *arg3);
671         return false;
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)
676         it code;
677         uint8_t b, x;
678         uint8_t *disp;
679         int64_t imm;
680         if (size != OP_SIZE_4 && size != OP_SIZE_8)
681                 goto invl;
682         if (unlikely(!reg_is_fp(arg1[0])))
683                 goto invl;
684         if (arg2[0] == ARG_ADDRESS_0) {
685                 b = 0;
686                 x = 0;
687                 disp = &arg2[1];
688         } else if (arg2[0] == ARG_ADDRESS_1) {
689                 b = arg2[1];
690                 x = 0;
691                 disp = &arg2[2];
692         } else if (arg2[0] == ARG_ADDRESS_2) {
693                 b = arg2[1];
694                 x = arg2[2];
695                 disp = &arg2[3];
696         } else {
697                 goto invl;
698         }
699         imm = get_imm(disp);
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;
705         } else {
706                 goto invl;
707         }
708         code |= (it)(arg1[0] & 0xf) << 36;
709         code |= (it)x << 32;
710         code |= (it)b << 28;
711         code |= (it)(imm & 0xfff) << 16;
712         g(cgen_s390(ctx, code));
713         return true;
714 invl:
715         internal(file_line, "cgen_fp_mem: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
716         return false;
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)
721         it code;
722         uint8_t b, x;
723         uint8_t *disp;
724         int64_t imm;
725         if (size != OP_SIZE_4 && size != OP_SIZE_8 && size != OP_SIZE_16)
726                 goto invl;
727         if (reg_is_fp(arg2[0])) {
728                 unsigned sz;
729                 code = size == OP_SIZE_4 ? fp_alu->err : size == OP_SIZE_8 ? fp_alu->drr : fp_alu->xrr;
730                 sz = code >> 46;
731                 if (!sz) {
732                         code |= (it)(arg1[0] & 0xf) << 36;
733                         code |= (it)(arg2[0] & 0xf) << 32;
734                 } else {
735                         code |= (it)(arg1[0] & 0xf) << 20;
736                         code |= (it)(arg2[0] & 0xf) << 16;
737                 }
738                 g(cgen_s390(ctx, code));
739                 return true;
740         } else if (arg2[0] == ARG_ADDRESS_0) {
741                 b = 0;
742                 x = 0;
743                 disp = &arg2[1];
744         } else if (arg2[0] == ARG_ADDRESS_1) {
745                 b = arg2[1];
746                 x = 0;
747                 disp = &arg2[2];
748         } else if (arg2[0] == ARG_ADDRESS_2) {
749                 b = arg2[1];
750                 x = arg2[2];
751                 disp = &arg2[3];
752         } else {
753                 goto invl;
754         }
755         imm = get_imm(disp);
756         if (unlikely(imm < 0) || unlikely(imm >= 4096))
757                 goto invl;
758         if (unlikely(size == OP_SIZE_16))
759                 goto invl;
760         code = size == OP_SIZE_4 ? fp_alu->erx : fp_alu->drx;
761         code |= (it)(arg1[0] & 0xf) << 36;
762         code |= (it)x << 32;
763         code |= (it)b << 28;
764         code |= (it)(imm & 0xfff) << 16;
765         g(cgen_s390(ctx, code));
766         return true;
767 invl:
768         internal(file_line, "cgen_fp_op: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
769         return false;
772 static bool attr_w cgen_xi(struct codegen_context *ctx, uint8_t *arg1, uint8_t *arg2, it xi, it xiy)
774         it code;
775         uint8_t b;
776         uint8_t *disp;
777         int64_t val, imm;
778         if (unlikely(arg1[0] == ARG_ADDRESS_0)) {
779                 b = 0;
780                 disp = &arg1[1];
781         } else if (likely(arg1[0] == ARG_ADDRESS_1) && likely(arg2[0] == ARG_IMM)) {
782                 b = arg1[1];
783                 disp = &arg1[2];
784         } else {
785                 goto invl;
786         }
788         imm = get_imm(disp);
789         if (likely(arg2[0] == ARG_IMM)) {
790                 val = get_imm(&arg2[1]);
791         } else {
792                 goto invl;
793         }
795         if (imm >= 0 && imm < 0x1000) {
796                 code = xi;
797                 code |= (it)(imm & 0xfff) << 16;
798         } else if (imm >= -0x80000 && imm < 0x80000) {
799                 code = xiy;
800                 code |= (it)(imm & 0xfff) << 16;
801                 code |= (it)(imm & 0xff000) >> 4;
802         } else {
803                 goto invl;
804         }
806         code |= (it)(val & 0xff) << 32;
807         code |= (it)b << 28;
809         g(cgen_s390(ctx, code));
810         return true;
811 invl:
812         internal(file_line, "cgen_xi: invalid arguments %02x, %02x", *arg1, *arg2);
813         return false;
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)
818         it code;
819         int64_t imm;
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))
821                 goto invl;
822         imm = get_imm(&arg1[2]);
823         if (size == OP_SIZE_4 && imm >= 0 && imm < 0x1000) {
824                 code = m;
825                 code |= (it)(imm & 0xfff) << 16;
826         } else {
827                 if (size == OP_SIZE_4)
828                         code = my;
829                 else
830                         code = mg;
831                 code |= (it)(imm & 0xfff) << 16;
832                 code |= (it)(imm & 0xff000) >> 4;
833         }
834         code |= (it)r_start << 36;
835         code |= (it)r_end << 32;
836         code |= (it)arg1[1] << 28;
837         g(cgen_s390(ctx, code));
838         return true;
839 invl:
840         internal(file_line, "cgen_lm_stm: invalid arguments %02x", *arg1);
841         return false;
844 static bool attr_w cgen_s390_push_pop(struct codegen_context *ctx, unsigned size, bool push)
846         uint8_t *arg1;
847         arg1 = ctx->code_position;
848         ctx->code_position = arg1 + arg_size(*arg1);
849         if (!push)
850                 g(cgen_lm_stm(ctx, size, R_6, R_15, arg1, S390_LM, S390_LMY, S390_LMG));
851         else
852                 g(cgen_lm_stm(ctx, size, R_6, R_15, arg1, S390_STM, S390_STMY, S390_STMG));
853         return true;
856 static bool attr_w cgen_call_indirect(struct codegen_context *ctx)
858         uint8_t reg = cget_one(ctx);
859         it code = S390_BASR;
860         code |= (it)R_14 << 36;
861         code |= (it)reg << 32;
862         g(cgen_s390(ctx, code));
863         return true;
866 static bool attr_w cgen_branch_imm(struct codegen_context *ctx, uint8_t reg, int64_t imm)
868         it code;
869         code = S390_BRAS;
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) {
874                 cgen_four(imm);
875         } else {
876                 cgen_eight(imm);
877         }
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));
882         return true;
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)) {
892                         switch (size) {
893                                 case OP_SIZE_1:
894                                         if (unlikely(!cpu_test_feature(CPU_FEATURE_extended_imm)))
895                                                 goto invl;
896                                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_8_unsigned));
897                                         return true;
898                                 case OP_SIZE_2:
899                                         if (unlikely(!cpu_test_feature(CPU_FEATURE_extended_imm)))
900                                                 goto invl;
901                                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_16_unsigned));
902                                         return true;
903                                 case OP_SIZE_4:
904                                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_32_unsigned));
905                                         return true;
906                                 default:
907                                         goto invl;
908                         }
909                 }
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));
914                                 return true;
915                         }
916                 }
917                 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_load));
918                 return true;
919         }
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));
923                         return true;
924                 }
925                 if (unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
926                         goto invl;
927                 g(cgen_fp_mem(ctx, size, arg1, arg2, S390_LE, S390_LEY, S390_LD, S390_LDY));
928                 return true;
929         }
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));
932                 return true;
933         }
934         if (reg_is_fp(arg2[0])) {
935                 if (unlikely(size < OP_SIZE_4) || unlikely(size > OP_SIZE_8))
936                         goto invl;
937                 g(cgen_fp_mem(ctx, size, arg2, arg1, S390_STE, S390_STEY, S390_STD, S390_STDY));
938                 return true;
939         }
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));
942                 return true;
943         }
944 invl:
945         internal(file_line, "cgen_mov: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
946         return false;
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));
954                 return true;
955         }
956         arg1 = ctx->code_position;
957         arg2 = arg1 + arg_size(*arg1);
958         ctx->code_position = arg2 + arg_size(*arg2);
959         switch (size) {
960                 case OP_SIZE_1:
961                         if (arg2[0] >= 0x10 ? !cpu_test_feature(CPU_FEATURE_long_displacement) : !cpu_test_feature(CPU_FEATURE_extended_imm))
962                                 goto invl;
963                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_8));
964                         return true;
965                 case OP_SIZE_2:
966                         if (arg2[0] < 0x10 && !cpu_test_feature(CPU_FEATURE_extended_imm))
967                                 goto invl;
968                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_16));
969                         return true;
970                 case OP_SIZE_4:
971                         g(cgen_rr_rx(ctx, OP_SIZE_NATIVE, arg1, arg1, arg2, &codes_load_32));
972                         return true;
973                 default:
974                         goto invl;
975         }
976 invl:
977         internal(file_line, "cgen_movsx: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
978         return false;
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));
989                 return true;
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));
993                         return true;
994                 }
995                 g(cgen_rr_rx(ctx, size, arg1, arg1, arg2, &codes_cmp_log));
996                 return true;
997         }
998         internal(file_line, "cgen_cmp: invalid arguments %u, %02x, %02x, %u", size, *arg1, *arg2, writes_flags);
999         return false;
1002 static bool attr_w cgen_test(struct codegen_context *ctx, unsigned size)
1004         it code;
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)) {
1010                 uint16_t m;
1011                 int64_t imm = get_imm(&arg2[1]);
1012                 if (!(imm & ~0xffffULL)) {
1013                         code = S390_TMLL;
1014                         m = (uint64_t)imm;
1015                 } else if (!(imm & ~0xffff0000ULL)) {
1016                         code = S390_TMLH;
1017                         m = (uint64_t)imm >> 16;
1018                 } else if (!(imm & ~0xffff00000000ULL)) {
1019                         code = S390_TMHL;
1020                         m = (uint64_t)imm >> 32;
1021                 } else if (!(imm & ~0xffff000000000000ULL)) {
1022                         code = S390_TMHH;
1023                         m = (uint64_t)imm >> 48;
1024                 } else {
1025                         goto invl;
1026                 }
1027                 code |= (it)m << 16;
1028                 code |= (it)arg1[0] << 36;
1029                 g(cgen_s390(ctx, code));
1030                 return true;
1031         }
1032         if (arg1[0] < 0x10 && arg2[0] == arg1[0]) {
1033                 if (size == OP_SIZE_4) {
1034                         code = S390_LTR;
1035                         code |= (it)arg1[0] << 36;
1036                         code |= (it)arg1[0] << 32;
1037                 } else if (size == OP_SIZE_8) {
1038                         code = S390_LTGR;
1039                         code |= (it)arg1[0] << 20;
1040                         code |= (it)arg1[0] << 16;
1041                 } else {
1042                         goto invl;
1043                 }
1044                 g(cgen_s390(ctx, code));
1045                 return true;
1046         }
1047 invl:
1048         internal(file_line, "cgen_test: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
1049         return false;
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))
1060                 goto invl;
1061         if (writes_flags == 0) {
1062                 if (unlikely(alu >= n_array_elements(codes_alu_no_flags)))
1063                         goto invl;
1064                 if (unlikely(codes_alu_no_flags[alu].rr == (it)-1) && unlikely(codes_alu_no_flags[alu].rrk == (it)-1))
1065                         goto invl;
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)))
1069                         goto invl;
1070                 if (unlikely(codes_alu[alu].rr == (it)-1) && unlikely(codes_alu[alu].rrk == (it)-1))
1071                         goto invl;
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)))
1075                         goto invl;
1076                 if (unlikely(codes_alu_log[alu].rr == (it)-1) && unlikely(codes_alu_log[alu].rrk == (it)-1))
1077                         goto invl;
1078                 g(cgen_rr_rx(ctx, size, arg1, arg2, arg3, &codes_alu_log[alu]));
1079         } else {
1080                 goto invl;
1081         }
1082         return true;
1083 invl:
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);
1086         return false;
1089 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
1091         it code;
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)))
1096                 goto invl;
1097         switch (alu) {
1098                 case ALU1_NEG:
1099                         if (unlikely(writes_flags != 1))
1100                                 goto invl;
1101                         if (size == OP_SIZE_4) {
1102                                 code = S390_LCR;
1103                                 code |= (it)arg1[0] << 36;
1104                                 code |= (it)arg2[0] << 32;
1105                         } else if (size == OP_SIZE_8) {
1106                                 code = S390_LCGR;
1107                                 code |= (it)arg1[0] << 20;
1108                                 code |= (it)arg2[0] << 16;
1109                         } else {
1110                                 goto invl;
1111                         }
1112                         break;
1113                 case ALU1_INC:
1114                 case ALU1_DEC:
1115                         if (unlikely(writes_flags != 1))
1116                                 goto invl;
1117                         if (size == OP_SIZE_4) {
1118                                 code = S390_AHI;
1119                         } else if (size == OP_SIZE_8) {
1120                                 code = S390_AGHI;
1121                         } else {
1122                                 goto invl;
1123                         }
1124                         code |= (it)arg1[0] << 36;
1125                         if (alu == ALU1_INC)
1126                                 code |= (it)0x0001 << 16;
1127                         else
1128                                 code |= (it)0xffff << 16;
1129                         break;
1130                 case ALU1_BSWAP:
1131                         if (size == OP_SIZE_4) {
1132                                 code = S390_LRVR;
1133                         } else if (size == OP_SIZE_8) {
1134                                 code = S390_LRVRG;
1135                         } else {
1136                                 goto invl;
1137                         }
1138                         code |= (it)arg1[0] << 20;
1139                         code |= (it)arg2[0] << 16;
1140                         break;
1141                 case ALU1_POPCNT:
1142                         if (size != OP_SIZE_8)
1143                                 goto invl;
1144                         code = S390_POPCNT;
1145                         code |= (it)arg1[0] << 20;
1146                         code |= (it)arg2[0] << 16;
1147                         break;
1148                 default:
1149                         goto invl;
1150         }
1151         g(cgen_s390(ctx, code));
1152         return true;
1153 invl:
1154         internal(file_line, "cgen_alu1: invalid arguments %u, %u, %02x, %02x", size, alu, *arg1, *arg2);
1155         return false;
1158 static bool attr_w cgen_lea3(struct codegen_context *ctx)
1160         it code;
1161         int64_t imm;
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)
1169                 goto invl;
1170         imm = get_imm(&arg4[1]);
1171         if (imm >= 0 && imm < 0x1000) {
1172                 code = S390_LA;
1173         } else {
1174                 code = S390_LAY;
1175                 code |= (it)(imm & 0xff000) >> 4;
1176         }
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));
1182         return true;
1183 invl:
1184         internal(file_line, "cgen_lea3: invalid arguments %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4);
1185         return false;
1188 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, unsigned alu)
1190         it code;
1191         unsigned sz;
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))
1198                 goto invl;
1199         if (arg3[0] >= 0x10 && unlikely(arg3[0] != ARG_IMM))
1200                 goto invl;
1202         if (size == OP_SIZE_4 && arg1[0] == arg2[0]) {
1203                 code = rot32[alu];
1204         } else if (size == OP_SIZE_4) {
1205                 code = rot32k[alu];
1206         } else if (size == OP_SIZE_8) {
1207                 code = rot64[alu];
1208         } else {
1209                 goto invl;
1210         }
1211         sz = code >> 46;
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;
1217         } else {
1218                 goto invl;
1219         }
1220         if (arg3[0] == ARG_IMM)
1221                 code |= (it)(get_imm(&arg3[1]) & (size == OP_SIZE_4 ? 0x1f : 0x3f)) << 16;
1222         else
1223                 code |= (it)arg3[0] << 28;
1224         g(cgen_s390(ctx, code));
1225         return true;
1226 invl:
1227         internal(file_line, "cgen_rot: invalid arguments %u, %u, %02x, %02x, %02x", size, alu, *arg1, *arg2, *arg3);
1228         return false;
1231 static bool attr_w cgen_mul_l(struct codegen_context *ctx, unsigned size)
1233         it code;
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))
1241                 goto invl;
1242         if (unlikely(arg2[0] & 1) || unlikely(arg1[0] != arg2[0] + 1) || unlikely(arg3[0] != arg1[0]))
1243                 goto invl;
1244         if (size == OP_SIZE_4) {
1245                 code = S390_MR;
1246                 code |= (it)arg2[0] << 36;
1247                 code |= (it)arg4[0] << 32;
1248         } else {
1249                 code = S390_MGRK;
1250                 code |= (it)arg2[0] << 20;
1251                 code |= (it)arg3[0] << 16;
1252                 code |= (it)arg4[0] << 28;
1253         }
1254         g(cgen_s390(ctx, code));
1255         return true;
1256 invl:
1257         internal(file_line, "cgen_mul_l: invalid arguments %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4);
1258         return false;
1261 static bool attr_w cgen_div_l(struct codegen_context *ctx, unsigned size, bool sgn)
1263         it code;
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))
1272                 goto invl;
1273         if (unlikely(arg1[0] & 1) || unlikely(arg2[0] != arg1[0] + 1))
1274                 goto invl;
1275         if (unlikely(arg3[0] != arg1[0]) || unlikely(arg4[0] != arg3[0] + 1))
1276                 goto invl;
1277         if (!sgn) {
1278                 code = size == OP_SIZE_4 ? S390_DLR : S390_DLGR;
1279         } else {
1280                 code = size == OP_SIZE_4 ? S390_DR : S390_DSGR;
1281         }
1282         if (code == S390_DR) {
1283                 code |= (it)arg1[0] << 36;
1284                 code |= (it)arg5[0] << 32;
1285         } else {
1286                 code |= (it)arg1[0] << 20;
1287                 code |= (it)arg5[0] << 16;
1288         }
1289         g(cgen_s390(ctx, code));
1290         return true;
1291 invl:
1292         internal(file_line, "cgen_div_l: invalid arguments %02x, %02x, %02x, %02x, %02x", *arg1, *arg2, *arg3, *arg4, *arg4);
1293         return false;
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)
1303                 goto invl;
1305         if (arg3[0] < 0x10) {
1306                 it code;
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));
1312                 return true;
1313         } else if (arg3[0] == ARG_ADDRESS_1) {
1314                 it code;
1315                 int64_t imm;
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)
1322                         goto invl;
1323                 code |= (it)(imm & 0xfff) << 16;
1324                 code |= (it)(imm & 0xff000) >> 4;
1325                 g(cgen_s390(ctx, code));
1326                 return true;
1327         }
1329 invl:
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;
1336         if (!st) {
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);
1341         } else {
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);
1346         }
1347         if (unlikely(arg2[0] >= 0x10) || unlikely(arg3[0] >= 0x10))
1348                 goto invl;
1349         if (unlikely(arg2[0] != arg3[0] + 1))
1350                 goto invl;
1351         if (!st)
1352                 g(cgen_lm_stm(ctx, size, arg3[0], arg2[0], arg1, S390_LM, S390_LMY, S390_LMG));
1353         else
1354                 g(cgen_lm_stm(ctx, size, arg3[0], arg2[0], arg1, S390_STM, S390_STMY, S390_STMG));
1355         return true;
1356 invl:
1357         internal(file_line, "cgen_ldp_stp: invalid arguments %u, %02x, %02x, %02x", size, *arg1, *arg2, *arg3);
1358         return false;
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]))
1369                 goto invl;
1370         g(cgen_rr_rx(ctx, OP_SIZE_4, arg1, arg2, arg3, &codes_ic));
1371         return true;
1372 invl:
1373         internal(file_line, "cgen_ic: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1374         return false;
1377 static bool attr_w cgen_mov_mask(struct codegen_context *ctx)
1379         it code;
1380         int64_t imm;
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))
1387                 goto invl;
1388         imm = get_imm(&arg3[1]);
1389         code = S390_IIHF;
1390         code |= (it)arg1[1] << 36;
1391         code |= (it)(imm & 0xffffffffLL);
1392         g(cgen_s390(ctx, code));
1393         return true;
1394 invl:
1395         internal(file_line, "cgen_mov_mask: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1396         return false;
1399 static bool attr_w cgen_memcpy(struct codegen_context *ctx)
1401         it code;
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))
1409                 goto invl;
1410         disp_dest = get_imm(&arg1[2]);
1411         disp_src = get_imm(&arg2[2]);
1412         len = get_imm(&arg3[1]);
1413         code = S390_MVC;
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));
1420         return true;
1421 invl:
1422         internal(file_line, "cgen_memcpy: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1423         return false;
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])))
1432                 goto invl;
1433         g(cgen_fp_op(ctx, size, arg1, arg2, &fp_cmp));
1434         return true;
1435 invl:
1436         internal(file_line, "cgen_fp_cmp: invalid arguments %u, %02x, %02x", size, *arg1, *arg2);
1437         return false;
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]))
1447                 goto invl;
1448         g(cgen_fp_op(ctx, size, arg1, arg3, &fp_alus[aux]));
1449         return true;
1450 invl:
1451         internal(file_line, "cgen_fp_alu: invalid arguments %u, %u, %02x, %02x, %02x", size, aux, *arg1, *arg2, *arg3);
1452         return false;
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])))
1461                 goto invl;
1462         g(cgen_fp_op(ctx, size, arg1, arg2, &fp_alu1s[aux]));
1463         return true;
1464 invl:
1465         internal(file_line, "cgen_fp_alu1: invalid arguments %u, %u, %02x, %02x", size, aux, *arg1, *arg2);
1466         return false;
1469 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1471         it code;
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])))
1476                 goto invl;
1477         switch (fp_op_size) {
1478                 case OP_SIZE_4:
1479                         code = int_op_size == OP_SIZE_4 ? S390_CFEBR : S390_CGEBR;
1480                         break;
1481                 case OP_SIZE_8:
1482                         code = int_op_size == OP_SIZE_4 ? S390_CFDBR : S390_CGDBR;
1483                         break;
1484                 case OP_SIZE_16:
1485                         code = int_op_size == OP_SIZE_4 ? S390_CFXBR : S390_CGXBR;
1486                         break;
1487                 default:
1488                         goto invl;
1489         }
1490         code |= (it)5 << 28;
1491         code |= (it)arg1[0] << 20;
1492         code |= (it)(arg2[0] & 0xf) << 16;
1493         g(cgen_s390(ctx, code));
1494         return true;
1495 invl:
1496         internal(file_line, "cgen_fp_to_int: invalid arguments %u, %u, %02x, %02x", int_op_size, fp_op_size, *arg1, *arg2);
1497         return false;
1500 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1502         it code;
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))
1507                 goto invl;
1508         switch (fp_op_size) {
1509                 case OP_SIZE_4:
1510                         code = int_op_size == OP_SIZE_4 ? S390_CEFBR : S390_CEGBR;
1511                         break;
1512                 case OP_SIZE_8:
1513                         code = int_op_size == OP_SIZE_4 ? S390_CDFBR : S390_CDGBR;
1514                         break;
1515                 case OP_SIZE_16:
1516                         code = int_op_size == OP_SIZE_4 ? S390_CXFBR : S390_CXGBR;
1517                         break;
1518                 default:
1519                         goto invl;
1520         }
1521         code |= (it)(arg1[0] & 0xf) << 20;
1522         code |= (it)arg2[0] << 16;
1523         g(cgen_s390(ctx, code));
1524         return true;
1525 invl:
1526         internal(file_line, "cgen_fp_from_int: invalid arguments %u, %u, %02x, %02x", int_op_size, fp_op_size, *arg1, *arg2);
1527         return false;
1530 static bool attr_w cgen_jmp_cond(struct codegen_context *ctx, bool lng, unsigned aux, bool logical)
1532         it code;
1533         if (!lng) {
1534                 g(add_relocation(ctx, JMP_SHORTEST, 0, NULL));
1535                 code = S390_BRC;
1536         } else if (USE_BRCL) {
1537                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1538                 code = S390_BRCL;
1539         } else {
1540                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1541                 code = S390_BRAS;
1542                 code |= (it)R_OFFSET_IMM << 36;
1543                 code |= (it)4 << 16;
1544                 g(cgen_s390(ctx, code));
1545                 cgen_four(0);
1546 #if defined(ARCH_S390_32)
1547                 code = S390_L;
1548 #else
1549                 code = S390_LGF;
1550 #endif
1551                 code |= (it)R_CONST_IMM << 36;
1552                 code |= (it)R_OFFSET_IMM << 28;
1553                 g(cgen_s390(ctx, code));
1554                 code = S390_LA;
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));
1559                 code = S390_BCR;
1560                 code |= (it)R_OFFSET_IMM << 32;
1561                 code |= (it)get_jmp_cond(aux, logical) << 36;
1562                 g(cgen_s390(ctx, code));
1563                 return true;
1564         }
1565         code |= (it)get_jmp_cond(aux, logical) << 36;
1566         g(cgen_s390(ctx, code));
1567         return true;
1570 static bool attr_w cgen_jmp_indirect(struct codegen_context *ctx)
1572         uint8_t reg = cget_one(ctx);
1573         it code = S390_BCR;
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));
1577         return true;
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: {
1585                         int16_t i16;
1586                         if (unlikely(offs < -0x8000) || unlikely(offs >= 0x8000))
1587                                 return false;
1588                         i16 = offs;
1589                         memcpy(ctx->mcode + reloc->position + 2, &i16, 2);
1590                         return true;
1591                 }
1592                 case JMP_SHORT: {
1593                         int32_t i32;
1594                         if (USE_BRCL) {
1595                                 if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
1596                                         return false;
1597                                 i32 = offs;
1598                                 memcpy(ctx->mcode + reloc->position + 2, &i32, 4);
1599                                 return true;
1600                         } else {
1601                                 offs *= 2;
1602                                 offs -= 4;
1603                                 if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
1604                                         return false;
1605                                 i32 = offs;
1606                                 memcpy(ctx->mcode + reloc->position + 4, &i32, 4);
1607                                 return true;
1608                         }
1609                 }
1610                 default: {
1611                         internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1612                         return false;
1613                 }
1614         }
1617 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1619         /*debug("insn: %08x", insn);*/
1620         switch (insn_opcode(insn)) {
1621                 case INSN_ENTRY:
1622                         g(cgen_entry(ctx));
1623                         return true;
1624                 case INSN_LABEL:
1625                         g(cgen_label(ctx));
1626                         return true;
1627                 case INSN_RET:
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)));
1629                         return true;
1630                 case INSN_S390_PUSH:
1631                         g(cgen_s390_push_pop(ctx, insn_op_size(insn), true));
1632                         return true;
1633                 case INSN_S390_POP:
1634                         g(cgen_s390_push_pop(ctx, insn_op_size(insn), false));
1635                         return true;
1636                 case INSN_CALL_INDIRECT:
1637                         g(cgen_call_indirect(ctx));
1638                         return true;
1639                 case INSN_MOV:
1640                         g(cgen_mov(ctx, insn_op_size(insn)));
1641                         return true;
1642                 case INSN_MOVSX:
1643                         g(cgen_movsx(ctx, insn_op_size(insn)));
1644                         return true;
1645                 case INSN_CMP:
1646                         g(cgen_cmp(ctx, insn_op_size(insn), insn_writes_flags(insn)));
1647                         return true;
1648                 case INSN_TEST:
1649                         if (unlikely(!insn_writes_flags(insn)))
1650                                 goto invalid_insn;
1651                         g(cgen_test(ctx, insn_op_size(insn)));
1652                         return true;
1653                 case INSN_ALU:
1654                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1655                                 goto invalid_insn;
1656                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1657                         return true;
1658                 case INSN_ALU_PARTIAL:
1659                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1660                                 goto invalid_insn;
1661                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1662                         return true;
1663                 case INSN_ALU1:
1664                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1665                                 goto invalid_insn;
1666                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1667                         return true;
1668                 case INSN_ALU1_PARTIAL:
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_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1672                         return true;
1673                 case INSN_LEA3:
1674                         if (unlikely(insn_op_size(insn) != OP_SIZE_ADDRESS))
1675                                 goto invalid_insn;
1676                         if (unlikely(insn_aux(insn) != 0))
1677                                 goto invalid_insn;
1678                         g(cgen_lea3(ctx));
1679                         return true;
1680                 case INSN_ROT:
1681                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1682                                 goto invalid_insn;
1683                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1684                         return true;
1685                 case INSN_ROT_PARTIAL:
1686                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) >= OP_SIZE_NATIVE))
1687                                 goto invalid_insn;
1688                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1689                         return true;
1690                 case INSN_MUL_L:
1691                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1692                                 goto invalid_insn;
1693                         g(cgen_mul_l(ctx, insn_op_size(insn)));
1694                         return true;
1695                 case INSN_DIV_L:
1696                         g(cgen_div_l(ctx, insn_op_size(insn), insn_aux(insn)));
1697                         return true;
1698                 case INSN_CMOV:
1699                 case INSN_CMOV_XCC:
1700                         if (unlikely(!cpu_test_feature(CPU_FEATURE_misc_45)))
1701                                 goto invalid_insn;
1702                         g(cgen_cmov(ctx, insn_op_size(insn), insn_aux(insn), insn_opcode(insn) == INSN_CMOV_XCC));
1703                         return true;
1704                 case INSN_STP:
1705                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1706                                 goto invalid_insn;
1707                         g(cgen_ldp_stp(ctx, insn_op_size(insn), true));
1708                         return true;
1709                 case INSN_LDP:
1710                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2) || unlikely(insn_op_size(insn) > OP_SIZE_NATIVE))
1711                                 goto invalid_insn;
1712                         g(cgen_ldp_stp(ctx, insn_op_size(insn), false));
1713                         return true;
1714                 case INSN_MOV_MASK:
1715                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1716                                 goto invalid_insn;
1717                         if (insn_aux(insn) == MOV_MASK_0_8) {
1718                                 g(cgen_ic(ctx));
1719                         } else if (insn_aux(insn) == MOV_MASK_32_64) {
1720                                 g(cgen_mov_mask(ctx));
1721                         } else {
1722                                 goto invalid_insn;
1723                         }
1724                         return true;
1725                 case INSN_MEMCPY:
1726                         g(cgen_memcpy(ctx));
1727                         return true;
1728                 case INSN_FP_CMP:
1729                         g(cgen_fp_cmp(ctx, insn_op_size(insn)));
1730                         return true;
1731                 case INSN_FP_ALU:
1732                         g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1733                         return true;
1734                 case INSN_FP_ALU1:
1735                         g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1736                         return true;
1737                 case INSN_FP_TO_INT32:
1738                         g(cgen_fp_to_int(ctx, OP_SIZE_4, insn_op_size(insn)));
1739                         return true;
1740                 case INSN_FP_TO_INT64:
1741                         g(cgen_fp_to_int(ctx, OP_SIZE_8, insn_op_size(insn)));
1742                         return true;
1743                 case INSN_FP_FROM_INT32:
1744                         g(cgen_fp_from_int(ctx, OP_SIZE_4, insn_op_size(insn)));
1745                         return true;
1746                 case INSN_FP_FROM_INT64:
1747                         g(cgen_fp_from_int(ctx, OP_SIZE_8, insn_op_size(insn)));
1748                         return true;
1749                 case INSN_JMP:
1750                         g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, COND_ALWAYS, false));
1751                         return true;
1752                 case INSN_JMP_COND:
1753                         g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, insn_aux(insn), false));
1754                         return true;
1755                 case INSN_JMP_COND_LOGICAL:
1756                         g(cgen_jmp_cond(ctx, insn_jump_size(insn) == JMP_SHORT, insn_aux(insn), true));
1757                         return true;
1758                 case INSN_JMP_INDIRECT:
1759                         g(cgen_jmp_indirect(ctx));
1760                         return true;
1761                 default:
1762                 invalid_insn:
1763                         internal(file_line, "cgen_insn: invalid insn %08x", insn);
1764                         return false;
1765         }