codegen: fix a bug in "bt" on big-endian machines
[ajla.git] / c2-hppa.inc
blob2ccb352ec29339c3b7edf49d4e41fd3898b343fa
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 #define  PARISC_N                       0x2U
21 #define  PARISC_COND_64                 0x0020U
22 #define  PARISC_COND_NEVER              0x0000U
23 #define  PARISC_COND_ALWAYS             0x1000U
24 #define  PARISC_COND_EQUAL              0x2000U
25 #define  PARISC_COND_NOT_EQUAL          0x3000U
26 #define  PARISC_COND_L_S                0x4000U
27 #define  PARISC_COND_GE_S               0x5000U
28 #define  PARISC_COND_LE_S               0x6000U
29 #define  PARISC_COND_G_S                0x7000U
30 #define  PARISC_COND_L_U                0x8000U
31 #define  PARISC_COND_GE_U               0x9000U
32 #define  PARISC_COND_LE_U               0xa000U
33 #define  PARISC_COND_G_U                0xb000U
34 #define  PARISC_COND_SV                 0xc000U
35 #define  PARISC_COND_NSV                0xd000U
36 #define  PARISC_COND_OD                 0xe000U
37 #define  PARISC_COND_EV                 0xf000U
38 #define  PARISC_COND_NEG                0x1000U
40 #define PARISC_LDSID            0x000010a0U
41 #define PARISC_MTSP             0x00001820U
42 #define PARISC_MTSAR            0x01601840U
43 #define PARISC_MTSARCM          0x016018c0U
44 #define PARISC_ANDCM            0x08000000U
45 #define PARISC_AND              0x08000200U
46 #define PARISC_OR               0x08000240U
47 #define PARISC_NOP              0x08000240U
48 #define PARISC_XOR              0x08000280U
49 #define PARISC_SUB              0x08000400U
50 #define PARISC_SUB_B            0x08000500U
51 #define PARISC_SUB_DB           0x08000520U
52 #define PARISC_ADD              0x08000600U
53 #define PARISC_ADD_C            0x08000700U
54 #define PARISC_ADD_DC           0x08000720U
55 #define PARISC_CMPCLR           0x08000880U
56 #define PARISC_UADDCM           0x08000980U
57 #define PARISC_ADD_L            0x08000a00U
58 #define PARISC_SHLADD_L_1       0x08000a40U
59 #define PARISC_SHLADD_L_2       0x08000a80U
60 #define PARISC_SHLADD_L_3       0x08000ac0U
62 #define PARISC_LD_ST            0x0c000000U
63 #define  PARISC_LD_ST_B                 0x00000000U
64 #define  PARISC_LD_ST_H                 0x00000040U
65 #define  PARISC_LD_ST_W                 0x00000080U
66 #define  PARISC_LD_ST_D                 0x000000c0U
67 #define  PARISC_LD_ST_IMM               0x00001000U
68 #define  PARISC_LD_ST_MA                0x00000020U
69 #define  PARISC_LD_ST_MB                0x00002020U
70 #define  PARISC_LD_ST_LD                0x00000000U
71 #define  PARISC_LD_ST_ST                0x00000200U
72 #define  PARISC_LD_SCALE                0x00002000U
73 #define PARISC_LDIL             0x20000000U
74 #define PARISC_ADDIL            0x28000000U
75 #define PARISC_LDO              0x34000000U
77 #define PARISC_LDB_LONG         0x40000000U
78 #define PARISC_LDH_LONG         0x44000000U
79 #define PARISC_LDW_LONG         0x48000000U
80 #define PARISC_LDW_M            0x4c000000U
81 #define PARISC_LDD              0x50000000U
82 #define PARISC_STB_LONG         0x60000000U
83 #define PARISC_STH_LONG         0x64000000U
84 #define PARISC_STW_LONG         0x68000000U
85 #define PARISC_STW_M            0x6c000000U
86 #define PARISC_STD              0x70000000U
87 #define  PARISC_LDD_STD_MA              0x00000008U
88 #define  PARISC_LDD_STD_MB              0x0000000cU
90 #define PARISC_CMPB             0x80000000U
91 #define PARISC_CMPIB            0x84000000U
92 #define PARISC_CMPB_NOT         0x88000000U
93 #define PARISC_CMPIB_NOT        0x8c000000U
94 #define PARISC_CMPICLR          0x90000000U
95 #define  PARISC_CMPICLR_64              0x00000800U
96 #define PARISC_SUBI             0x94000000U
97 #define PARISC_CMPB_64          0x9c000000U
98 #define PARISC_ADDB             0xa0000000U
99 #define PARISC_ADDB_NOT         0xa8000000U
100 #define PARISC_ADDI             0xb4000000U
101 #define PARISC_CMPB_64_NOT      0xbc000000U
103 #define PARISC_BB_1             0xc4004000U
104 #define PARISC_BB_64_1          0xc4006000U
105 #define PARISC_BB_0             0xc400c000U
106 #define PARISC_BB_64_0          0xc400e000U
107 #define PARISC_SHRPW_SAR        0xd0000000U
108 #define PARISC_SHRPD_SAR        0xd0000200U
109 #define PARISC_EXTRW_U_SAR      0xd0001000U
110 #define PARISC_EXTRD_U_SAR      0xd0001200U
111 #define PARISC_EXTRW_S_SAR      0xd0001400U
112 #define PARISC_EXTRD_S_SAR      0xd0001600U
113 #define PARISC_EXTRW_U          0xd0001800U
114 #define PARISC_EXTRW_S          0xd0001c00U
115 #define PARISC_DEPW_Z_SAR       0xd4000000U
116 #define PARISC_DEPD_Z_SAR       0xd4000200U
117 #define PARISC_DEPW_SAR         0xd4000400U
118 #define PARISC_DEPD_SAR         0xd4000600U
119 #define PARISC_DEPW_Z           0xd4000800U
120 #define PARISC_DEPW             0xd4000c00U
121 #define PARISC_DEPWI_Z_SAR      0xd4001000U
122 #define PARISC_DEPDI_Z_SAR      0xd4001200U
123 #define PARISC_DEPWI_SAR        0xd4001400U
124 #define PARISC_DEPDI_SAR        0xd4001600U
125 #define PARISC_DEPWI_Z          0xd4001800U
126 #define PARISC_DEPWI            0xd4001c00U
127 #define PARISC_EXTRD_U          0xd8001800U
128 #define PARISC_EXTRD_S          0xd8001c00U
129 #define PARISC_BE               0xe0000000U
130 #define PARISC_BL               0xe8000000U
131 #define PARISC_BLR              0xe8004000U
132 #define PARISC_BL_L             0xe800a000U
133 #define PARISC_BV               0xe800c000U
134 #define PARISC_BVE_RET          0xe800d000U
135 #define PARISC_BVE_CALL         0xe800f000U
136 #define PARISC_CMPIB_64         0xec000000U
137 #define PARISC_DEPD_Z           0xf0001000U
138 #define PARISC_DEPD             0xf0001400U
139 #define PARISC_DEPDI_Z          0xf4000000U
140 #define PARISC_DEPDI            0xf4000400U
142 #define  PARISC_FP_DOUBLE               0x00000800U
143 #define PARISC_FLDW             0x24001000U
144 #define PARISC_FSTW             0x24001200U
145 #define PARISC_FLDD             0x2c001000U
146 #define PARISC_FSTD             0x2c001200U
147 #define PARISC_FCMP             0x30000400U
148 #define  PARISC_FCMP_P                  0x02U
149 #define  PARISC_FCMP_NE                 0x04U
150 #define  PARISC_FCMP_AE                 0x08U
151 #define  PARISC_FCMP_A                  0x0cU
152 #define  PARISC_FCMP_BE                 0x10U
153 #define  PARISC_FCMP_B                  0x14U
154 #define  PARISC_FCMP_E                  0x18U
155 #define  PARISC_FCMP_NP                 0x1cU
156 #define PARISC_FADD             0x30000600U
157 #define PARISC_FTEST            0x30002420U
158 #define PARISC_FSUB             0x30002600U
159 #define PARISC_FCPY             0x30004000U
160 #define PARISC_FMPY             0x30004600U
161 #define PARISC_FDIV             0x30006600U
162 #define PARISC_FCNVXF           0x30008200U
163 #define  PARISC_FCNVXF_FROM_LONG        0x00000800U
164 #define  PARISC_FCNVXF_TO_DOUBLE        0x00002000U
165 #define PARISC_FSQRT            0x30008000U
166 #define PARISC_FNEG             0x3000c000U
167 #define PARISC_FCNVFXT          0x30018200U
168 #define  PARISC_FCNVFXT_FROM_DOUBLE     0x00000800U
169 #define  PARISC_FCNVFXT_TO_LONG         0x00002000U
170 #define PARISC_FLDD_LONG        0x50000002U
171 #define PARISC_FLDW_LONG        0x5c000000U
172 #define PARISC_FSTD_LONG        0x70000002U
173 #define PARISC_FSTW_LONG        0x7c000000U
175 static const int32_t cmp_sub_cond[0x12] = {
176         PARISC_COND_SV,         PARISC_COND_NSV,        PARISC_COND_L_U,        PARISC_COND_GE_U,
177         PARISC_COND_EQUAL,      PARISC_COND_NOT_EQUAL,  PARISC_COND_LE_U,       PARISC_COND_G_U,
178         PARISC_COND_L_S,        PARISC_COND_GE_S,       -1,                     -1,
179         PARISC_COND_L_S,        PARISC_COND_GE_S,       PARISC_COND_LE_S,       PARISC_COND_G_S,
180         PARISC_COND_EV,         PARISC_COND_OD,
183 static unsigned cmp_swap_arguments(unsigned cond)
185         switch (cond) {
186                 case COND_B:    return COND_A;
187                 case COND_AE:   return COND_BE;
188                 case COND_E:    return COND_E;
189                 case COND_NE:   return COND_NE;
190                 case COND_BE:   return COND_AE;
191                 case COND_A:    return COND_B;
192                 case COND_L:    return COND_G;
193                 case COND_GE:   return COND_LE;
194                 case COND_LE:   return COND_GE;
195                 case COND_G:    return COND_L;
196         }
197         internal(file_line, "cmp_swap_arguments: can't swap the condition %u", cond);
198         return 0;
201 static bool attr_w cgen_2reg(struct codegen_context *ctx, uint32_t mc, unsigned r1, unsigned rt)
203         mc |= (uint32_t)r1 << 21;
204         mc |= (uint32_t)rt << 16;
205         cgen_four(mc);
206         return true;
209 static bool attr_w cgen_3reg(struct codegen_context *ctx, uint32_t mc, unsigned r1, unsigned r2, unsigned rt)
211         mc |= (uint32_t)r1 << 16;
212         mc |= (uint32_t)r2 << 21;
213         mc |= rt;
214         cgen_four(mc);
215         return true;
218 static uint32_t attr_unused low_sign_ext_5(unsigned bit5)
220         return  ((bit5 & 0x10) >> 4) |
221                 ((bit5 & 0x0f) << 1);
224 static uint32_t low_sign_ext_11(unsigned bit11)
226         return  ((bit11 & 0x400) >> 10) |
227                 ((bit11 & 0x3ff) << 1);
230 static uint32_t low_sign_ext_14(unsigned bit14)
232         return  ((bit14 & 0x2000) >> 13) |
233                 ((bit14 & 0x1fff) << 1);
236 static uint32_t assemble_12(uint32_t bit12)
238         return  ((bit12 & 0x800) >> 11) |
239                 ((bit12 & 0x400) >> 8) |
240                 ((bit12 & 0x3ff) << 3);
243 static uint32_t assemble_17(uint32_t bit17)
245         return  ((bit17 & 0x10000) >> 16) |
246                 ((bit17 & 0x0f800) << 5) |
247                 ((bit17 & 0x00400) >> 8) |
248                 ((bit17 & 0x003ff) << 3);
251 static uint32_t assemble_21(uint32_t bit21)
253         return  ((bit21 & 0x100000) >> 20) |
254                 ((bit21 & 0x0ffe00) >> 8) |
255                 ((bit21 & 0x000180) << 7) |
256                 ((bit21 & 0x00007c) << 14) |
257                 ((bit21 & 0x000003) << 12);
260 static uint32_t assemble_22(uint32_t bit22)
262         return  ((bit22 & 0x200000) >> 21) |
263                 ((bit22 & 0x1f0000) << 5) |
264                 ((bit22 & 0x00f800) << 5) |
265                 ((bit22 & 0x000400) >> 8) |
266                 ((bit22 & 0x0003ff) << 3);
269 static bool attr_w cgen_ret(struct codegen_context *ctx)
271         uint32_t mc;
272         if (!PA_20 && PA_SPACES) {
273                 mc = PARISC_LDSID;
274                 mc |= (uint32_t)R_RP << 21;
275                 mc |= R_CG_SCRATCH;
276                 cgen_four(mc);
277                 mc = PARISC_MTSP;
278                 mc |= (uint32_t)R_CG_SCRATCH << 16;
279                 cgen_four(mc);
280                 mc = PARISC_BE;
281                 mc |= (uint32_t)R_RP << 21;
282                 mc |= PARISC_N;
283                 cgen_four(mc);
284         } else {
285                 mc = PA_20 ? PARISC_BVE_RET : PARISC_BV;
286                 mc |= (uint32_t)R_RP << 21;
287                 mc |= PARISC_N;
288                 cgen_four(mc);
289         }
290         cgen_four(PARISC_NOP);
291         return true;
294 static bool attr_w cgen_call(struct codegen_context *ctx, unsigned length)
296         if (length <= JMP_SHORT) {
297                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
298                 cgen_four(PARISC_BL | ((uint32_t)R_RP << 21) | PARISC_N);
299                 cgen_four(PARISC_NOP);
300         } else if (length == JMP_LONG && PA_20) {
301                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
302                 cgen_four(PARISC_BL_L | PARISC_N);
303                 cgen_four(PARISC_NOP);
304         } else {
305                 g(add_relocation(ctx, JMP_EXTRA_LONG, 0, NULL));
306                 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
307                 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
308                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_RP, R_CG_SCRATCH));
309                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_RP, R_CG_SCRATCH));
310                 cgen_four(PARISC_NOP);
311         }
312         return true;
315 static bool attr_w cgen_call_indirect(struct codegen_context *ctx)
317         uint32_t mc;
318         unsigned reg = cget_one(ctx);
320         mc = PARISC_LDD | low_sign_ext_14(0x10);
321         g(cgen_2reg(ctx, mc, reg, R_31));
323         cgen_four(PARISC_BVE_CALL | ((uint32_t)R_31 << 21));
325         mc = PARISC_LDD | low_sign_ext_14(0x18);
326         g(cgen_2reg(ctx, mc, reg, R_DP));
328         return true;
331 static bool attr_w cgen_ld_st(struct codegen_context *ctx, bool ld, unsigned size, uint8_t reg, uint8_t *address)
333         int64_t imm = 0;
334         uint32_t mc;
336         if (address[0] == ARG_ADDRESS_1) {
337                 imm = get_imm(&address[2]);
338                 if (ld) {
339                         switch (size) {
340                                 case OP_SIZE_1: mc = PARISC_LDB_LONG; break;
341                                 case OP_SIZE_2: mc = PARISC_LDH_LONG; break;
342                                 case OP_SIZE_4: mc = PARISC_LDW_LONG; break;
343                                 case OP_SIZE_8: mc = PARISC_LDD; break;
344                                 default:        goto invalid;
345                         }
346                 } else {
347                         switch (size) {
348                                 case OP_SIZE_1: mc = PARISC_STB_LONG; break;
349                                 case OP_SIZE_2: mc = PARISC_STH_LONG; break;
350                                 case OP_SIZE_4: mc = PARISC_STW_LONG; break;
351                                 case OP_SIZE_8: mc = PARISC_STD; break;
352                                 default:        goto invalid;
353                         }
354                 }
355                 mc |= low_sign_ext_14(imm);
356                 g(cgen_2reg(ctx, mc, address[1], reg));
357                 return true;
358         }
359         if (address[0] == ARG_ADDRESS_1_PRE_I || address[0] == ARG_ADDRESS_1_POST_I) {
360                 imm = get_imm(&address[2]);
361                 if (size == OP_SIZE_4) {
362                         if (imm >= 0 && address[0] == ARG_ADDRESS_1_PRE_I)
363                                 goto invalid;
364                         if (imm < 0 && address[0] == ARG_ADDRESS_1_POST_I)
365                                 goto invalid;
366                 }
367                 if (ld) {
368                         switch (size) {
369                                 case OP_SIZE_4: mc = PARISC_LDW_M; break;
370                                 case OP_SIZE_8: mc = PARISC_LDD | (address[0] == ARG_ADDRESS_1_PRE_I ? PARISC_LDD_STD_MB : PARISC_LDD_STD_MA); break;
371                                 default:        goto invalid;
372                         }
373                 } else {
374                         switch (size) {
375                                 case OP_SIZE_4: mc = PARISC_STW_M; break;
376                                 case OP_SIZE_8: mc = PARISC_STD | (address[0] == ARG_ADDRESS_1_PRE_I ? PARISC_LDD_STD_MB : PARISC_LDD_STD_MA); break;
377                                 default:        goto invalid;
378                         }
379                 }
380                 mc |= low_sign_ext_14(imm);
381                 g(cgen_2reg(ctx, mc, address[1], reg));
382                 return true;
383         }
384         if (address[0] >= ARG_ADDRESS_2 && address[0] <= ARG_ADDRESS_2_8 && ld) {
385                 imm = get_imm(&address[3]);
386                 if (unlikely(imm != 0))
387                         goto invalid;
388                 mc = PARISC_LD_ST | PARISC_LD_ST_LD;
389                 if (address[0] == ARG_ADDRESS_2) {
390                 } else if (address[0] == ARG_ADDRESS_2_4 && size == OP_SIZE_4) {
391                         mc |= PARISC_LD_SCALE;
392                 } else if (address[0] == ARG_ADDRESS_2_8 && size == OP_SIZE_8) {
393                         mc |= PARISC_LD_SCALE;
394                 } else {
395                         goto invalid;
396                 }
397                 switch (size) {
398                         case OP_SIZE_1: mc |= PARISC_LD_ST_B; break;
399                         case OP_SIZE_2: mc |= PARISC_LD_ST_H; break;
400                         case OP_SIZE_4: mc |= PARISC_LD_ST_W; break;
401                         case OP_SIZE_8: mc |= PARISC_LD_ST_D; break;
402                         default:        goto invalid;
403                 }
404                 g(cgen_3reg(ctx, mc, address[2], address[1], reg));
405                 return true;
406         }
407 invalid:
408         internal(file_line, "cgen_ld_st: invalid address: %x, %02x, %02x, %"PRIxMAX"", size, reg, address[0], (uintmax_t)imm);
409         return false;
412 static bool attr_w cgen_fp_ld_st(struct codegen_context *ctx, bool ld, unsigned size, uint8_t reg, uint8_t *address)
414         int64_t imm = 0;
415         uint32_t mc;
417         if (unlikely(address[0] != ARG_ADDRESS_1))
418                 goto invalid;
420         imm = get_imm(&address[2]);
421         if (imm >= -0x10 && imm < 0x10) {
422                 if (ld)
423                         mc = size == OP_SIZE_4 ? PARISC_FLDW : PARISC_FLDD;
424                 else
425                         mc = size == OP_SIZE_4 ? PARISC_FSTW : PARISC_FSTD;
426                 mc |= low_sign_ext_5(imm) << 16;
427                 mc |= reg & 0x1f;
428                 mc |= (uint32_t)address[1] << 21;
429                 cgen_four(mc);
430                 return true;
431         } else {
432                 if (ld)
433                         mc = size == OP_SIZE_4 ? PARISC_FLDW_LONG : PARISC_FLDD_LONG;
434                 else
435                         mc = size == OP_SIZE_4 ? PARISC_FSTW_LONG : PARISC_FSTD_LONG;
436                 mc |= low_sign_ext_14(imm);
437                 g(cgen_2reg(ctx, mc, address[1], reg & 0x1f));
438                 return true;
439         }
441 invalid:
442         internal(file_line, "cgen_fp_ld_st: invalid address: %x, %02x, %02x, %"PRIxMAX"", size, reg, address[0], (uintmax_t)imm);
443         return false;
446 static bool attr_w cgen_mov_args(struct codegen_context *ctx, unsigned size, uint8_t *arg1, uint8_t *arg2)
448         int64_t imm;
449         uint32_t mc;
451         if (arg1[0] < 0x20) {
452                 if (arg2[0] < 0x20) {
453                         if (size < OP_SIZE_NATIVE) {
454                                 if (OP_SIZE_NATIVE == OP_SIZE_4) {
455                                         switch (size) {
456                                                 case OP_SIZE_1:
457                                                         mc = PARISC_EXTRW_U ^ 0x3f8U;
458                                                         break;
459                                                 case OP_SIZE_2:
460                                                         mc = PARISC_EXTRW_U ^ 0x3f0U;
461                                                         break;
462                                                 default:
463                                                         internal(file_line, "cgen_mov_args: invalid op size %u", size);
464                                         }
465                                 } else {
466                                         switch (size) {
467                                                 case OP_SIZE_1:
468                                                         mc = PARISC_EXTRD_U ^ 0x13f8U;
469                                                         break;
470                                                 case OP_SIZE_2:
471                                                         mc = PARISC_EXTRD_U ^ 0x13f0U;
472                                                         break;
473                                                 case OP_SIZE_4:
474                                                         mc = PARISC_EXTRD_U ^ 0x13e0U;
475                                                         break;
476                                                 default:
477                                                         internal(file_line, "cgen_mov_args: invalid op size %u", size);
478                                         }
479                                 }
480                                 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
481                                 return true;
482                         }
483                         g(cgen_3reg(ctx, PARISC_OR, arg2[0], 0, arg1[0]));
484                         return true;
485                 }
486                 if (arg2[0] == ARG_IMM) {
487                         imm = get_imm(&arg2[1]);
488                         if (imm >= -0x2000 && imm < 0x2000) {
489                                 mc = PARISC_LDO;
490                                 mc |= low_sign_ext_14(imm);
491                                 g(cgen_2reg(ctx, mc, R_ZERO, arg1[0]));
492                                 return true;
493                         }
494                         if (imm & 0x7ff)
495                                 goto invalid;
496                         mc = PARISC_LDIL;
497                         mc |= (uint32_t)arg1[0] << 21;
498                         mc |= assemble_21((uint64_t)imm >> 11);
499                         cgen_four(mc);
500                         return true;
501                 }
502                 return cgen_ld_st(ctx, true, size, arg1[0], arg2);
503         }
505         if (arg2[0] < 0x20) {
506                 return cgen_ld_st(ctx, false, size, arg2[0], arg1);
507         }
508         if (arg2[0] == ARG_IMM) {
509                 imm = get_imm(&arg2[1]);
510                 if (unlikely(imm != 0))
511                         goto invalid;
512                 return cgen_ld_st(ctx, false, size, R_ZERO, arg1);
513         }
515         if (reg_is_fp(arg1[0]) && arg2[0] == ARG_ADDRESS_1) {
516                 return cgen_fp_ld_st(ctx, true, size, arg1[0], arg2);
517         }
518         if (reg_is_fp(arg2[0]) && arg1[0] == ARG_ADDRESS_1) {
519                 return cgen_fp_ld_st(ctx, false, size, arg2[0], arg1);
520         }
521         if (reg_is_fp(arg1[0]) && reg_is_fp(arg2[0])) {
522                 mc = PARISC_FCPY;
523                 switch (size) {
524                         case OP_SIZE_4:         break;
525                         case OP_SIZE_8:         mc |= PARISC_FP_DOUBLE; break;
526                         default:                internal(file_line, "cgen_fp_alu: invalid size %u", size);
527                 }
528                 g(cgen_3reg(ctx, mc, 0, arg2[0] & 0x1f, arg1[0] & 0x1f));
529                 return true;
530         }
532 invalid:
533         internal(file_line, "cgen_mov_args: invalid arguments %02x, %02x", arg1[0], arg2[0]);
534         return false;
537 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
539         uint8_t *arg1 = ctx->code_position;
540         uint8_t *arg2 = arg1 + arg_size(*arg1);
541         ctx->code_position = arg2 + arg_size(*arg2);
542         return cgen_mov_args(ctx, size, arg1, arg2);
545 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
547         uint32_t mc;
548         uint8_t *arg1 = ctx->code_position;
549         uint8_t *arg2 = arg1 + arg_size(*arg1);
550         ctx->code_position = arg2 + arg_size(*arg2);
551         if (unlikely(arg1[0] >= 0x20) || unlikely(arg2[0] >= 0x20))
552                 internal(file_line, "cgen_movsx: invalid arguments %02x, %02x", arg1[0], arg2[0]);
554         if (size < OP_SIZE_NATIVE) {
555                 if (OP_SIZE_NATIVE == OP_SIZE_4) {
556                         switch (size) {
557                                 case OP_SIZE_1:
558                                         mc = PARISC_EXTRW_S ^ 0x3f8U;
559                                         break;
560                                 case OP_SIZE_2:
561                                         mc = PARISC_EXTRW_S ^ 0x3f0U;
562                                         break;
563                                 default:
564                                         internal(file_line, "cgen_movsx: invalid op size %u", size);
565                         }
566                 } else {
567                         switch (size) {
568                                 case OP_SIZE_1:
569                                         mc = PARISC_EXTRD_S ^ 0x13f8U;
570                                         break;
571                                 case OP_SIZE_2:
572                                         mc = PARISC_EXTRD_S ^ 0x13f0U;
573                                         break;
574                                 case OP_SIZE_4:
575                                         mc = PARISC_EXTRD_S ^ 0x13e0U;
576                                         break;
577                                 default:
578                                         internal(file_line, "cgen_movsx: invalid op size %u", size);
579                         }
580                 }
581                 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
582                 return true;
583         } else {
584                 return cgen_mov_args(ctx, size, arg1, arg2);
585         }
588 static bool attr_w cgen_cmp_dest_reg(struct codegen_context *ctx, unsigned size, unsigned cond)
590         int32_t fc;
591         uint32_t mc;
592         uint8_t *arg1 = ctx->code_position;
593         uint8_t *arg2 = arg1 + arg_size(*arg1);
594         uint8_t *arg3 = arg2 + arg_size(*arg2);
595         ctx->code_position = arg3 + arg_size(*arg3);
597         if (arg3[0] == ARG_IMM) {
598                 cond = cmp_swap_arguments(cond);
599         }
601         fc = cmp_sub_cond[cond];
602         fc ^= PARISC_COND_NEG;
604         if (arg3[0] == ARG_IMM) {
605                 int64_t imm = get_imm(&arg3[1]);
606                 mc = PARISC_CMPICLR;
607                 if (size == OP_SIZE_8)
608                         mc |= PARISC_CMPICLR_64;
609                 mc |= fc;
610                 mc |= low_sign_ext_11(imm);
611                 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
612         } else {
613                 mc = PARISC_CMPCLR;
614                 if (size == OP_SIZE_8)
615                         mc |= PARISC_COND_64;
616                 mc |= fc;
617                 g(cgen_3reg(ctx, mc, arg2[0], arg3[0], arg1[0]));
618         }
620         mc = PARISC_LDO;
621         mc |= low_sign_ext_14(1);
622         g(cgen_2reg(ctx, mc, R_ZERO, arg1[0]));
624         return true;
627 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned writes_flags, unsigned alu, bool trap, unsigned length)
629         uint32_t mc;
630         unsigned r1, r2, rt;
631         uint8_t z = R_ZERO;
632         uint8_t *arg1 = ctx->code_position;
633         uint8_t *arg2 = arg1 + arg_size(*arg1);
634         uint8_t *arg3 = arg2 + arg_size(*arg2);
635         ctx->code_position = arg3 + arg_size(*arg3);
637         if (unlikely(arg1[0] >= 0x20) || unlikely(arg2[0] >= 0x20))
638                 goto invalid;
640         if (arg3[0] == ARG_IMM) {
641                 int64_t imm = get_imm(&arg3[1]);
642                 if (!imm) {
643                         arg3 = &z;
644                         goto do_3reg;
645                 }
646                 if (unlikely(writes_flags))
647                         goto invalid;
648                 if (!trap) {
649                         if (alu == ALU_SUB)
650                                 imm = -(uint64_t)imm;
651                         else if (unlikely(alu != ALU_ADD))
652                                 goto invalid;
653                         if (imm >= -0x2000 && imm < 0x2000) {
654                                 mc = PARISC_LDO;
655                                 mc |= low_sign_ext_14(imm);
656                                 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
657                                 return true;
658                         } else if (!(imm & 0x7ff) && arg1[0] == R_1) {
659                                 mc = PARISC_ADDIL;
660                                 mc |= (uint32_t)arg2[0] << 21;
661                                 mc |= assemble_21((uint64_t)imm >> 11);
662                                 cgen_four(mc);
663                                 return true;
664                         } else {
665                                 goto invalid;
666                         }
667                 } else {
668                         if (alu == ALU_SUB)
669                                 imm = -(uint64_t)imm;
670                         else if (unlikely(alu != ALU_ADD))
671                                 goto invalid;
672                         if (size == OP_SIZE_8) {
673                                 mc = PARISC_LDO;
674                                 mc |= low_sign_ext_14(imm);
675                                 g(cgen_2reg(ctx, mc, R_ZERO, R_CG_SCRATCH));
677                                 mc = PARISC_ADD;
678                                 r1 = arg2[0];
679                                 r2 = R_CG_SCRATCH;
680                                 rt = arg1[0];
681                         } else {
682                                 mc = PARISC_ADDI;
683                                 mc |= low_sign_ext_11(imm);
684                                 r1 = arg1[0];
685                                 r2 = arg2[0];
686                                 rt = 0;
687                         }
688                         goto do_op;
689                 }
690         }
692 do_3reg:
693         switch (alu) {
694                 case ALU_ADD:   mc = writes_flags ? PARISC_ADD : PARISC_ADD_L;
695                                 break;
696                 case ALU_OR:    ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: or must not write flags"));
697                                 mc = PARISC_OR;
698                                 break;
699                 case ALU_ADC:   ajla_assert_lo(writes_flags, (file_line, "cgen_alu: adc must write flags"));
700                                 mc = size == OP_SIZE_4 ? PARISC_ADD_C : PARISC_ADD_DC;
701                                 break;
702                 case ALU_SBB:   ajla_assert_lo(writes_flags, (file_line, "cgen_alu: sbb must write flags"));
703                                 mc = size == OP_SIZE_4 ? PARISC_SUB_B : PARISC_SUB_DB;
704                                 break;
705                 case ALU_AND:   ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: and must not write flags"));
706                                 mc = PARISC_AND;
707                                 break;
708                 case ALU_SUB:   ajla_assert_lo(writes_flags, (file_line, "cgen_alu: sub must write flags"));
709                                 mc = PARISC_SUB;
710                                 break;
711                 case ALU_XOR:   ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: xor must not write flags"));
712                                 mc = PARISC_XOR;
713                                 break;
714                 case ALU_ANDN:  ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: andn must not write flags"));
715                                 mc = PARISC_ANDCM;
716                                 break;
717                 default:        goto invalid;
718         }
720         if (alu == ALU_ADD && arg3[0] == ARG_SHIFTED_REGISTER) {
721                 uint8_t *args;
722                 if (unlikely((arg3[1] >> 6) != 0))
723                         goto invalid;
724                 if (unlikely((arg3[1] & ARG_SHIFT_AMOUNT)) >= 4)
725                         goto invalid;
726                 mc |= (uint32_t)(arg3[1] & ARG_SHIFT_AMOUNT) << 6;
727                 arg3 += 2;
728                 args = arg3;
729                 arg3 = arg2;
730                 arg2 = args;
731         }
733         if (unlikely(arg3[0] >= 0x20))
734                 goto invalid;
736 #ifdef ARCH_PARISC32
737         if (alu == ALU_ADD && size == OP_SIZE_4 && arg1[0] == arg2[0] && trap && length == JMP_SHORTEST) {
738                 bool known;
739                 mc = PARISC_ADDB;
740                 mc |= PARISC_COND_SV;
741                 mc |= PARISC_N;
742                 g(add_relocation(ctx, JMP_SHORTEST, ctx->code_position - arg1, &known));
743                 g(cgen_2reg(ctx, mc, arg1[0], arg3[0]));
744                 if (unlikely(!known))
745                         cgen_four(PARISC_NOP);
746                 return true;
747         }
748 #endif
750         r1 = arg2[0];
751         r2 = arg3[0];
752         rt = arg1[0];
754 do_op:
755         if (trap) {
756                 if (length == JMP_EXTRA_LONG || (length == JMP_LONG && !PA_20))
757                         mc |= PARISC_COND_SV;
758                 else
759                         mc |= PARISC_COND_NSV;
760                 if (size == OP_SIZE_8)
761                         mc |= PARISC_COND_64;
762         }
764         g(cgen_3reg(ctx, mc, r1, r2, rt));
766         if (trap) {
767                 if (length <= JMP_SHORT) {
768                         g(add_relocation(ctx, JMP_SHORT, ctx->code_position - arg1, NULL));
769                         cgen_four(PARISC_BL | PARISC_N);
770                 } else if (length == JMP_LONG && PA_20) {
771                         g(add_relocation(ctx, JMP_LONG, ctx->code_position - arg1, NULL));
772                         cgen_four(PARISC_BL_L | PARISC_N);
773                 } else {
774                         cgen_four(PARISC_BL | PARISC_N | assemble_12(3));
775                         g(add_relocation(ctx, JMP_EXTRA_LONG, ctx->code_position - arg1, NULL));
776                         cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
777                         g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
778                         g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
779                         g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
780                 }
781         }
783         return true;
785 invalid:
786         internal(file_line, "cgen_alu: invalid arguments %02x, %02x, %02x, %u, %u, %u", arg1[0], arg2[0], arg3[0], alu, writes_flags, (unsigned)trap);
787         return false;
790 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned writes_flags, unsigned alu, bool trap, unsigned length)
792         uint32_t mc;
793         unsigned r1, r2, rt;
794         uint8_t *arg1 = ctx->code_position;
795         uint8_t *arg2 = arg1 + arg_size(*arg1);
796         ctx->code_position = arg2 + arg_size(*arg2);
798         if (unlikely(arg1[0] >= 0x20) || unlikely(arg2[0] >= 0x20))
799                 goto invalid;
801         switch (alu) {
802                 case ALU1_NOT:  ajla_assert_lo(!writes_flags, (file_line, "cgen_alu1: not must not write flags"));
803                                 mc = PARISC_UADDCM;
804                                 r1 = R_ZERO;
805                                 r2 = arg2[0];
806                                 rt = arg1[0];
807                                 break;
808                 case ALU1_NEG:  ajla_assert_lo(writes_flags, (file_line, "cgen_alu1: neg must write flags"));
809                                 mc = PARISC_SUB;
810                                 r1 = R_ZERO;
811                                 r2 = arg2[0];
812                                 rt = arg1[0];
813                                 break;
814                 case ALU1_INC:
815                 case ALU1_DEC:  ajla_assert_lo(writes_flags, (file_line, "cgen_alu1: inc/dec must write flags"));
816                                 if (trap && size == OP_SIZE_8) {
817                                         mc = PARISC_LDO;
818                                         mc |= low_sign_ext_14(alu == ALU1_INC ? 1 : -1);
819                                         g(cgen_2reg(ctx, mc, R_ZERO, R_CG_SCRATCH));
821                                         mc = PARISC_ADD;
822                                         r1 = arg2[0];
823                                         r2 = R_CG_SCRATCH;
824                                         rt = arg1[0];
825                                 } else {
826                                         mc = PARISC_ADDI;
827                                         mc |= low_sign_ext_11(alu == ALU1_INC ? 1 : -1);
828                                         r1 = arg1[0];
829                                         r2 = arg2[0];
830                                         rt = 0;
831                                 }
832                                 break;
833                 default:        goto invalid;
834         }
836         if (trap) {
837                 if (length == JMP_EXTRA_LONG || (length == JMP_LONG && !PA_20))
838                         mc |= PARISC_COND_SV;
839                 else
840                         mc |= PARISC_COND_NSV;
841                 if (size == OP_SIZE_8)
842                         mc |= PARISC_COND_64;
843         }
845         g(cgen_3reg(ctx, mc, r1, r2, rt));
847         if (trap) {
848                 if (length <= JMP_SHORT) {
849                         g(add_relocation(ctx, JMP_SHORT, ctx->code_position - arg1, NULL));
850                         cgen_four(PARISC_BL | PARISC_N);
851                 } else if (length == JMP_LONG && PA_20) {
852                         g(add_relocation(ctx, JMP_LONG, ctx->code_position - arg1, NULL));
853                         cgen_four(PARISC_BL_L | PARISC_N);
854                 } else {
855                         cgen_four(PARISC_BL | PARISC_N | assemble_12(3));
856                         g(add_relocation(ctx, JMP_EXTRA_LONG, ctx->code_position - arg1, NULL));
857                         cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
858                         g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
859                         g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
860                         g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
861                 }
862         }
864         return true;
866 invalid:
867         internal(file_line, "cgen_alu1: invalid arguments %02x, %02x, %u, %u", arg1[0], arg2[0], alu, writes_flags);
868         return false;
871 static bool attr_w cgen_sar(struct codegen_context *ctx, bool sar_complement, uint8_t reg)
873         uint32_t mc;
874         if (!sar_complement) {
875                 mc = PARISC_MTSAR;
876                 mc |= (uint32_t)reg << 16;
877                 cgen_four(mc);
878         } else if (PA_20) {
879                 mc = PARISC_MTSARCM;
880                 mc |= (uint32_t)reg << 16;
881                 cgen_four(mc);
882         } else {
883                 mc = PARISC_LDO;
884                 mc |= low_sign_ext_14(-1);
885                 g(cgen_2reg(ctx, mc, 0, R_CG_SCRATCH));
886                 mc = PARISC_XOR;
887                 g(cgen_3reg(ctx, mc, R_CG_SCRATCH, reg, R_CG_SCRATCH));
888                 mc = PARISC_MTSAR;
889                 mc |= (uint32_t)R_CG_SCRATCH << 16;
890                 cgen_four(mc);
891         }
892         return true;
895 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, unsigned rot)
897         uint32_t mc;
898         uint8_t *arg1 = ctx->code_position;
899         uint8_t *arg2 = arg1 + arg_size(*arg1);
900         uint8_t *arg3 = arg2 + arg_size(*arg2);
901         ctx->code_position = arg3 + arg_size(*arg3);
902         if (arg3[0] == ARG_IMM) {
903                 int64_t imm = get_imm(&arg3[1]);
904                 unsigned sh = imm & (size == OP_SIZE_4 ? 31 : 63);
905                 if (size == OP_SIZE_4) {
906                         switch (rot) {
907                                 case ROT_SHL:
908                                         mc = PARISC_DEPW_Z;
909                                         mc |= sh | (sh << 5);
910                                         break;
911                                 case ROT_SHR:
912                                         mc = PARISC_EXTRW_U;
913                                         mc |= sh | ((31 - sh) << 5);
914                                         break;
915                                 case ROT_SAR:
916                                         mc = PARISC_EXTRW_S;
917                                         mc |= sh | ((31 - sh) << 5);
918                                         break;
919                                 default:
920                                         goto invalid;
921                         }
922                 } else {
923                         switch (rot) {
924                                 case ROT_SHL:
925                                         mc = PARISC_DEPD_Z;
926                                         mc |= (sh & 31) | ((sh & 31) << 5);
927                                         if (sh & 32)
928                                                 mc ^= 0x1800;
929                                         break;
930                                 case ROT_SHR:
931                                         mc = PARISC_EXTRD_U;
932                                         mc |= (sh & 31) | ((31 - (sh & 31)) << 5);
933                                         if (sh & 32)
934                                                 mc ^= 0x1800;
935                                         break;
936                                 case ROT_SAR:
937                                         mc = PARISC_EXTRD_S;
938                                         mc |= (sh & 31) | ((31 - (sh & 31)) << 5);
939                                         if (sh & 32)
940                                                 mc ^= 0x1800;
941                                         break;
942                                 default:
943                                         goto invalid;
944                         }
945                 }
946                 if (rot == ROT_SHL)
947                         g(cgen_2reg(ctx, mc, arg1[0], arg2[0]));
948                 else
949                         g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
950                 return true;
951         } else if (arg3[0] < 0x20) {
952                 bool sar_complement = rot != ROT_SHR;
953                 g(cgen_sar(ctx, sar_complement, arg3[0]));
954                 if (size == OP_SIZE_4) {
955                         switch (rot) {
956                                 case ROT_SHL:
957                                         mc = PARISC_DEPW_Z_SAR;
958                                         break;
959                                 case ROT_SHR:
960                                         mc = PARISC_SHRPW_SAR;
961                                         break;
962                                 case ROT_SAR:
963                                         mc = PARISC_EXTRW_S_SAR;
964                                         break;
965                                 default:
966                                         goto invalid;
967                         }
968                 } else {
969                         switch (rot) {
970                                 case ROT_SHL:
971                                         mc = PARISC_DEPD_Z_SAR | 0x100;
972                                         break;
973                                 case ROT_SHR:
974                                         mc = PARISC_SHRPD_SAR;
975                                         break;
976                                 case ROT_SAR:
977                                         mc = PARISC_EXTRD_S_SAR | 0x100;
978                                         break;
979                                 default:
980                                         goto invalid;
981                         }
982                 }
983                 if (rot == ROT_SHL) {
984                         g(cgen_2reg(ctx, mc, arg1[0], arg2[0]));
985                 } else if (rot == ROT_SHR) {
986                         g(cgen_3reg(ctx, mc, R_ZERO, arg2[0], arg1[0]));
987                 } else {
988                         g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
989                 }
990                 return true;
991         }
993 invalid:
994         internal(file_line, "cgen_rot: invalid arguments %02x, %02x, %02x, %u, %u", arg1[0], arg2[0], arg3[0], size, rot);
995         return false;
998 static bool attr_w cgen_btx(struct codegen_context *ctx, unsigned size, unsigned aux)
1000         uint32_t mc;
1001         uint8_t *arg1 = ctx->code_position;
1002         uint8_t *arg2 = arg1 + arg_size(*arg1);
1003         uint8_t *arg3 = arg2 + arg_size(*arg2);
1004         ctx->code_position = arg3 + arg_size(*arg3);
1006         if (aux == BTX_BTS || aux == BTX_BTR) {
1007                 if (arg1[0] != arg2[0]) {
1008                         g(cgen_3reg(ctx, PARISC_OR, arg2[0], 0, arg1[0]));
1009                 }
1010         }
1012         if (arg3[0] == ARG_IMM) {
1013                 int64_t imm = get_imm(&arg3[1]);
1014                 unsigned bit = imm & (size == OP_SIZE_4 ? 31 : 63);
1015                 if (size == OP_SIZE_4) {
1016                         switch (aux) {
1017                                 case BTX_BTS:
1018                                 case BTX_BTR:
1019                                         mc = PARISC_DEPWI;
1020                                         mc |= 31U | (bit << 5);
1021                                         g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1022                                         return true;
1023                                 case BTX_BTEXT:
1024                                         mc = PARISC_EXTRW_U;
1025                                         mc |= 31U | ((31 - bit) << 5);
1026                                         g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1027                                         return true;
1028                                 default:
1029                                         goto invalid;
1030                         }
1031                 } else {
1032                         switch (aux) {
1033                                 case BTX_BTS:
1034                                 case BTX_BTR:
1035                                         mc = PARISC_DEPDI;
1036                                         mc |= 31U | ((bit & 0x1f) << 5) | ((bit & 0x20) << 6);
1037                                         g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1038                                         return true;
1039                                 case BTX_BTEXT:
1040                                         mc = PARISC_EXTRD_U;
1041                                         mc |= 31U | (((63 - bit) & 0x1f) << 5) | (((63 - bit) & 0x20) << 6);
1042                                         g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1043                                         return true;
1044                                 default:
1045                                         goto invalid;
1046                         }
1047                 }
1048         } else {
1049                 g(cgen_sar(ctx, true, arg3[0]));
1050                 if (size == OP_SIZE_4) {
1051                         switch (aux) {
1052                                 case BTX_BTS:
1053                                 case BTX_BTR:
1054                                         mc = PARISC_DEPWI_SAR;
1055                                         mc |= 31U;
1056                                         g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1057                                         return true;
1058                                 case BTX_BTEXT:
1059                                         mc = PARISC_EXTRW_U_SAR;
1060                                         mc |= 31U;
1061                                         g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1062                                         return true;
1063                                 default:
1064                                         goto invalid;
1065                         }
1066                 } else {
1067                         switch (aux) {
1068                                 case BTX_BTS:
1069                                 case BTX_BTR:
1070                                         mc = PARISC_DEPDI_SAR;
1071                                         mc |= 31U;
1072                                         g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1073                                         return true;
1074                                 case BTX_BTEXT:
1075                                         mc = PARISC_EXTRD_U_SAR;
1076                                         mc |= 31U;
1077                                         g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1078                                         return true;
1079                                 default:
1080                                         goto invalid;
1081                         }
1082                 }
1083         }
1085 invalid:
1086         internal(file_line, "cgen_btx: invalid arguments %02x, %02x, %02x, %u, %u", arg1[0], arg2[0], arg3[0], size, aux);
1087         return false;
1090 static bool attr_w cgen_cmp_cmov(struct codegen_context *ctx, unsigned op_size, unsigned cond)
1092         int32_t fc;
1093         uint32_t mc;
1094         int64_t imm;
1095         uint8_t *arg1 = ctx->code_position;
1096         uint8_t *arg2 = arg1 + arg_size(*arg1);
1097         uint8_t *arg3 = arg2 + arg_size(*arg2);
1098         uint8_t *arg4 = arg3 + arg_size(*arg3);
1099         uint8_t *arg5 = arg4 + arg_size(*arg4);
1100         ctx->code_position = arg5 + arg_size(*arg5);
1102         if (arg3[0] == ARG_IMM) {
1103                 cond = cmp_swap_arguments(cond);
1104         }
1106         fc = cmp_sub_cond[cond];
1107         fc ^= PARISC_COND_NEG;
1109         if (arg5[0] == ARG_IMM) {
1110                 imm = get_imm(&arg5[1]);
1111                 mc = PARISC_CMPICLR;
1112                 mc |= fc;
1113                 mc |= low_sign_ext_11(imm);
1114                 g(cgen_2reg(ctx, mc, arg4[0], R_ZERO));
1115         } else {
1116                 mc = PARISC_CMPCLR;
1117                 mc |= fc;
1118                 g(cgen_3reg(ctx, mc, arg4[0], arg5[0], R_ZERO));
1119         }
1121         g(cgen_mov_args(ctx, op_size, arg1, arg3));
1123         return true;
1126 static bool attr_w cgen_movr(struct codegen_context *ctx, unsigned cond)
1128         int32_t fc;
1129         uint32_t mc;
1130         uint8_t *arg1 = ctx->code_position;
1131         uint8_t *arg2 = arg1 + arg_size(*arg1);
1132         uint8_t *arg3 = arg2 + arg_size(*arg2);
1133         uint8_t *arg4 = arg3 + arg_size(*arg3);
1134         ctx->code_position = arg4 + arg_size(*arg4);
1136         fc = cmp_sub_cond[cond];
1137         fc ^= PARISC_COND_NEG;
1139         if (unlikely(arg1[0] != arg2[0]) || unlikely(arg1[0] >= 0x20))
1140                 internal(file_line, "cgen_movr: invalid arguments");
1142         mc = PARISC_ADD_L;
1143         mc |= fc;
1144         if (OP_SIZE_NATIVE == OP_SIZE_8)
1145                 mc |= PARISC_COND_64;
1147         g(cgen_3reg(ctx, mc, R_ZERO, arg3[0], R_ZERO));
1149         g(cgen_mov_args(ctx, OP_SIZE_NATIVE, arg1, arg4));
1151         return true;
1154 static bool attr_w cgen_fp_cmp_cond(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1156         uint32_t mc;
1157         unsigned cond;
1158         uint8_t *arg1 = ctx->code_position;
1159         uint8_t *arg2 = arg1 + arg_size(*arg1);
1160         ctx->code_position = arg2 + arg_size(*arg2);
1161         switch (aux) {
1162                 case FP_COND_P:         cond = PARISC_FCMP_P; break;
1163                 case FP_COND_NP:        cond = PARISC_FCMP_NP; break;
1164                 case FP_COND_E:         cond = PARISC_FCMP_E; break;
1165                 case FP_COND_NE:        cond = PARISC_FCMP_NE; break;
1166                 case FP_COND_A:         cond = PARISC_FCMP_A; break;
1167                 case FP_COND_BE:        cond = PARISC_FCMP_BE; break;
1168                 case FP_COND_B:         cond = PARISC_FCMP_B; break;
1169                 case FP_COND_AE:        cond = PARISC_FCMP_AE; break;
1170                 default:                internal(file_line, "cgen_fp_cmp_cond: invalid condition %u", aux);
1171                                         return false;
1172         }
1173         mc = PARISC_FCMP;
1174         if (op_size == OP_SIZE_8)
1175                 mc |= PARISC_FP_DOUBLE;
1176         g(cgen_3reg(ctx, mc, arg1[0] & 0x1f, arg2[0] & 0x1f, cond));
1177         return true;
1180 static bool attr_w cgen_fp_test_reg(struct codegen_context *ctx)
1182         unsigned reg = cget_one(ctx);
1183         uint32_t mc;
1185         mc = PARISC_LDO;
1186         mc |= low_sign_ext_14(1);
1187         g(cgen_2reg(ctx, mc, R_ZERO, reg));
1189         cgen_four(PARISC_FTEST);
1191         mc = PARISC_LDO;
1192         mc |= low_sign_ext_14(0);
1193         g(cgen_2reg(ctx, mc, R_ZERO, reg));
1195         return true;
1198 static bool attr_w cgen_fp_alu(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1200         uint32_t mc;
1201         uint8_t *arg1 = ctx->code_position;
1202         uint8_t *arg2 = arg1 + arg_size(*arg1);
1203         uint8_t *arg3 = arg2 + arg_size(*arg2);
1204         ctx->code_position = arg3 + arg_size(*arg3);
1205         switch (aux) {
1206                 case FP_ALU_ADD:        mc = PARISC_FADD; break;
1207                 case FP_ALU_SUB:        mc = PARISC_FSUB; break;
1208                 case FP_ALU_MUL:        mc = PARISC_FMPY; break;
1209                 case FP_ALU_DIV:        mc = PARISC_FDIV; break;
1210                 default:                internal(file_line, "cgen_fp_alu: invalid alu %u", aux);
1211         }
1212         switch (op_size) {
1213                 case OP_SIZE_4:         break;
1214                 case OP_SIZE_8:         mc |= PARISC_FP_DOUBLE; break;
1215                 default:                internal(file_line, "cgen_fp_alu: invalid size %u", op_size);
1216         }
1217         g(cgen_3reg(ctx, mc, arg3[0] & 0x1f, arg2[0] & 0x1f, arg1[0] & 0x1f));
1218         return true;
1221 static bool attr_w cgen_fp_alu1(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1223         uint32_t mc;
1224         uint8_t *arg1 = ctx->code_position;
1225         uint8_t *arg2 = arg1 + arg_size(*arg1);
1226         ctx->code_position = arg2 + arg_size(*arg2);
1227         switch (aux) {
1228                 case FP_ALU1_NEG:       mc = PARISC_FNEG; break;
1229                 case FP_ALU1_SQRT:      mc = PARISC_FSQRT; break;
1230                 default:                internal(file_line, "cgen_fp_alu1: invalid alu %u", aux);
1231         }
1232         switch (op_size) {
1233                 case OP_SIZE_4:         break;
1234                 case OP_SIZE_8:         mc |= PARISC_FP_DOUBLE; break;
1235                 default:                internal(file_line, "cgen_fp_alu: invalid size %u", op_size);
1236         }
1237         g(cgen_3reg(ctx, mc, 0, arg2[0] & 0x1f, arg1[0] & 0x1f));
1238         return true;
1241 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1243         uint32_t mc;
1244         uint8_t *arg1 = ctx->code_position;
1245         uint8_t *arg2 = arg1 + arg_size(*arg1);
1246         ctx->code_position = arg2 + arg_size(*arg2);
1248         mc = PARISC_FCNVFXT;
1249         if (int_op_size == OP_SIZE_8)
1250                 mc |= PARISC_FCNVFXT_TO_LONG;
1251         if (fp_op_size == OP_SIZE_8)
1252                 mc |= PARISC_FCNVFXT_FROM_DOUBLE;
1253         mc |= arg1[0] & 0x1f;
1254         mc |= (uint32_t)(arg2[0] & 0x1f) << 21;
1255         cgen_four(mc);
1256         return true;
1259 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1261         uint32_t mc;
1262         uint8_t *arg1 = ctx->code_position;
1263         uint8_t *arg2 = arg1 + arg_size(*arg1);
1264         ctx->code_position = arg2 + arg_size(*arg2);
1266         mc = PARISC_FCNVXF;
1267         if (int_op_size == OP_SIZE_8)
1268                 mc |= PARISC_FCNVXF_FROM_LONG;
1269         if (fp_op_size == OP_SIZE_8)
1270                 mc |= PARISC_FCNVXF_TO_DOUBLE;
1271         mc |= arg1[0] & 0x1f;
1272         mc |= (uint32_t)(arg2[0] & 0x1f) << 21;
1273         cgen_four(mc);
1274         return true;
1277 static bool attr_w cgen_cond_jmp(struct codegen_context *ctx, uint32_t mc, unsigned length, unsigned reg1, unsigned reg2, int reloc_offset)
1279         if (length == JMP_SHORTEST) {
1280                 bool known;
1281                 mc |= PARISC_N;
1282                 g(add_relocation(ctx, JMP_SHORTEST, reloc_offset, &known));
1283                 g(cgen_2reg(ctx, mc, reg2, reg1));
1284                 if (unlikely(!known))
1285                         cgen_four(PARISC_NOP);
1286         } else if (length == JMP_SHORT) {
1287                 mc |= PARISC_N;
1288                 g(cgen_2reg(ctx, mc, reg2, reg1));
1289                 g(add_relocation(ctx, JMP_SHORT, reloc_offset, NULL));
1290                 cgen_four(PARISC_BL | PARISC_N);
1291         } else if (length == JMP_LONG && PA_20) {
1292                 mc |= PARISC_N;
1293                 g(cgen_2reg(ctx, mc, reg2, reg1));
1294                 g(add_relocation(ctx, JMP_LONG, reloc_offset, NULL));
1295                 cgen_four(PARISC_BL_L | PARISC_N);
1296         } else {
1297                 mc |= PARISC_N;
1298                 mc |= assemble_12(3);
1299                 g(cgen_2reg(ctx, mc, reg2, reg1));
1300                 g(add_relocation(ctx, JMP_EXTRA_LONG, reloc_offset, NULL));
1301                 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
1302                 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
1303                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1304                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1305         }
1306         return true;
1309 static bool attr_w cgen_jmp_12regs(struct codegen_context *ctx, unsigned size, unsigned cond, unsigned length, unsigned reg1, unsigned reg2, int reloc_offset)
1311         int32_t fc;
1312         uint32_t mc;
1313         fc = cmp_sub_cond[cond];
1314         if (length > JMP_SHORTEST)
1315                 fc ^= PARISC_COND_NEG;
1316         if (size == OP_SIZE_4)
1317                 mc = !(fc & PARISC_COND_NEG) ? PARISC_CMPB : PARISC_CMPB_NOT;
1318         else
1319                 mc = !(fc & PARISC_COND_NEG) ? PARISC_CMPB_64 : PARISC_CMPB_64_NOT;
1320         mc |= ((uint32_t)fc & ~PARISC_COND_NEG);
1321         g(cgen_cond_jmp(ctx, mc, length, reg1, reg2, reloc_offset));
1322         return true;
1325 static bool attr_w cgen_jmp(struct codegen_context *ctx, unsigned length)
1327         if (length <= JMP_SHORT) {
1328                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1329                 cgen_four(PARISC_BL | PARISC_N);
1330         } else if (length == JMP_LONG && PA_20) {
1331                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1332                 cgen_four(PARISC_BL_L | PARISC_N);
1333         } else {
1334                 g(add_relocation(ctx, JMP_EXTRA_LONG, 0, NULL));
1335                 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
1336                 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
1337                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1338                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1339         }
1340         return true;
1343 static bool attr_w cgen_jmp_reg(struct codegen_context *ctx, unsigned size, unsigned cond, unsigned length)
1345         unsigned reg = cget_one(ctx);
1346         return cgen_jmp_12regs(ctx, size, cond, length, reg, 0, 1);
1349 static bool attr_w cgen_jmp_reg_bit(struct codegen_context *ctx, unsigned size, unsigned bit, bool jnz, unsigned length)
1351         uint32_t mc;
1352         unsigned reg = cget_one(ctx);
1353         if (length > JMP_SHORTEST)
1354                 jnz = !jnz;
1355         if (size == OP_SIZE_4 || bit < 32) {
1356                 bit = 31 - bit;
1357                 mc = jnz ? PARISC_BB_1 : PARISC_BB_0;
1358         } else {
1359                 bit = 63 - bit;
1360                 mc = jnz ? PARISC_BB_64_1 : PARISC_BB_64_0;
1361         }
1362         g(cgen_cond_jmp(ctx, mc, length, reg, bit, 1));
1363         return true;
1366 static bool attr_w cgen_jmp_2regs(struct codegen_context *ctx, unsigned size, unsigned cond, unsigned length)
1368         uint8_t *arg1 = ctx->code_position;
1369         uint8_t *arg2 = arg1 + arg_size(*arg1);
1370         ctx->code_position = arg2 + arg_size(*arg2);
1371         if (arg2[0] < 0x20)
1372                 return cgen_jmp_12regs(ctx, size, cond, length, arg1[0], arg2[0], 2);
1373         if (arg2[0] == ARG_IMM) {
1374                 int64_t imm = get_imm(&arg2[1]);
1375                 uint32_t mc;
1376                 int32_t fc;
1377                 cond = cmp_swap_arguments(cond);
1378                 fc = cmp_sub_cond[cond];
1379                 if (length > JMP_SHORTEST)
1380                         fc ^= PARISC_COND_NEG;
1381                 if (size == OP_SIZE_4) {
1382                         mc = fc & PARISC_COND_NEG ? PARISC_CMPIB_NOT : PARISC_CMPIB;
1383                         mc |= fc & ~PARISC_COND_NEG;
1384                 } else {
1385                         mc = PARISC_CMPIB_64;
1386                         switch (fc) {
1387                                 case PARISC_COND_EQUAL:         mc |= 1 << 13; break;
1388                                 case PARISC_COND_NOT_EQUAL:     mc |= 5 << 13; break;
1389                                 case PARISC_COND_L_S:           mc |= 2 << 13; break;
1390                                 case PARISC_COND_GE_S:          mc |= 6 << 13; break;
1391                                 case PARISC_COND_LE_S:          mc |= 3 << 13; break;
1392                                 case PARISC_COND_G_S:           mc |= 7 << 13; break;
1393                                 case PARISC_COND_L_U:           mc |= 0 << 13; break;
1394                                 case PARISC_COND_GE_U:          mc |= 4 << 13; break;
1395                                 default:        internal(file_line, "cgen_jmp_2regs: unsupported condition %x", fc);
1396                         }
1397                 }
1398                 g(cgen_cond_jmp(ctx, mc, length, low_sign_ext_5(imm), arg1[0], 10));
1399                 return true;
1400         }
1401         internal(file_line, "cgen_jmp_2regs: invalid arguments %02x, %02x", arg1[0], arg2[0]);
1402         return false;
1405 static bool attr_w cgen_jmp_fp_test(struct codegen_context *ctx, unsigned length)
1407         cgen_four(PARISC_FTEST);
1408         if (length <= JMP_SHORT) {
1409                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1410                 cgen_four(PARISC_BL | PARISC_N);
1411         } else if (length == JMP_LONG && PA_20) {
1412                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1413                 cgen_four(PARISC_BL_L | PARISC_N);
1414         } else {
1415                 cgen_four(PARISC_BL | PARISC_N | assemble_12(0));
1416                 cgen_four(PARISC_BL | PARISC_N | assemble_12(3));
1417                 g(add_relocation(ctx, JMP_EXTRA_LONG, 0, NULL));
1418                 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
1419                 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
1420                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1421                 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1422         }
1423         return true;
1426 static bool attr_w cgen_jmp_indirect(struct codegen_context *ctx, unsigned reg)
1428         uint32_t mc;
1429 #ifdef ARCH_PARISC32
1430         if (PA_20) {
1431                 if (PA_SPACES) {
1432                         mc = PARISC_BVE_RET;
1433                         mc |= (uint32_t)reg << 21;
1434                         cgen_four(mc);
1435                         mc = PARISC_STW_LONG;
1436                         mc |= low_sign_ext_14(-0x18);
1437                         g(cgen_2reg(ctx, mc, R_SP, R_RP));
1438                 } else {
1439                         mc = PARISC_BVE_RET;
1440                         mc |= (uint32_t)reg << 21;
1441                         mc |= PARISC_N;
1442                         cgen_four(mc);
1443                 }
1444         } else {
1445                 if (PA_SPACES) {
1446                         mc = PARISC_LDSID;
1447                         mc |= (uint32_t)reg << 21;
1448                         mc |= R_CG_SCRATCH;
1449                         cgen_four(mc);
1450                         mc = PARISC_MTSP;
1451                         mc |= (uint32_t)R_CG_SCRATCH << 16;
1452                         cgen_four(mc);
1453                         mc = PARISC_BE;
1454                         mc |= (uint32_t)reg << 21;
1455                         cgen_four(mc);
1456                         mc = PARISC_STW_LONG;
1457                         mc |= low_sign_ext_14(-0x18);
1458                         g(cgen_2reg(ctx, mc, R_SP, R_RP));
1459                 } else {
1460                         mc = PARISC_BV;
1461                         mc |= (uint32_t)reg << 21;
1462                         mc |= PARISC_N;
1463                         cgen_four(mc);
1464                 }
1465         }
1466 #else
1467         mc = PARISC_BV;
1468         mc |= (uint32_t)reg << 21;
1469         mc |= PARISC_N;
1470         cgen_four(mc);
1471 #endif
1472         if (unlikely(!ctx->fn))
1473                 cgen_four(PARISC_NOP);
1474         return true;
1477 static bool attr_w cgen_call_millicode(struct codegen_context attr_unused *ctx)
1479 #ifdef ARCH_PARISC32
1480         uint32_t mc;
1481         unsigned reg = R_SCRATCH_NA_1;
1482         unsigned bit;
1484         mc = PARISC_BB_0;
1485         bit = 31 - 1;
1486         mc |= assemble_12(1);
1487         mc |= PARISC_N;
1488         g(cgen_2reg(ctx, mc, bit, reg));
1490         mc = PARISC_LD_ST;
1491         mc |= PARISC_LD_ST_W;
1492         mc |= PARISC_LD_ST_IMM;
1493         mc |= PARISC_LD_ST_LD;
1494         g(cgen_3reg(ctx, mc, low_sign_ext_5(2), reg, R_19));
1495         g(cgen_3reg(ctx, mc, low_sign_ext_5(-2), reg, reg));
1497         g(cgen_jmp_indirect(ctx, reg));
1498 #endif
1499         return true;
1502 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1504         uint32_t mc;
1505         uint32_t mc4[4];
1506         int64_t offs = (int64_t)(ctx->label_to_pos[reloc->label_id] >> 2) - (int64_t)(reloc->position >> 2) - 2;
1507         switch (reloc->length) {
1508                 case JMP_SHORTEST:
1509                         if (unlikely(offs < -0x800) || unlikely(offs >= 0x800))
1510                                 return false;
1511                         memcpy(&mc, ctx->mcode + reloc->position, 4);
1512                         mc &= ~0x00001ffdU;
1513                         mc |= assemble_12(offs);
1514                         memcpy(ctx->mcode + reloc->position, &mc, 4);
1515                         return true;
1516                 case JMP_SHORT:
1517                         if (unlikely(offs < -0x10000) || unlikely(offs >= 0x10000))
1518                                 return false;
1519                         memcpy(&mc, ctx->mcode + reloc->position, 4);
1520                         mc &= ~0x001f1ffdU;
1521                         mc |= assemble_17(offs);
1522                         memcpy(ctx->mcode + reloc->position, &mc, 4);
1523                         return true;
1524                 case JMP_LONG:
1525                         if (unlikely(offs < -0x200000) || unlikely(offs >= 0x200000))
1526                                 return false;
1527                         memcpy(&mc, ctx->mcode + reloc->position, 4);
1528                         mc &= ~0x03ff1ffdU;
1529                         mc |= assemble_22(offs);
1530                         memcpy(ctx->mcode + reloc->position, &mc, 4);
1531                         return true;
1532                 case JMP_EXTRA_LONG:
1533                         offs -= 2;
1534                         if (unlikely(offs != (int32_t)offs))
1535                                 return false;
1536                         memcpy(&mc4, ctx->mcode + reloc->position, 16);
1537                         mc4[0] &= ~0x001fffffU;
1538                         mc4[0] |= assemble_21((uint64_t)offs >> 1 >> 11);
1539                         mc4[1] &= ~0x00003fffU;
1540                         mc4[1] |= low_sign_ext_14(((uint64_t)offs >> 1) & 0x7ff);
1541                         if (offs & 1)
1542                                 mc4[2] = PARISC_NOP;
1543                         else
1544                                 mc4[3] = PARISC_NOP;
1545                         memcpy(ctx->mcode + reloc->position, &mc4, 16);
1546                         return true;
1547                 default:
1548                         internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1549         }
1550         return false;
1553 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1555         /*debug("insn: %08x", insn);*/
1556         switch (insn_opcode(insn)) {
1557                 case INSN_ENTRY:
1558                         g(cgen_entry(ctx));
1559                         return true;
1560                 case INSN_LABEL:
1561                         g(cgen_label(ctx));
1562                         return true;
1563                 case INSN_RET:
1564                         g(cgen_ret(ctx));
1565                         return true;
1566                 case INSN_CALL:
1567                         g(cgen_call(ctx, insn_jump_size(insn)));
1568                         return true;
1569                 case INSN_CALL_INDIRECT:
1570                         g(cgen_call_indirect(ctx));
1571                         return true;
1572                 case INSN_MOV:
1573                         g(cgen_mov(ctx, insn_op_size(insn)));
1574                         return true;
1575                 case INSN_MOVSX:
1576                         g(cgen_movsx(ctx, insn_op_size(insn)));
1577                         return true;
1578                 case INSN_CMP_DEST_REG:
1579                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1580                                 goto invalid_insn;
1581                         g(cgen_cmp_dest_reg(ctx, insn_op_size(insn), insn_aux(insn)));
1582                         return true;
1583                 case INSN_ALU:
1584                 case INSN_ALU_FLAGS:
1585                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1586                                 goto invalid_insn;
1587                         g(cgen_alu(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), false, insn_jump_size(insn)));
1588                         return true;
1589                 case INSN_ALU_TRAP:
1590                 case INSN_ALU_FLAGS_TRAP:
1591                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1592                                 goto invalid_insn;
1593                         g(cgen_alu(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), true, insn_jump_size(insn)));
1594                         return true;
1595                 case INSN_ALU1:
1596                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1597                                 goto invalid_insn;
1598                         g(cgen_alu1(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), false, insn_jump_size(insn)));
1599                         return true;
1600                 case INSN_ALU1_TRAP:
1601                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1602                                 goto invalid_insn;
1603                         g(cgen_alu1(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), true, insn_jump_size(insn)));
1604                         return true;
1605                 case INSN_ROT:
1606                         if (unlikely(insn_op_size(insn) < OP_SIZE_4) || unlikely(insn_writes_flags(insn) != 0))
1607                                 goto invalid_insn;
1608                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1609                         return true;
1610                 case INSN_BTX:
1611                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1612                                 goto invalid_insn;
1613                         g(cgen_btx(ctx, insn_op_size(insn), insn_aux(insn)));
1614                         return true;
1615                 case INSN_CMP_CMOV:
1616                         if (unlikely(insn_writes_flags(insn) != 0))
1617                                 goto invalid_insn;
1618                         g(cgen_cmp_cmov(ctx, insn_op_size(insn), insn_aux(insn)));
1619                         return true;
1620                 case INSN_MOVR:
1621                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE) || unlikely(insn_writes_flags(insn) != 0))
1622                                 goto invalid_insn;
1623                         g(cgen_movr(ctx, insn_aux(insn)));
1624                         return true;
1625                 case INSN_FP_CMP_COND:
1626                         g(cgen_fp_cmp_cond(ctx, insn_op_size(insn), insn_aux(insn)));
1627                         return true;
1628                 case INSN_FP_TEST_REG:
1629                         g(cgen_fp_test_reg(ctx));
1630                         return true;
1631                 case INSN_FP_ALU:
1632                         g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1633                         return true;
1634                 case INSN_FP_ALU1:
1635                         g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1636                         return true;
1637                 case INSN_FP_TO_INT32:
1638                 case INSN_FP_TO_INT64:
1639                         g(cgen_fp_to_int(ctx, insn_opcode(insn) == INSN_FP_TO_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1640                         return true;
1641                 case INSN_FP_FROM_INT32:
1642                 case INSN_FP_FROM_INT64:
1643                         g(cgen_fp_from_int(ctx, insn_opcode(insn) == INSN_FP_FROM_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1644                         return true;
1645                 case INSN_JMP:
1646                         g(cgen_jmp(ctx, insn_jump_size(insn)));
1647                         return true;
1648                 case INSN_JMP_REG:
1649                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1650                                 goto invalid_insn;
1651                         g(cgen_jmp_reg(ctx, insn_op_size(insn), insn_aux(insn), insn_jump_size(insn)));
1652                         return true;
1653                 case INSN_JMP_REG_BIT:
1654                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1655                                 goto invalid_insn;
1656                         g(cgen_jmp_reg_bit(ctx, insn_op_size(insn), insn_aux(insn) & 63, insn_aux(insn) >> 6, insn_jump_size(insn)));
1657                         return true;
1658                 case INSN_JMP_2REGS:
1659                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1660                                 goto invalid_insn;
1661                         g(cgen_jmp_2regs(ctx, insn_op_size(insn), insn_aux(insn), insn_jump_size(insn)));
1662                         return true;
1663                 case INSN_JMP_FP_TEST:
1664                         g(cgen_jmp_fp_test(ctx, insn_jump_size(insn)));
1665                         return true;
1666                 case INSN_JMP_INDIRECT:
1667                         g(cgen_jmp_indirect(ctx, cget_one(ctx)));
1668                         return true;
1669                 case INSN_CALL_MILLICODE:
1670                         g(cgen_call_millicode(ctx));
1671                         return true;
1672                 default:
1673                 invalid_insn:
1674                         internal(file_line, "cgen_insn: invalid insn %08x", insn);
1675                         return false;
1676         }