codegen: use gen_frame_store for for bswap and brev
[ajla.git] / c2-riscv.inc
blob16482236c62a4e2d837081b3507fc61a88eca213
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 RISCV_LB                0x00000003U
20 #define RISCV_LH                0x00001003U
21 #define RISCV_LW                0x00002003U
22 #define RISCV_LD                0x00003003U
23 #define RISCV_LBU               0x00004003U
24 #define RISCV_LHU               0x00005003U
25 #define RISCV_LWU               0x00006003U
26 #define RISCV_FL                0x00000007U
27 #define  RISCV_FSL_H                    0x00001000U
28 #define  RISCV_FSL_W                    0x00002000U
29 #define  RISCV_FSL_D                    0x00003000U
30 #define  RISCV_FSL_Q                    0x00004000U
31 #define RISCV_ADDI              0x00000013U
32 #define RISCV_BSETI             0x28001013U
33 #define RISCV_BCLRI             0x48001013U
34 #define RISCV_CLZ               0x60001013U
35 #define RISCV_BINVI             0x68001013U
36 #define RISCV_CTZ               0x60101013U
37 #define RISCV_CPOP              0x60201013U
38 #define RISCV_SEXT_B            0x60401013U
39 #define RISCV_SEXT_H            0x60501013U
40 #define RISCV_BEXTI             0x48005013U
41 #define RISCV_REV8              0x6b805013U
42 #define RISCV_SLLI              0x00001013U
43 #define RISCV_SLTI              0x00002013U
44 #define RISCV_SLTIU             0x00003013U
45 #define RISCV_XORI              0x00004013U
46 #define RISCV_SRLI              0x00005013U
47 #define RISCV_SRAI              0x40005013U
48 #define RISCV_RORI              0x60005013U
49 #define RISCV_ORI               0x00006013U
50 #define RISCV_ANDI              0x00007013U
51 #define RISCV_AUIPC             0x00000017U
52 #define RISCV_ADDIW             0x0000001bU
53 #define RISCV_SLLIW             0x0000101bU
54 #define RISCV_SRLIW             0x0000501bU
55 #define RISCV_SRAIW             0x4000501bU
56 #define RISCV_CLZW              0x6000101bU
57 #define RISCV_CTZW              0x6010101bU
58 #define RISCV_CPOPW             0x6020101bU
59 #define RISCV_RORIW             0x6000501bU
60 #define RISCV_SB                0x00000023U
61 #define RISCV_SH                0x00001023U
62 #define RISCV_SW                0x00002023U
63 #define RISCV_SD                0x00003023U
64 #define RISCV_FS                0x00000027U
65 #define RISCV_ADD               0x00000033U
66 #define RISCV_MUL               0x02000033U
67 #define RISCV_SUB               0x40000033U
68 #define RISCV_SLL               0x00001033U
69 #define RISCV_MULH              0x02001033U
70 #define RISCV_BSET              0x28001033U
71 #define RISCV_BCLR              0x48001033U
72 #define RISCV_BINV              0x68001033U
73 #define RISCV_ROL               0x60001033U
74 #define RISCV_SLT               0x00002033U
75 #define RISCV_SH1ADD            0x20002033U
76 #define RISCV_SLTU              0x00003033U
77 #define RISCV_XOR               0x00004033U
78 #define RISCV_DIV               0x02004033U
79 #define RISCV_SH2ADD            0x20004033U
80 #define RISCV_SRL               0x00005033U
81 #define RISCV_DIVU              0x02005033U
82 #define RISCV_SRA               0x40005033U
83 #define RISCV_BEXT              0x48005033U
84 #define RISCV_ROR               0x60005033U
85 #define RISCV_OR                0x00006033U
86 #define RISCV_REM               0x02006033U
87 #define RISCV_SH3ADD            0x20006033U
88 #define RISCV_AND               0x00007033U
89 #define RISCV_REMU              0x02007033U
90 #define RISCV_ANDN              0x40007033U
91 #define RISCV_LUI               0x00000037U
92 #define RISCV_ADDW              0x0000003bU
93 #define RISCV_ADD_UW            0x0800003bU
94 #define RISCV_SUBW              0x4000003bU
95 #define RISCV_SLLW              0x0000103bU
96 #define RISCV_MULW              0x0200003bU
97 #define RISCV_ROLW              0x6000103bU
98 #define RISCV_DIVW              0x0200403bU
99 #define RISCV_ZEXT_H            0x0800403bU
100 #define RISCV_SRLW              0x0000503bU
101 #define RISCV_DIVUW             0x0200503bU
102 #define RISCV_SRAW              0x4000503bU
103 #define RISCV_RORW              0x6000503bU
104 #define RISCV_REMW              0x0200603bU
105 #define RISCV_REMUW             0x0200703bU
106 #define RISCV_FADD              0x00000053U
107 #define RISCV_FSUB              0x08000053U
108 #define RISCV_FMUL              0x10000053U
109 #define RISCV_FDIV              0x18000053U
110 #define RISCV_FSGNJ             0x20000053U
111 #define RISCV_FLE               0xa0000053U
112 #define RISCV_FCVT_TO_W         0xc0000053U
113 #define RISCV_FCVT_TO_L         0xc0200053U
114 #define RISCV_FCVT_FROM_W       0xd0000053U
115 #define RISCV_FCVT_FROM_L       0xd0200053U
116 #define RISCV_FSGNJN            0x20001053U
117 #define RISCV_FLT               0xa0001053U
118 #define RISCV_FSGNJX            0x20002053U
119 #define RISCV_FEQ               0xa0002053U
120 #define RISCV_FSQRT             0x58000053U
121 #define  RISCV_F_RNE                    0x00000000U
122 #define  RISCV_F_RTZ                    0x00001000U
123 #define  RISCV_F_RDN                    0x00002000U
124 #define  RISCV_F_RUP                    0x00003000U
125 #define  RISCV_F_RMM                    0x00004000U
126 #define  RISCV_F_DYN                    0x00007000U
127 #define  RISCV_F_SINGLE                 0x00000000U
128 #define  RISCV_F_DOUBLE                 0x02000000U
129 #define  RISCV_F_HALF                   0x04000000U
130 #define  RISCV_F_QUAD                   0x06000000U
131 #define RISCV_BEQ               0x00000063U
132 #define RISCV_BNE               0x00001063U
133 #define RISCV_BLT               0x00004063U
134 #define RISCV_BGE               0x00005063U
135 #define RISCV_BLTU              0x00006063U
136 #define RISCV_BGEU              0x00007063U
137 #define RISCV_JALR              0x00000067U
138 #define RISCV_JAL               0x0000006fU
140 #define RISCV_C_J               0xa001U
141 #define RISCV_C_BEQZ            0xc001U
142 #define RISCV_C_BNEZ            0xe001U
144 static bool cgen_rv_compress(struct codegen_context *ctx, uint32_t insn)
146          if (likely(cpu_test_feature(CPU_FEATURE_c))) {
147                 size_t result;
148                 uint16_t c;
149                 binary_search(size_t, n_array_elements(riscv_compress), result, riscv_compress[result].l == insn, riscv_compress[result].l < insn, goto uncompressed);
150                 c = riscv_compress[result].s;
151                 cgen_two(c);
152                 return true;
153          }
154 uncompressed:
155         cgen_four(insn);
156         return true;
159 #define cgen_rv(dword)                                  \
160 do {                                                    \
161         if (unlikely(!cgen_rv_compress(ctx, dword)))    \
162                 return false;                           \
163 } while (0)
166 static bool attr_w cgen_memory_load(struct codegen_context *ctx, uint32_t mc, unsigned rd, unsigned rs, int64_t imm)
168         if (unlikely(imm < -0x800) || unlikely(imm >= 0x800))
169                 internal(file_line, "cgen_memory_load: invalid immediate value %"PRIxMAX"", (uintmax_t)imm);
170         mc |= (uint32_t)rs << 15;
171         mc |= (uint32_t)rd << 7;
172         mc |= (uint32_t)imm << 20;
173         cgen_rv(mc);
174         return true;
177 static bool attr_w cgen_memory_store(struct codegen_context *ctx, uint32_t mc, unsigned rs1, unsigned rs2, int64_t imm)
179         if (unlikely(imm < -0x800) || unlikely(imm >= 0x800))
180                 internal(file_line, "cgen_memory_store: invalid immediate value %"PRIxMAX"", (uintmax_t)imm);
181         mc |= (uint32_t)rs1 << 15;
182         mc |= (uint32_t)rs2 << 20;
183         mc |= ((uint32_t)imm & 0x1f) << 7;
184         mc |= ((uint32_t)imm & 0xfe0) << 20;
185         cgen_rv(mc);
186         return true;
189 static bool attr_w cgen_jmp_call_indirect(struct codegen_context *ctx, bool call)
191         uint8_t reg = cget_one(ctx);
192         uint32_t mc;
193         mc = RISCV_JALR;
194         if (call)
195                 mc |= (uint32_t)R_RA << 7;
196         mc |= (uint32_t)reg << 15;
197         cgen_rv(mc);
198         return true;
201 static uint32_t riscv_fp_op_size(unsigned fp_op_size)
203         switch (fp_op_size) {
204                 case OP_SIZE_2:         return RISCV_F_HALF;
205                 case OP_SIZE_4:         return RISCV_F_SINGLE;
206                 case OP_SIZE_8:         return RISCV_F_DOUBLE;
207                 case OP_SIZE_16:        return RISCV_F_QUAD;
208                 default:                internal(file_line, "riscv_fp_op_size: invalid size %u", fp_op_size);
209         }
210         return (uint32_t)-1;
213 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
215         uint32_t mc;
216         int64_t imm;
217         uint8_t z = R_ZERO;
218         uint8_t *arg1 = ctx->code_position;
219         uint8_t *arg2 = arg1 + arg_size(*arg1);
220         ctx->code_position = arg2 + arg_size(*arg2);
221         if (arg1[0] < 0x20) {
222                 if (arg2[0] == ARG_IMM) {
223                         imm = get_imm(&arg2[1]);
224                         if (unlikely((imm & 0xfff) != 0) ||
225                             unlikely(imm < -0x80000000LL) ||
226                             unlikely(imm >= 0x80000000LL))
227                                 internal(file_line, "cgen_mov: invalid immediate value %"PRIxMAX"", (uintmax_t)imm);
228                         mc = RISCV_LUI;
229                         mc |= (uint32_t)arg1[0] << 7;
230                         mc |= (uint32_t)imm;
231                         cgen_rv(mc);
232                         return true;
233                 }
234                 if (arg2[0] == ARG_ADDRESS_1) {
235                         imm = get_imm(&arg2[2]);
236                         switch (size) {
237                                 case OP_SIZE_1: mc = RISCV_LBU; break;
238                                 case OP_SIZE_2: mc = RISCV_LHU; break;
239                                 case OP_SIZE_4: mc = RISCV_LWU; break;
240                                 case OP_SIZE_8: mc = RISCV_LD; break;
241                                 default:        goto invalid;
242                         }
243                         g(cgen_memory_load(ctx, mc, arg1[0], arg2[1], imm));
244                         return true;
245                 }
246                 if (arg2[0] < 0x20) {
247                         switch (size) {
248                                 case OP_SIZE_1: mc = RISCV_ANDI | ((uint32_t)0xff << 20); break;
249                                 case OP_SIZE_2: mc = RISCV_ZEXT_H; break;
250                                 case OP_SIZE_4: mc = RISCV_ADD_UW; break;
251                                 case OP_SIZE_8: mc = RISCV_ADDI; break;
252                                 default:        goto invalid;
253                         }
254                         mc |= (uint32_t)arg1[0] << 7;
255                         mc |= (uint32_t)arg2[0] << 15;
256                         cgen_rv(mc);
257                         return true;
258                 }
259                 goto invalid;
260         }
261         if (reg_is_fp(arg1[0])) {
262                 if (reg_is_fp(arg2[0])) {
263                         mc = RISCV_FSGNJ;
264                         mc |= (uint32_t)(arg1[0] & 0x1f) << 7;
265                         mc |= (uint32_t)(arg2[0] & 0x1f) << 15;
266                         mc |= (uint32_t)(arg2[0] & 0x1f) << 20;
267                         mc |= riscv_fp_op_size(size);
268                         cgen_rv(mc);
269                         return true;
270                 }
271                 if (arg2[0] == ARG_ADDRESS_1) {
272                         imm = get_imm(&arg2[2]);
273                         switch (size) {
274                                 case OP_SIZE_2: mc = RISCV_FL | RISCV_FSL_H; break;
275                                 case OP_SIZE_4: mc = RISCV_FL | RISCV_FSL_W; break;
276                                 case OP_SIZE_8: mc = RISCV_FL | RISCV_FSL_D; break;
277                                 case OP_SIZE_16:mc = RISCV_FL | RISCV_FSL_Q; break;
278                                 default:        goto invalid;
279                         }
280                         g(cgen_memory_load(ctx, mc, arg1[0] & 0x1f, arg2[1], imm));
281                         return true;
282                 }
283                 goto invalid;
284         }
285         if (arg1[0] == ARG_ADDRESS_1) {
286                 if (arg2[0] == ARG_IMM) {
287                         imm = get_imm(&arg2[1]);
288                         if (unlikely(imm != 0))
289                                 goto invalid;
290                         arg2 = &z;
291                 }
292                 if (arg2[0] < 0x20) {
293                         imm = get_imm(&arg1[2]);
294                         switch (size) {
295                                 case OP_SIZE_1: mc = RISCV_SB; break;
296                                 case OP_SIZE_2: mc = RISCV_SH; break;
297                                 case OP_SIZE_4: mc = RISCV_SW; break;
298                                 case OP_SIZE_8: mc = RISCV_SD; break;
299                                 default:        goto invalid;
300                         }
301                         g(cgen_memory_store(ctx, mc, arg1[1], arg2[0], imm));
302                         return true;
303                 }
304                 if (reg_is_fp(arg2[0])) {
305                         imm = get_imm(&arg1[2]);
306                         switch (size) {
307                                 case OP_SIZE_2: mc = RISCV_FS | RISCV_FSL_H; break;
308                                 case OP_SIZE_4: mc = RISCV_FS | RISCV_FSL_W; break;
309                                 case OP_SIZE_8: mc = RISCV_FS | RISCV_FSL_D; break;
310                                 case OP_SIZE_16:mc = RISCV_FS | RISCV_FSL_Q; break;
311                                 default:        goto invalid;
312                         }
313                         g(cgen_memory_store(ctx, mc, arg1[1], arg2[0] & 0x1f, imm));
314                         return true;
315                 }
316                 goto invalid;
317         }
319 invalid:
320         internal(file_line, "cgen_mov: invalid arguments %u, %02x, %02x", size, arg1[0], arg2[0]);
321         return false;
324 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
326         uint8_t *arg1, *arg2;
327         if (size == OP_SIZE_NATIVE) {
328                 g(cgen_mov(ctx, size));
329                 return true;
330         }
331         arg1 = ctx->code_position;
332         arg2 = arg1 + arg_size(*arg1);
333         ctx->code_position = arg2 + arg_size(*arg2);
335         if (unlikely(arg1[0] >= 0x20))
336                 goto invalid;
338         if (arg2[0] == ARG_ADDRESS_1) {
339                 uint32_t mc;
340                 switch (size) {
341                         case OP_SIZE_1: mc = RISCV_LB; break;
342                         case OP_SIZE_2: mc = RISCV_LH; break;
343                         case OP_SIZE_4: mc = RISCV_LW; break;
344                         default:        goto invalid;
345                 }
346                 g(cgen_memory_load(ctx, mc, arg1[0], arg2[1], get_imm(&arg2[2])));
347                 return true;
348         }
350         if (arg2[0] < 0x20) {
351                 uint32_t mc;
352                 switch (size) {
353                         case OP_SIZE_1: mc = RISCV_SEXT_B; break;
354                         case OP_SIZE_2: mc = RISCV_SEXT_H; break;
355                         case OP_SIZE_4: mc = RISCV_ADDIW; break;
356                         default:        goto invalid;
357                 }
358                 mc |= (uint32_t)arg1[0] << 7;
359                 mc |= (uint32_t)arg2[0] << 15;
360                 cgen_rv(mc);
361                 return true;
362         }
364 invalid:
365         internal(file_line, "cgen_movsx: invalid parameters %u, %02x, %02x", size, arg1[0], arg2[0]);
366         return false;
369 static bool attr_w cgen_cmp_dest_reg(struct codegen_context *ctx, unsigned aux)
371         uint32_t mc;
372         bool swap = false;
373         uint8_t z = R_ZERO;
374         uint8_t *arg1 = ctx->code_position;
375         uint8_t *arg2 = arg1 + arg_size(*arg1);
376         uint8_t *arg3 = arg2 + arg_size(*arg2);
377         ctx->code_position = arg3 + arg_size(*arg3);
378         if (arg3[0] == ARG_IMM) {
379                 int64_t imm = get_imm(&arg3[1]);
380                 if (unlikely(imm < -0x800) && unlikely(imm >= 0x800))
381                         internal(file_line, "cgen_cmp_dest_reg: invalid imm value %"PRIxMAX"", (intmax_t)imm);
382                 switch (aux) {
383                         case COND_B:            mc = RISCV_SLTIU; break;
384                         case COND_L:            mc = RISCV_SLTI; break;
385                         default:                internal(file_line, "cgen_cmp_dest_reg: invalid condition %u", aux);
386                 }
387                 mc |= (uint32_t)arg1[0] << 7;
388                 mc |= (uint32_t)arg2[0] << 15;
389                 mc |= (uint32_t)imm << 20;
390                 cgen_rv(mc);
391                 return true;
392         }
393         if (arg2[0] == ARG_IMM) {
394                 int64_t imm = get_imm(&arg2[1]);
395                 if (unlikely(imm != 0))
396                         internal(file_line, "cgen_cmp_dest_reg: non-zero second argument");
397                 arg2 = &z;
398         }
399         switch (aux) {
400                 case COND_B:            mc = RISCV_SLTU; break;
401                 case COND_A:            mc = RISCV_SLTU; swap = true; break;
402                 case COND_L:            mc = RISCV_SLT; break;
403                 case COND_G:            mc = RISCV_SLT; swap = true; break;
404                 default:                internal(file_line, "cgen_cmp_dest_reg: invalid condition %u", aux);
405         }
406         if (swap) {
407                 uint8_t *argx = arg2;
408                 arg2 = arg3;
409                 arg3 = argx;
410         }
411         mc |= (uint32_t)arg1[0] << 7;
412         mc |= (uint32_t)arg2[0] << 15;
413         mc |= (uint32_t)arg3[0] << 20;
414         cgen_rv(mc);
415         return true;
418 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned alu)
420         uint32_t mc;
421         uint8_t *arg1 = ctx->code_position;
422         uint8_t *arg2 = arg1 + arg_size(*arg1);
423         uint8_t *arg3 = arg2 + arg_size(*arg2);
424         ctx->code_position = arg3 + arg_size(*arg3);
426         if (arg3[0] == ARG_IMM) {
427                 int64_t imm = get_imm(&arg3[1]);
428                 if (alu == ALU_SUB) {
429                         imm = -(uint64_t)imm;
430                         alu = ALU_ADD;
431                 }
432                 if (unlikely(imm < -0x800) || unlikely(imm >= 0x800))
433                         internal(file_line, "cgen_alu: invalid imm value %"PRIxMAX"", (intmax_t)imm);
434                 switch (alu) {
435                         case ALU_ADD:   mc = size == OP_SIZE_8 ? RISCV_ADDI : RISCV_ADDIW; break;
436                         case ALU_XOR:   mc = RISCV_XORI; break;
437                         case ALU_OR:    mc = RISCV_ORI; break;
438                         case ALU_AND:   mc = RISCV_ANDI; break;
439                         default:        internal(file_line, "cgen_alu: invalid alu %u", alu);
440                 }
441                 mc |= (uint32_t)arg1[0] << 7;
442                 mc |= (uint32_t)arg2[0] << 15;
443                 mc |= (uint32_t)imm << 20;
444                 cgen_rv(mc);
445                 return true;
446         }
447         if (alu == ALU_ADD && arg3[0] == ARG_SHIFTED_REGISTER) {
448                 uint8_t *arg_swp = arg3;
449                 arg3 = arg2;
450                 arg2 = arg_swp;
451         }
452         if (arg2[0] == ARG_SHIFTED_REGISTER) {
453                 if (unlikely(alu != ALU_ADD) || unlikely(size != OP_SIZE_8))
454                         internal(file_line, "cgen_alu: invalid shifted alu %u, %u", alu, size);
455                 if (arg2[1] == (ARG_SHIFT_LSL | 0))
456                         mc = RISCV_ADD;
457                 else if (arg2[1] == (ARG_SHIFT_LSL | 1))
458                         mc = RISCV_SH1ADD;
459                 else if (arg2[1] == (ARG_SHIFT_LSL | 2))
460                         mc = RISCV_SH2ADD;
461                 else if (arg2[1] == (ARG_SHIFT_LSL | 3))
462                         mc = RISCV_SH3ADD;
463                 else
464                         internal(file_line, "cgen_alu: invalid shifted register operation: %02x", arg2[1]);
465                 mc |= (uint32_t)arg1[0] << 7;
466                 mc |= (uint32_t)arg2[2] << 15;
467                 mc |= (uint32_t)arg3[0] << 20;
468                 cgen_rv(mc);
469                 return true;
470         }
471         switch (alu) {
472                 case ALU_ADD:   mc = size == OP_SIZE_8 ? RISCV_ADD : RISCV_ADDW; break;
473                 case ALU_SUB:   mc = size == OP_SIZE_8 ? RISCV_SUB : RISCV_SUBW; break;
474                 case ALU_XOR:   mc = RISCV_XOR; break;
475                 case ALU_OR:    mc = RISCV_OR; break;
476                 case ALU_AND:   mc = RISCV_AND; break;
477                 case ALU_ANDN:  mc = RISCV_ANDN; break;
478                 case ALU_MUL:   mc = size == OP_SIZE_8 ? RISCV_MUL : RISCV_MULW; break;
479                 case ALU_SMULH: if (unlikely(size != OP_SIZE_8))
480                                         goto invalid;
481                                 mc = RISCV_MULH; break;
482                 case ALU_UDIV:  mc = size == OP_SIZE_8 ? RISCV_DIVU : RISCV_DIVUW; break;
483                 case ALU_SDIV:  mc = size == OP_SIZE_8 ? RISCV_DIV : RISCV_DIVW; break;
484                 case ALU_UREM:  mc = size == OP_SIZE_8 ? RISCV_REMU : RISCV_REMUW; break;
485                 case ALU_SREM:  mc = size == OP_SIZE_8 ? RISCV_REM : RISCV_REMW; break;
486                 invalid:
487                 default:        internal(file_line, "cgen_alu: invalid alu %u", alu);
488         }
489         mc |= (uint32_t)arg1[0] << 7;
490         mc |= (uint32_t)arg2[0] << 15;
491         mc |= (uint32_t)arg3[0] << 20;
492         cgen_rv(mc);
493         return true;
496 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned alu)
498         bool tgt20 = false;
499         uint32_t mc;
500         uint8_t *arg1 = ctx->code_position;
501         uint8_t *arg2 = arg1 + arg_size(*arg1);
502         ctx->code_position = arg2 + arg_size(*arg2);
503         switch (alu) {
504                 case ALU1_NOT:  mc = RISCV_XORI | ((uint32_t)-1 << 20); break;
505                 case ALU1_NEG:  mc = (size == OP_SIZE_8 ? RISCV_SUB : RISCV_SUBW); tgt20 = true; break;
506                 case ALU1_INC:  mc = (size == OP_SIZE_8 ? RISCV_ADDI : RISCV_ADDIW) | ((uint32_t)1 << 20); break;
507                 case ALU1_DEC:  mc = (size == OP_SIZE_8 ? RISCV_ADDI : RISCV_ADDIW) | ((uint32_t)-1 << 20); break;
508                 case ALU1_BSWAP:if (unlikely(size != OP_SIZE_8))
509                                         goto invalid;
510                                 mc = RISCV_REV8; break;
511                 case ALU1_BSF:  mc = size == OP_SIZE_8 ? RISCV_CTZ : RISCV_CTZW; break;
512                 case ALU1_LZCNT:mc = size == OP_SIZE_8 ? RISCV_CLZ : RISCV_CLZW; break;
513                 case ALU1_POPCNT:mc = size == OP_SIZE_8 ? RISCV_CPOP : RISCV_CPOPW; break;
514                 invalid:
515                 default:        internal(file_line, "cgen_alu1: invalid alu %u", alu);
516                                 return false;
517         }
518         mc |= (uint32_t)arg1[0] << 7;
519         mc |= (uint32_t)arg2[0] << (tgt20 ? 20 : 15);
520         cgen_rv(mc);
521         return true;
524 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, unsigned alu)
526         uint32_t mc;
527         uint8_t *arg1 = ctx->code_position;
528         uint8_t *arg2 = arg1 + arg_size(*arg1);
529         uint8_t *arg3 = arg2 + arg_size(*arg2);
530         ctx->code_position = arg3 + arg_size(*arg3);
531         if (arg3[0] == ARG_IMM) {
532                 int64_t imm = get_imm(&arg3[1]);
533                 if (alu == ROT_ROL)
534                         imm = -(uint64_t)imm;
535                 imm &= size == OP_SIZE_4 ? 0x1f : 0x3f;
536                 switch (alu) {
537                         case ROT_ROL:   mc = size == OP_SIZE_4 ? RISCV_RORIW : RISCV_RORI; break;
538                         case ROT_ROR:   mc = size == OP_SIZE_4 ? RISCV_RORIW : RISCV_RORI; break;
539                         case ROT_SHL:   mc = size == OP_SIZE_4 ? RISCV_SLLIW : RISCV_SLLI; break;
540                         case ROT_SHR:   mc = size == OP_SIZE_4 ? RISCV_SRLIW : RISCV_SRLI; break;
541                         case ROT_SAR:   mc = size == OP_SIZE_4 ? RISCV_SRAIW : RISCV_SRAI; break;
542                         default:        internal(file_line, "cgen_rot: invalid alu %u", alu);
543                 }
544                 mc |= (uint32_t)arg1[0] << 7;
545                 mc |= (uint32_t)arg2[0] << 15;
546                 mc |= (uint32_t)imm << 20;
547                 cgen_rv(mc);
548                 return true;
549         }
550         switch (alu) {
551                 case ROT_ROL:   mc = size == OP_SIZE_4 ? RISCV_ROLW : RISCV_ROL; break;
552                 case ROT_ROR:   mc = size == OP_SIZE_4 ? RISCV_RORW : RISCV_ROR; break;
553                 case ROT_SHL:   mc = size == OP_SIZE_4 ? RISCV_SLLW : RISCV_SLL; break;
554                 case ROT_SHR:   mc = size == OP_SIZE_4 ? RISCV_SRLW : RISCV_SRL; break;
555                 case ROT_SAR:   mc = size == OP_SIZE_4 ? RISCV_SRAW : RISCV_SRA; break;
556                 default:        internal(file_line, "cgen_rot: invalid alu %u", alu);
557         }
558         mc |= (uint32_t)arg1[0] << 7;
559         mc |= (uint32_t)arg2[0] << 15;
560         mc |= (uint32_t)arg3[0] << 20;
561         cgen_rv(mc);
562         return true;
565 static bool attr_w cgen_btx(struct codegen_context *ctx, unsigned alu)
567         uint32_t mc;
568         uint8_t *arg1 = ctx->code_position;
569         uint8_t *arg2 = arg1 + arg_size(*arg1);
570         uint8_t *arg3 = arg2 + arg_size(*arg2);
571         ctx->code_position = arg3 + arg_size(*arg3);
572         if (arg3[0] == ARG_IMM) {
573                 int64_t imm = get_imm(&arg3[1]) & 0x3f;
574                 switch (alu) {
575                         case BTX_BTS:   mc = RISCV_BSETI; break;
576                         case BTX_BTR:   mc = RISCV_BCLRI; break;
577                         case BTX_BTC:   mc = RISCV_BINVI; break;
578                         case BTX_BTEXT: mc = RISCV_BEXTI; break;
579                         default:        internal(file_line, "cgen_btx: invalid alu %u", alu);
580                 }
581                 mc |= (uint32_t)arg1[0] << 7;
582                 mc |= (uint32_t)arg2[0] << 15;
583                 mc |= (uint32_t)imm << 20;
584                 cgen_rv(mc);
585                 return true;
586         }
587         switch (alu) {
588                 case BTX_BTS:   mc = RISCV_BSET; break;
589                 case BTX_BTR:   mc = RISCV_BCLR; break;
590                 case BTX_BTC:   mc = RISCV_BINV; break;
591                 case BTX_BTEXT: mc = RISCV_BEXT; break;
592                 default:        internal(file_line, "cgen_btx: invalid alu %u", alu);
593         }
594         mc |= (uint32_t)arg1[0] << 7;
595         mc |= (uint32_t)arg2[0] << 15;
596         mc |= (uint32_t)arg3[0] << 20;
597         cgen_rv(mc);
598         return true;
601 static bool attr_w cgen_fp_cmp_dest_reg(struct codegen_context *ctx, unsigned op_size, unsigned aux)
603         uint32_t mc;
604         bool swap = false;
605         uint8_t *arg1 = ctx->code_position;
606         uint8_t *arg2 = arg1 + arg_size(*arg1);
607         uint8_t *arg3 = arg2 + arg_size(*arg2);
608         ctx->code_position = arg3 + arg_size(*arg3);
609         switch (aux) {
610                 case FP_COND_E:         mc = RISCV_FEQ; break;
611                 case FP_COND_A:         mc = RISCV_FLT; swap = true; break;
612                 case FP_COND_BE:        mc = RISCV_FLE; break;
613                 case FP_COND_B:         mc = RISCV_FLT; break;
614                 case FP_COND_AE:        mc = RISCV_FLE; swap = true; break;
615                 default:                internal(file_line, "cgen_fp_cmp_dest_reg: invalid condition %u", aux);
616         }
617         if (swap) {
618                 uint8_t *argx = arg2;
619                 arg2 = arg3;
620                 arg3 = argx;
621         }
622         switch (op_size) {
623                 case OP_SIZE_2:         mc |= RISCV_F_HALF; break;
624                 case OP_SIZE_4:         mc |= RISCV_F_SINGLE; break;
625                 case OP_SIZE_8:         mc |= RISCV_F_DOUBLE; break;
626                 case OP_SIZE_16:        mc |= RISCV_F_QUAD; break;
627                 default:                internal(file_line, "cgen_fp_cmp_dest_reg: invalid size %u", op_size);
628         }
629         mc |= (uint32_t)arg1[0] << 7;
630         mc |= (uint32_t)(arg2[0] & 0x1f) << 15;
631         mc |= (uint32_t)(arg3[0] & 0x1f) << 20;
632         cgen_rv(mc);
633         return true;
636 static bool attr_w cgen_fp_alu(struct codegen_context *ctx, unsigned op_size, unsigned aux)
638         uint32_t mc;
639         uint8_t *arg1 = ctx->code_position;
640         uint8_t *arg2 = arg1 + arg_size(*arg1);
641         uint8_t *arg3 = arg2 + arg_size(*arg2);
642         ctx->code_position = arg3 + arg_size(*arg3);
643         switch (aux) {
644                 case FP_ALU_ADD:        mc = RISCV_FADD; break;
645                 case FP_ALU_SUB:        mc = RISCV_FSUB; break;
646                 case FP_ALU_MUL:        mc = RISCV_FMUL; break;
647                 case FP_ALU_DIV:        mc = RISCV_FDIV; break;
648                 default:                internal(file_line, "cgen_fp_alu: invalid alu %u", aux);
649         }
650         mc |= RISCV_F_RNE;
651         mc |= riscv_fp_op_size(op_size);
652         mc |= (uint32_t)(arg1[0] & 0x1f) << 7;
653         mc |= (uint32_t)(arg2[0] & 0x1f) << 15;
654         mc |= (uint32_t)(arg3[0] & 0x1f) << 20;
655         cgen_rv(mc);
656         return true;
659 static bool attr_w cgen_fp_alu1(struct codegen_context *ctx, unsigned op_size, unsigned aux)
661         uint32_t mc;
662         uint8_t *arg1 = ctx->code_position;
663         uint8_t *arg2 = arg1 + arg_size(*arg1);
664         ctx->code_position = arg2 + arg_size(*arg2);
665         switch (aux) {
666                 case FP_ALU1_NEG:       mc = RISCV_FSGNJN;
667                                         mc |= (uint32_t)(arg1[0] & 0x1f) << 7;
668                                         mc |= (uint32_t)(arg2[0] & 0x1f) << 15;
669                                         mc |= (uint32_t)(arg2[0] & 0x1f) << 20;
670                                         break;
671                 case FP_ALU1_SQRT:      mc = RISCV_FSQRT;
672                                         mc |= (uint32_t)(arg1[0] & 0x1f) << 7;
673                                         mc |= (uint32_t)(arg2[0] & 0x1f) << 15;
674                                         mc |= RISCV_F_RNE;
675                                         break;
676                 default:                internal(file_line, "cgen_fp_alu1: invalid alu %u", aux);
677         }
678         mc |= riscv_fp_op_size(op_size);
679         cgen_rv(mc);
680         return true;
683 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
685         uint32_t mc;
686         uint8_t *arg1 = ctx->code_position;
687         uint8_t *arg2 = arg1 + arg_size(*arg1);
688         ctx->code_position = arg2 + arg_size(*arg2);
689         switch (int_op_size) {
690                 case OP_SIZE_4: mc = RISCV_FCVT_TO_W; break;
691                 case OP_SIZE_8: mc = RISCV_FCVT_TO_L; break;
692                 default:        internal(file_line, "cgen_fp_to_int: invalid int size %u", int_op_size);
693         }
694         mc |= RISCV_F_RTZ;
695         mc |= riscv_fp_op_size(fp_op_size);
696         mc |= (uint32_t)arg1[0] << 7;
697         mc |= (uint32_t)(arg2[0] & 0x1f) << 15;
698         cgen_rv(mc);
699         return true;
702 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
704         uint32_t mc;
705         uint8_t *arg1 = ctx->code_position;
706         uint8_t *arg2 = arg1 + arg_size(*arg1);
707         ctx->code_position = arg2 + arg_size(*arg2);
708         switch (int_op_size) {
709                 case OP_SIZE_4: mc = RISCV_FCVT_FROM_W; break;
710                 case OP_SIZE_8: mc = RISCV_FCVT_FROM_L; break;
711                 default:        internal(file_line, "cgen_fp_from_int: invalid int size %u", int_op_size);
712         }
713         mc |= RISCV_F_RNE;
714         mc |= riscv_fp_op_size(fp_op_size);
715         mc |= (uint32_t)(arg1[0] & 0x1f) << 7;
716         mc |= (uint32_t)arg2[0] << 15;
717         cgen_rv(mc);
718         return true;
721 static bool attr_w cgen_jmp(struct codegen_context *ctx, unsigned length)
723         if (length == JMP_SHORTEST && likely(cpu_test_feature(CPU_FEATURE_c))) {
724                 g(add_relocation(ctx, JMP_SHORTEST, 0, NULL));
725                 cgen_two(RISCV_C_J);
726         } else if (length <= JMP_LONG) {
727                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
728                 cgen_four(RISCV_JAL);
729         } else if (length == JMP_EXTRA_LONG) {
730                 g(add_relocation(ctx, JMP_EXTRA_LONG, 0, NULL));
731                 cgen_four(RISCV_AUIPC | ((uint32_t)R_CONST_HELPER << 7));
732                 cgen_four(RISCV_JALR | ((uint32_t)R_CONST_HELPER << 15));
733         } else {
734                 internal(file_line, "cgen_jmp: invalid length %u", length);
735         }
736         return true;
739 static bool attr_w cgen_jmp_12regs(struct codegen_context *ctx, unsigned cond, unsigned length, unsigned reg1, unsigned reg2, int reloc_offset)
741         uint32_t mc;
742         bool swap = false;
743         if (length > JMP_SHORT)
744                 cond ^= 1;
745         switch (cond) {
746                 case COND_B:    mc = RISCV_BLTU; break;
747                 case COND_AE:   mc = RISCV_BGEU; break;
748                 case COND_E:    mc = RISCV_BEQ; break;
749                 case COND_NE:   mc = RISCV_BNE; break;
750                 case COND_BE:   mc = RISCV_BGEU; swap = true; break;
751                 case COND_A:    mc = RISCV_BLTU; swap = true; break;
752                 case COND_S:
753                 case COND_L:    mc = RISCV_BLT; break;
754                 case COND_NS:
755                 case COND_GE:   mc = RISCV_BGE; break;
756                 case COND_LE:   mc = RISCV_BGE; swap = true; break;
757                 case COND_G:    mc = RISCV_BLT; swap = true; break;
758                 default:        goto invalid;
759         }
760         if (swap) {
761                 unsigned regx = reg1;
762                 reg1 = reg2;
763                 reg2 = regx;
764         }
766         mc |= (uint32_t)reg1 << 15;
767         mc |= (uint32_t)reg2 << 20;
769         if (length == JMP_SHORTEST && (cond == COND_E || cond == COND_NE) && (reg1 & 0x18) == 0x8 && reg2 == R_ZERO && cpu_test_feature(CPU_FEATURE_c)) {
770                 uint16_t mc2 = cond == COND_E ? RISCV_C_BEQZ : RISCV_C_BNEZ;
771                 mc2 |= ((uint16_t)reg1 & 0x7) << 7;
772                 g(add_relocation(ctx, JMP_SHORTEST, reloc_offset, NULL));
773                 cgen_two(mc2);
774         } else if (length <= JMP_SHORT) {
775                 g(add_relocation(ctx, JMP_SHORT, reloc_offset, NULL));
776                 cgen_four(mc);
777         } else if (length == JMP_LONG) {
778                 mc |= 0x400;
779                 cgen_four(mc);
780                 g(add_relocation(ctx, JMP_LONG, reloc_offset, NULL));
781                 mc = RISCV_JAL;
782                 cgen_four(mc);
783         } else if (length == JMP_EXTRA_LONG) {
784                 mc |= 0x600;
785                 cgen_four(mc);
786                 g(add_relocation(ctx, JMP_EXTRA_LONG, reloc_offset, NULL));
787                 cgen_four(RISCV_AUIPC | ((uint32_t)R_CONST_HELPER << 7));
788                 cgen_four(RISCV_JALR | ((uint32_t)R_CONST_HELPER << 15));
789         } else {
790                 internal(file_line, "cgen_jmp_12regs: invalid length %u", length);
791         }
792         return true;
794 invalid:
795         internal(file_line, "cgen_jmp_12regs: invalid arguments %u, %02x, %02x", cond, reg1, reg2);
796         return false;
799 static bool attr_w cgen_jmp_reg(struct codegen_context *ctx, unsigned cond, unsigned length)
801         uint8_t *arg1 = ctx->code_position;
802         ctx->code_position = arg1 + arg_size(*arg1);
803         if (arg1[0] < 0x20) {
804                 return cgen_jmp_12regs(ctx, cond, length, arg1[0], R_ZERO, 1);
805         }
806         internal(file_line, "cgen_jmp_reg: invalid argument %02x", arg1[0]);
807         return false;
810 static bool attr_w cgen_jmp_2regs(struct codegen_context *ctx, unsigned cond, unsigned length)
812         uint8_t *arg1 = ctx->code_position;
813         uint8_t *arg2 = arg1 + arg_size(*arg1);
814         ctx->code_position = arg2 + arg_size(*arg2);
815         if (arg1[0] < 0x20 && arg2[0] < 0x20) {
816                 return cgen_jmp_12regs(ctx, cond, length, arg1[0], arg2[0], 2);
817         }
818         internal(file_line, "cgen_jmp_2regs: invalid arguments %02x, %02x", arg1[0], arg2[0]);
819         return false;
823 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
825         uint16_t mc2;
826         uint32_t mc;
827         uint64_t mc8;
828         int64_t offs = (int64_t)(ctx->label_to_pos[reloc->label_id] >> 1) - (int64_t)(reloc->position >> 1);
829         switch (reloc->length) {
830                 case JMP_SHORTEST:
831                         memcpy(&mc2, ctx->mcode + reloc->position, 2);
832                         if ((mc2 & 0xe003) == RISCV_C_J) {
833                                 if (unlikely(offs < -0x400) || unlikely(offs >= 0x400))
834                                         return false;
835                                 mc2 &= 0xe003;
836                                 mc2 |= ((uint32_t)offs & 0x7) << 3;
837                                 mc2 |= ((uint32_t)offs & 0x8) << 8;
838                                 mc2 |= ((uint32_t)offs & 0x10) >> 2;
839                                 mc2 |= ((uint32_t)offs & 0x20) << 2;
840                                 mc2 |= ((uint32_t)offs & 0x40);
841                                 mc2 |= ((uint32_t)offs & 0x180) << 2;
842                                 mc2 |= ((uint32_t)offs & 0x200) >> 1;
843                                 mc2 |= ((uint32_t)offs & 0x400) << 2;
844                         } else if ((mc2 & 0xe003) == RISCV_C_BEQZ || (mc2 & 0xe003) == RISCV_C_BNEZ) {
845                                 if (unlikely(offs < -0x80) || unlikely(offs >= 0x80))
846                                         return false;
847                                 mc2 &= 0xe383;
848                                 mc2 |= ((uint32_t)offs & 0x3) << 3;
849                                 mc2 |= ((uint32_t)offs & 0xc) << 8;
850                                 mc2 |= ((uint32_t)offs & 0x10) >> 2;
851                                 mc2 |= ((uint32_t)offs & 0x60);
852                                 mc2 |= ((uint32_t)offs & 0x80) << 5;
853                         } else {
854                                 internal(file_line, "resolve_relocation: invalid 2-byte instruction %04x", mc2);
855                         }
856                         memcpy(ctx->mcode + reloc->position, &mc2, 2);
857                         return true;
858                 case JMP_SHORT:
859                         if (unlikely(offs < -0x800) || unlikely(offs >= 0x800))
860                                 return false;
861                         memcpy(&mc, ctx->mcode + reloc->position, 4);
862                         mc &= 0x01fff07fU;
863                         mc |= ((uint32_t)offs & 0xf) << (8 - 0);
864                         mc |= ((uint32_t)offs & 0x3f0) << (25 - 4);
865                         mc |= ((uint32_t)offs & 0x400) >> (10 - 7);
866                         mc |= ((uint32_t)offs & 0x800) << (31 - 11);
867                         memcpy(ctx->mcode + reloc->position, &mc, 4);
868                         return true;
869                 case JMP_LONG:
870                         if (unlikely(offs < -0x80000) || unlikely(offs >= 0x80000))
871                                 return false;
872                         memcpy(&mc, ctx->mcode + reloc->position, 4);
873                         mc &= 0x00000fffU;
874                         mc |= ((uint32_t)offs & 0x3ff) << (21 - 0);
875                         mc |= ((uint32_t)offs & 0x400) << (20 - 10);
876                         mc |= ((uint32_t)offs & 0x7f800) << (12 - 11);
877                         mc |= ((uint32_t)offs & 0x80000) << (31 - 19);
878                         memcpy(ctx->mcode + reloc->position, &mc, 4);
879                         return true;
880                 case JMP_EXTRA_LONG:
881                         offs = (uint64_t)offs << 1;
882                         memcpy(&mc8, ctx->mcode + reloc->position, 8);
883                         mc8 &= 0x000fffff00000fffULL;
884                         mc8 |= ((uint64_t)offs & 0xfffULL) << (32 + 20);
885                         if (offs & 0x800) {
886                                 offs = (uint64_t)offs + 0x1000;
887                         }
888                         if (unlikely(offs < -0x80000000LL) || unlikely(offs >= 0x80000000LL))
889                                 return false;
890                         mc8 |= ((uint64_t)offs & 0xfffff000ULL);
891                         memcpy(ctx->mcode + reloc->position, &mc8, 8);
892                         return true;
893                 default:
894                         internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
895         }
896         return false;
899 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
901         if (unlikely(insn_writes_flags(insn)))
902                 goto invalid_insn;
903         /*debug("insn: %08x", (unsigned)insn);*/
904         switch (insn_opcode(insn)) {
905                 case INSN_ENTRY:
906                         g(cgen_entry(ctx));
907                         return true;
908                 case INSN_LABEL:
909                         g(cgen_label(ctx));
910                         return true;
911                 case INSN_RET:
912                         cgen_rv(RISCV_JALR | ((uint32_t)R_RA << 15));
913                         return true;
914                 case INSN_CALL_INDIRECT:
915                         g(cgen_jmp_call_indirect(ctx, true));
916                         return true;
917                 case INSN_MOV:
918                         g(cgen_mov(ctx, insn_op_size(insn)));
919                         return true;
920                 case INSN_MOVSX:
921                         g(cgen_movsx(ctx, insn_op_size(insn)));
922                         return true;
923                 case INSN_CMP_DEST_REG:
924                         if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
925                                 goto invalid_insn;
926                         g(cgen_cmp_dest_reg(ctx, insn_aux(insn)));
927                         return true;
928                 case INSN_ALU:
929                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
930                                 goto invalid_insn;
931                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn)));
932                         return true;
933                 case INSN_ALU1:
934                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
935                                 goto invalid_insn;
936                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
937                         return true;
938                 case INSN_ROT:
939                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
940                                 goto invalid_insn;
941                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
942                         return true;
943                 case INSN_BTX:
944                         if (unlikely(insn_op_size(insn) != OP_SIZE_8))
945                                 goto invalid_insn;
946                         g(cgen_btx(ctx, insn_aux(insn)));
947                         return true;
948                 case INSN_FP_CMP_DEST_REG:
949                         g(cgen_fp_cmp_dest_reg(ctx, insn_op_size(insn), insn_aux(insn)));
950                         return true;
951                 case INSN_FP_ALU:
952                         g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
953                         return true;
954                 case INSN_FP_ALU1:
955                         g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
956                         return true;
957                 case INSN_FP_TO_INT32:
958                 case INSN_FP_TO_INT64:
959                         g(cgen_fp_to_int(ctx, insn_opcode(insn) == INSN_FP_TO_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
960                         return true;
961                 case INSN_FP_FROM_INT32:
962                 case INSN_FP_FROM_INT64:
963                         g(cgen_fp_from_int(ctx, insn_opcode(insn) == INSN_FP_FROM_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
964                         return true;
965                 case INSN_JMP:
966                         g(cgen_jmp(ctx, insn_jump_size(insn)));
967                         return true;
968                 case INSN_JMP_REG:
969                         if (unlikely(insn_op_size(insn) != OP_SIZE_8))
970                                 goto invalid_insn;
971                         g(cgen_jmp_reg(ctx, insn_aux(insn), insn_jump_size(insn)));
972                         return true;
973                 case INSN_JMP_2REGS:
974                         if (unlikely(insn_op_size(insn) != OP_SIZE_8))
975                                 goto invalid_insn;
976                         g(cgen_jmp_2regs(ctx, insn_aux(insn), insn_jump_size(insn)));
977                         return true;
978                 case INSN_JMP_INDIRECT:
979                         g(cgen_jmp_call_indirect(ctx, false));
980                         return true;
981                 default:
982                 invalid_insn:
983                         internal(file_line, "cgen_insn: invalid insn %08x in %s", insn, da(ctx->fn,function)->function_name);
984                         return false;
985         }