2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #define IA64_A_ALU 0x10000000000ULL
20 #define IA64_A_ALU_ADD 0x00000000000ULL
21 #define IA64_A_ALU_SUB 0x00028000000ULL
22 #define IA64_A_ALU_AND 0x00060000000ULL
23 #define IA64_A_ALU_ANDCM 0x00068000000ULL
24 #define IA64_A_ALU_OR 0x00070000000ULL
25 #define IA64_A_ALU_XOR 0x00078000000ULL
26 #define IA64_A_SHLADD 0x10080000000ULL
27 #define IA64_A_ADD_IMM14 0x10800000000ULL
28 #define IA64_A_ALU_IMM8 0x10000000000ULL
29 #define IA64_A_ALU_IMM8_SUB 0x00128000000ULL
30 #define IA64_A_ALU_IMM8_AND 0x00160000000ULL
31 #define IA64_A_ALU_IMM8_ANDCM 0x00168000000ULL
32 #define IA64_A_ALU_IMM8_OR 0x00170000000ULL
33 #define IA64_A_ALU_IMM8_XOR 0x00178000000ULL
34 #define IA64_A_ADD_IMM22 0x12000000000ULL
35 #define IA64_A_CMP_LT 0x18000000000ULL
36 #define IA64_A_CMP_LT_IMM8 0x18800000000ULL
37 #define IA64_A_CMP_LTU 0x1a000000000ULL
38 #define IA64_A_CMP_LTU_IMM8 0x1a800000000ULL
39 #define IA64_A_CMP_EQ 0x1c000000000ULL
40 #define IA64_A_CMP_EQ_IMM8 0x1c800000000ULL
41 #define IA64_A_CMP4 0x00400000000ULL
43 #define IA64_I_ZXT1 0x00080000000ULL
44 #define IA64_I_ZXT2 0x00088000000ULL
45 #define IA64_I_ZXT4 0x00090000000ULL
46 #define IA64_I_SXT1 0x000a0000000ULL
47 #define IA64_I_SXT2 0x000a8000000ULL
48 #define IA64_I_SXT4 0x000b0000000ULL
49 #define IA64_I_NOP 0x00008000000ULL
50 #define IA64_I_MOV_TO_AR 0x00150000000ULL
51 #define IA64_I_MOV_TO_AR_PFS 0x00004000000ULL
52 #define IA64_I_MOVE_FROM_BR 0x00188000000ULL
53 #define IA64_I_MOVE_TO_BR 0x00e00000000ULL
54 #define IA64_I_DEP 0x08000000000ULL
55 #define IA64_I_TBIT 0x0a000000000ULL
56 #define IA64_I_EXTR_U 0x0a400000000ULL
57 #define IA64_I_EXTR 0x0a400002000ULL
58 #define IA64_I_DEP_Z 0x0a600000000ULL
59 #define IA64_I_DEP_Z_IMM 0x0a604000000ULL
60 #define IA64_I_DEP_IMM 0x0ae00000000ULL
61 #define IA64_I_POPCNT 0x0e690000000ULL
62 #define IA64_I_MUX1_REV 0x0eca0b00000ULL
63 #define IA64_I_SHR_U 0x0f200000000ULL
64 #define IA64_I_SHR 0x0f220000000ULL
65 #define IA64_I_SHL 0x0f240000000ULL
67 #define IA64_M_NOP 0x00008000000ULL
68 #define IA64_M_ALLOC 0x02c00000000ULL
69 #define IA64_M_LD1 0x08000000000ULL
70 #define IA64_M_LD2 0x08040000000ULL
71 #define IA64_M_LD4 0x08080000000ULL
72 #define IA64_M_LD8 0x080c0000000ULL
73 #define IA64_M_GETF_SIG 0x08708000000ULL
74 #define IA64_M_ST1 0x08c00000000ULL
75 #define IA64_M_ST2 0x08c40000000ULL
76 #define IA64_M_ST4 0x08c80000000ULL
77 #define IA64_M_ST8 0x08cc0000000ULL
78 #define IA64_M_LDFE 0x0c000000000ULL
79 #define IA64_M_LDF8 0x0c040000000ULL
80 #define IA64_M_LDFS 0x0c080000000ULL
81 #define IA64_M_LDFD 0x0c0c0000000ULL
82 #define IA64_M_SETF_SIG 0x0c708000000ULL
83 #define IA64_M_STFE 0x0cc00000000ULL
84 #define IA64_M_STF8 0x0cc40000000ULL
85 #define IA64_M_STFS 0x0cc80000000ULL
86 #define IA64_M_STFD 0x0ccc0000000ULL
88 #define IA64_B_BR_JMP_INDIRECT 0x00100001000ULL
89 #define IA64_B_BR_RET 0x00108801100ULL
90 #define IA64_B_BR_CALL_INDIRECT 0x02100001000ULL
91 #define IA64_B_NOP 0x04000000000ULL
92 #define IA64_B_BR21 0x08000001000ULL
93 #define IA64_BR_DPNT 0x00600000000ULL
95 #define IA64_F_NOP 0x00008000000ULL
96 #define IA64_F_FMERGE_S 0x00080000000ULL
97 #define IA64_F_FMERGE_NS 0x00088000000ULL
98 #define IA64_F_FMERGE_SE 0x00090000000ULL
99 #define IA64_F_FCVT_FX_TRUNC 0x000d0000000ULL
100 #define IA64_F_FCVT_XF 0x000e0000000ULL
101 #define IA64_F_FCMP 0x08000000000ULL
102 #define IA64_F_FCMP_EQ 0x00000000000ULL
103 #define IA64_F_FCMP_LE 0x00200000000ULL
104 #define IA64_F_FCMP_LT 0x01000000000ULL
105 #define IA64_F_FCMP_UNORD 0x01200000000ULL
106 #define IA64_F_FMA 0x10000000000ULL
107 #define IA64_F_FMS 0x14000000000ULL
108 #define IA64_F_FNMA 0x18000000000ULL
109 #define IA64_F_FMA_E 0x00000000000ULL
110 #define IA64_F_FMA_S 0x01000000000ULL
111 #define IA64_F_FMA_D 0x02000000000ULL
112 #define IA64_F_FMA_PS 0x03000000000ULL
114 #define IA64_L_NOP 0x00000000000ULL
116 #define IA64_X_NOP 0x00008000000ULL
117 #define IA64_X_BRL 0x18000001000ULL
118 #define IA64_X_MOVL 0x0c000000000ULL
120 #define UNIT_ANY 0x0f
129 #define STOP_01 0x01000000U
130 #define STOP_12 0x02000000U
131 #define STOP_23 0x04000000U
133 static const uint32_t templates[32] = {
134 UNIT_M | UNIT_I << 8 | UNIT_I << 16,
135 UNIT_M | UNIT_I << 8 | UNIT_I << 16 | STOP_23,
136 UNIT_M | UNIT_I << 8 | UNIT_I << 16 | STOP_12,
137 UNIT_M | UNIT_I << 8 | UNIT_I << 16 | STOP_12 | STOP_23,
138 UNIT_M | UNIT_L << 8 | UNIT_X << 16,
139 UNIT_M | UNIT_L << 8 | UNIT_X << 16 | STOP_23,
142 UNIT_M | UNIT_M << 8 | UNIT_I << 16,
143 UNIT_M | UNIT_M << 8 | UNIT_I << 16 | STOP_23,
144 UNIT_M | UNIT_M << 8 | UNIT_I << 16 | STOP_01,
145 UNIT_M | UNIT_M << 8 | UNIT_I << 16 | STOP_01 | STOP_23,
146 UNIT_M | UNIT_F << 8 | UNIT_I << 16,
147 UNIT_M | UNIT_F << 8 | UNIT_I << 16 | STOP_23,
148 UNIT_M | UNIT_M << 8 | UNIT_F << 16,
149 UNIT_M | UNIT_M << 8 | UNIT_F << 16 | STOP_23,
150 UNIT_M | UNIT_I << 8 | UNIT_B << 16,
151 UNIT_M | UNIT_I << 8 | UNIT_B << 16 | STOP_23,
152 UNIT_M | UNIT_B << 8 | UNIT_B << 16,
153 UNIT_M | UNIT_B << 8 | UNIT_B << 16 | STOP_23,
156 UNIT_B | UNIT_B << 8 | UNIT_B << 16,
157 UNIT_B | UNIT_B << 8 | UNIT_B << 16 | STOP_23,
158 UNIT_M | UNIT_M << 8 | UNIT_B << 16,
159 UNIT_M | UNIT_M << 8 | UNIT_B << 16 | STOP_23,
162 UNIT_M | UNIT_F << 8 | UNIT_B << 16,
163 UNIT_M | UNIT_F << 8 | UNIT_B << 16 | STOP_23,
168 #define ACCESS_MEMORY 0xfe
169 #define ACCESS_NOTHING 0xff
171 static void new_bundle(struct codegen_context *ctx)
174 for (i = 0; i < 3; i++) {
175 ctx->a.insns[i] = -1ULL;
176 ctx->a.insn_units[i] = 0xff;
177 ctx->a.insn_stops[i] = false;
181 static void clear_wr_mask(struct codegen_context *ctx)
183 memset(&ctx->a.wr_mask, 0, sizeof ctx->a.wr_mask);
186 static void init_arch_context(struct codegen_context *ctx)
192 static bool test_mask(uint64_t mask[4], uint8_t bit)
194 if (bit == ACCESS_NOTHING)
196 ajla_assert_lo(reg_is_gr(bit) || reg_is_fp(bit) || reg_is_p(bit) || reg_is_b(bit) || bit == ACCESS_MEMORY, (file_line, "test_mask: invalid bit %u", bit));
197 return (mask[bit >> 6] & 1ULL << (bit & 63)) != 0;
200 static void set_mask(uint64_t mask[4], uint8_t bit)
202 if (bit == ACCESS_NOTHING)
204 ajla_assert_lo(reg_is_gr(bit) || reg_is_fp(bit) || reg_is_p(bit) || reg_is_b(bit) || bit == ACCESS_MEMORY, (file_line, "set_mask: invalid bit %u", bit));
205 mask[bit >> 6] |= 1ULL << (bit & 63);
208 static uint32_t get_possible_templates(struct codegen_context *ctx)
212 for (i = 0; i < 32; i++) {
213 uint32_t tmpl = templates[i];
214 for (j = 0; j < 3; j++) {
215 uint8_t insn_unit = ctx->a.insn_units[j];
216 uint8_t tmpl_unit = tmpl >> (j * 8) & 0xff;
217 if (!(tmpl_unit & insn_unit)) {
220 if (ctx->a.insn_stops[j] != (tmpl >> (24 + j) & 1)) {
230 static uint64_t get_nop(unsigned unit)
233 case UNIT_I: return IA64_I_NOP;
234 case UNIT_M: return IA64_M_NOP;
235 case UNIT_B: return IA64_B_NOP;
236 case UNIT_F: return IA64_F_NOP;
237 case UNIT_L: return IA64_L_NOP;
238 case UNIT_X: return IA64_X_NOP;
239 default: internal(file_line, "get_nop: invalid unit %x", unit);
244 static unsigned get_free_slot(struct codegen_context *ctx)
247 while (slot > 0 && ctx->a.insns[slot - 1] == -1ULL)
252 static bool attr_w ia64_purge_bundle(struct codegen_context *ctx)
257 if (!get_free_slot(ctx))
259 tmpls = get_possible_templates(ctx);
260 if (unlikely(!tmpls))
261 internal(file_line, "ia64_purge_bundle: no possible templates");
262 tmpl = low_bit(tmpls);
263 for (i = 0; i < 3; i++) {
264 if (ctx->a.insns[i] == -1ULL) {
265 ctx->a.insns[i] = get_nop(templates[tmpl] >> (i * 8) & 0xff);
266 ctx->a.insn_units[i] = templates[tmpl] >> (i * 8) & 0xff;
269 low = tmpl | ctx->a.insns[0] << 5 | ctx->a.insns[1] << 46;
270 high = ctx->a.insns[1] >> 18 | ctx->a.insns[2] << 23;
277 static bool ia64_fill_bundle(struct codegen_context *ctx)
281 if (!get_free_slot(ctx))
283 tmpls = get_possible_templates(ctx);
284 if (unlikely(!tmpls))
285 internal(file_line, "ia64_fill_bundle: no possible templates");
286 tmpl = low_bit(tmpls);
287 for (i = 0; i < 3; i++) {
288 if (ctx->a.insns[i] == -1ULL) {
289 ctx->a.insns[i] = get_nop(templates[tmpl] >> (i * 8) & 0xff);
290 ctx->a.insn_units[i] = templates[tmpl] >> (i * 8) & 0xff;
296 static bool attr_w ia64_insn(struct codegen_context *ctx, uint8_t unit, uint64_t mc, uint8_t wr1, uint8_t wr2, uint8_t rd1, uint8_t rd2, uint8_t rd3)
298 unsigned slot = get_free_slot(ctx);
299 bool need_stop = false;
300 need_stop |= test_mask(ctx->a.wr_mask, wr1);
301 need_stop |= test_mask(ctx->a.wr_mask, wr2);
302 need_stop |= test_mask(ctx->a.wr_mask, rd1);
303 need_stop |= test_mask(ctx->a.wr_mask, rd2);
304 need_stop |= test_mask(ctx->a.wr_mask, rd3);
305 /*debug("ia64_insn: %x, %lx, %d, %u", unit, mc, need_stop, slot);*/
308 try_stop_in_next_slot:
309 ctx->a.insn_stops[slot - 1] = need_stop;
310 if (!get_possible_templates(ctx)) {
311 ctx->a.insn_stops[slot - 1] = false;
313 if (unlikely(slot > 3))
314 internal(file_line, "ia64_insn: can't set stop at the end of the bundle");
315 goto try_stop_in_next_slot;
319 g(ia64_purge_bundle(ctx));
327 ctx->a.insn_units[slot] = unit;
328 if (!get_possible_templates(ctx)) {
329 ctx->a.insn_units[slot] = 0xff;
331 if (unlikely(slot == 3)) {
332 g(ia64_purge_bundle(ctx));
337 ctx->a.insns[slot] = mc;
338 set_mask(ctx->a.wr_mask, wr1);
339 set_mask(ctx->a.wr_mask, wr2);
343 static bool attr_w cgen_ia64_ret(struct codegen_context *ctx)
347 mc |= bits_b(B_0) << 13;
348 g(ia64_insn(ctx, UNIT_B, mc, ACCESS_MEMORY, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
350 g(ia64_insn(ctx, UNIT_B, mc, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_MEMORY, ACCESS_NOTHING, ACCESS_NOTHING));
354 static bool attr_w cgen_ia64_alloc(struct codegen_context *ctx)
357 uint8_t *arg1 = ctx->code_position;
358 uint8_t *arg2 = arg1 + arg_size(*arg1);
359 uint8_t *arg3 = arg2 + arg_size(*arg2);
360 ctx->code_position = arg3 + arg_size(*arg3);
361 ia64_fill_bundle(ctx);
363 mc |= bits_gr(arg1[0]) << 6;
364 mc |= get_imm(&arg2[1]) << 13;
365 mc |= get_imm(&arg3[1]) << 20;
366 g(ia64_insn(ctx, UNIT_M, mc, arg1[0], ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
370 static bool attr_w cgen_ia64_dealloc(struct codegen_context *ctx)
373 uint8_t *arg1 = ctx->code_position;
374 ctx->code_position = arg1 + arg_size(*arg1);
375 mc = IA64_I_MOV_TO_AR | IA64_I_MOV_TO_AR_PFS;
376 mc |= bits_gr(arg1[0]) << 13;
377 g(ia64_insn(ctx, UNIT_I, mc, ACCESS_NOTHING, ACCESS_NOTHING, arg1[0], ACCESS_NOTHING, ACCESS_NOTHING));
381 static bool attr_w cgen_call_indirect(struct codegen_context *ctx)
384 unsigned reg = cget_one(ctx);
385 mc = IA64_B_BR_CALL_INDIRECT;
386 mc |= bits_b(B_0) << 6;
387 mc |= bits_b(reg) << 13;
388 g(ia64_insn(ctx, UNIT_B, mc, B_0, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
392 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
397 uint8_t *arg1 = ctx->code_position;
398 uint8_t *arg2 = arg1 + arg_size(*arg1);
399 ctx->code_position = arg2 + arg_size(*arg2);
401 if (reg_is_gr(arg1[0])) {
402 if (reg_is_gr(arg2[0])) {
414 mc = IA64_A_ADD_IMM14;
415 mc |= bits_gr(arg1[0]) << 6;
416 mc |= bits_gr(arg2[0]) << 20;
417 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
422 mc |= bits_gr(arg1[0]) << 6;
423 mc |= bits_gr(arg2[0]) << 20;
424 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
427 if (reg_is_fp(arg2[0])) {
428 mc = IA64_M_GETF_SIG;
429 mc |= bits_gr(arg1[0]) << 6;
430 mc |= bits_fp(arg2[0]) << 13;
431 g(ia64_insn(ctx, UNIT_M, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
434 if (reg_is_b(arg2[0])) {
435 mc = IA64_I_MOVE_FROM_BR;
436 mc |= bits_gr(arg1[0]) << 6;
437 mc |= bits_b(arg2[0]) << 13;
438 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
441 if (reg_is_p(arg2[0])) {
442 mc = IA64_A_ADD_IMM14;
443 mc |= bits_gr(arg1[0]) << 6;
444 mc |= (uint64_t)1 << 13;
445 mc |= bits_p(arg2[0]);
446 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
448 mc = IA64_A_ADD_IMM14;
449 mc |= bits_gr(arg1[0]) << 6;
450 mc |= bits_p(arg2[0] ^ 1);
451 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
455 if (arg2[0] == ARG_ADDRESS_1) {
456 imm = get_imm(&arg2[2]);
457 if (unlikely(imm != 0))
460 case OP_SIZE_1: mc = IA64_M_LD1; break;
461 case OP_SIZE_2: mc = IA64_M_LD2; break;
462 case OP_SIZE_4: mc = IA64_M_LD4; break;
463 case OP_SIZE_8: mc = IA64_M_LD8; break;
464 default: goto invalid;
466 mc |= bits_gr(arg1[0]) << 6;
467 mc |= bits_gr(arg2[1]) << 20;
468 g(ia64_insn(ctx, UNIT_M, mc, arg1[0], ACCESS_NOTHING, arg2[1], ACCESS_MEMORY, ACCESS_NOTHING));
471 if (arg2[0] == ARG_IMM) {
472 imm = get_imm(&arg2[1]);
473 if (imm >= -0x200000 && imm < 0x200000) {
474 mc = IA64_A_ADD_IMM22;
475 mc |= bits_gr(arg1[0]) << 6;
476 mc |= (imm & 0x7f) << 13;
477 mc |= ((uint64_t)imm >> 7 & 0x1ff) << 27;
478 mc |= ((uint64_t)imm >> 16 & 0x1f) << 22;
479 mc |= ((uint64_t)imm >> 21 & 0x1) << 36;
480 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
483 mc = (imm & 0x7fffffffffc00000ULL) >> 22;
484 g(ia64_insn(ctx, UNIT_L, mc, arg1[0], ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
486 mc |= bits_gr(arg1[0]) << 6;
487 mc |= (imm & 0x7f) << 13;
488 mc |= ((uint64_t)imm >> 7 & 0x1ff) << 27;
489 mc |= ((uint64_t)imm >> 16 & 0x1f) << 22;
490 mc |= ((uint64_t)imm >> 21 & 0x1) << 21;
491 mc |= ((uint64_t)imm >> 63) << 36;
492 g(ia64_insn(ctx, UNIT_X, mc, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
497 if (reg_is_fp(arg1[0])) {
498 if (reg_is_gr(arg2[0])) {
499 mc = IA64_M_SETF_SIG;
500 mc |= bits_fp(arg1[0]) << 6;
501 mc |= bits_gr(arg2[0]) << 13;
502 g(ia64_insn(ctx, UNIT_M, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
505 if (reg_is_fp(arg2[0])) {
506 mc = IA64_F_FMERGE_S;
507 mc |= bits_fp(arg1[0]) << 6;
508 mc |= bits_fp(arg2[0]) << 13;
509 mc |= bits_fp(arg2[0]) << 20;
510 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
513 if (arg2[0] == ARG_ADDRESS_1) {
514 imm = get_imm(&arg2[2]);
515 if (unlikely(imm != 0))
518 case OP_SIZE_4: mc = IA64_M_LDFS; break;
519 case OP_SIZE_8: mc = IA64_M_LDFD; break;
520 case OP_SIZE_10:mc = IA64_M_LDFE; break;
521 default: goto invalid;
523 mc |= bits_fp(arg1[0]) << 6;
524 mc |= bits_gr(arg2[1]) << 20;
525 g(ia64_insn(ctx, UNIT_M, mc, arg1[0], ACCESS_NOTHING, arg2[1], ACCESS_MEMORY, ACCESS_NOTHING));
529 if (reg_is_b(arg1[0])) {
530 if (reg_is_gr(arg2[0])) {
531 mc = IA64_I_MOVE_TO_BR;
532 mc |= bits_gr(arg2[0]) << 13;
533 mc |= bits_b(arg1[0]) << 6;
534 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
538 if (arg1[0] == ARG_ADDRESS_1) {
539 imm = get_imm(&arg1[2]);
540 if (unlikely(imm != 0))
542 if (arg2[0] == ARG_IMM) {
543 imm = get_imm(&arg2[1]);
544 if (unlikely(imm != 0))
548 if (reg_is_gr(arg2[0])) {
550 case OP_SIZE_1: mc = IA64_M_ST1; break;
551 case OP_SIZE_2: mc = IA64_M_ST2; break;
552 case OP_SIZE_4: mc = IA64_M_ST4; break;
553 case OP_SIZE_8: mc = IA64_M_ST8; break;
554 default: goto invalid;
556 mc |= bits_gr(arg2[0]) << 13;
557 mc |= bits_gr(arg1[1]) << 20;
558 g(ia64_insn(ctx, UNIT_M, mc, ACCESS_MEMORY, ACCESS_NOTHING, arg1[1], arg2[0], ACCESS_NOTHING));
561 if (reg_is_fp(arg2[0])) {
563 case OP_SIZE_4: mc = IA64_M_STFS; break;
564 case OP_SIZE_8: mc = IA64_M_STFD; break;
565 case OP_SIZE_10:mc = IA64_M_STFE; break;
566 default: goto invalid;
568 mc |= bits_fp(arg2[0]) << 13;
569 mc |= bits_gr(arg1[1]) << 20;
570 g(ia64_insn(ctx, UNIT_M, mc, ACCESS_MEMORY, ACCESS_NOTHING, arg1[1], arg2[0], ACCESS_NOTHING));
573 if (reg_is_p(arg2[0])) {
574 mc = IA64_A_ADD_IMM14;
575 mc |= bits_gr(R_CG_SCRATCH) << 6;
576 mc |= (uint64_t)1 << 13;
577 mc |= bits_p(arg2[0]);
578 g(ia64_insn(ctx, UNIT_A, mc, R_CG_SCRATCH, ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
580 mc = IA64_A_ADD_IMM14;
581 mc |= bits_gr(R_CG_SCRATCH) << 6;
582 mc |= bits_p(arg2[0] ^ 1);
583 g(ia64_insn(ctx, UNIT_A, mc, R_CG_SCRATCH, ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
586 case OP_SIZE_1: mc = IA64_M_ST1; break;
587 case OP_SIZE_2: mc = IA64_M_ST2; break;
588 case OP_SIZE_4: mc = IA64_M_ST4; break;
589 case OP_SIZE_8: mc = IA64_M_ST8; break;
590 default: goto invalid;
592 mc |= bits_gr(R_CG_SCRATCH) << 13;
593 mc |= bits_gr(arg1[1]) << 20;
594 g(ia64_insn(ctx, UNIT_M, mc, ACCESS_MEMORY, ACCESS_NOTHING, arg1[1], R_CG_SCRATCH, ACCESS_NOTHING));
600 internal(file_line, "cgen_mov: invalid arguments %u, %02x, %02x", size, arg1[0], arg2[0]);
604 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
607 uint8_t *arg1 = ctx->code_position;
608 uint8_t *arg2 = arg1 + arg_size(*arg1);
609 ctx->code_position = arg2 + arg_size(*arg2);
611 if (likely(reg_is_gr(arg1[0])) && likely(reg_is_gr(arg2[0]))) {
623 mc = IA64_A_ADD_IMM14;
624 mc |= bits_gr(arg1[0]) << 6;
625 mc |= bits_gr(arg2[0]) << 20;
626 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
631 mc |= bits_gr(arg1[0]) << 6;
632 mc |= bits_gr(arg2[0]) << 20;
633 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
638 internal(file_line, "cgen_mov: invalid arguments %02x, %02x, %u", arg1[0], arg2[0], size);
642 static bool attr_w cgen_cmp_dest_reg(struct codegen_context *ctx, unsigned op_size, unsigned cond)
646 bool swap_preds = false, swap_regs = false;
648 uint8_t *arg1 = ctx->code_position;
649 uint8_t *arg2 = arg1 + arg_size(*arg1);
650 uint8_t *arg3 = arg2 + arg_size(*arg2);
651 ctx->code_position = arg3 + arg_size(*arg3);
653 if (unlikely(!reg_is_p(arg1[0])) || unlikely(!reg_is_gr(arg2[0])))
658 if (arg3[0] == ARG_IMM) {
659 int64_t imm = get_imm(&arg3[1]);
664 if (unlikely(imm <= -0x80) || unlikely(imm >= 0x80))
667 case COND_AE: mc = IA64_A_CMP_LTU_IMM8; imm--; break;
668 case COND_B: mc = IA64_A_CMP_LTU_IMM8; imm--; swap_preds = true; break;
669 case COND_E: mc = IA64_A_CMP_EQ_IMM8; break;
670 case COND_NE: mc = IA64_A_CMP_EQ_IMM8; swap_preds = true; break;
671 case COND_BE: mc = IA64_A_CMP_LTU_IMM8; swap_preds = true; break;
672 case COND_A: mc = IA64_A_CMP_LTU_IMM8; break;
673 case COND_L: mc = IA64_A_CMP_LT_IMM8; imm--; swap_preds = true; break;
674 case COND_GE: mc = IA64_A_CMP_LT_IMM8; imm--; break;
675 case COND_LE: mc = IA64_A_CMP_LT_IMM8; swap_preds = true; break;
676 case COND_G: mc = IA64_A_CMP_LT_IMM8; break;
677 default: goto invalid;
683 if (op_size == OP_SIZE_4)
686 mc |= (imm & 0x7f) << 13;
687 mc |= ((uint64_t)imm >> 7 & 1) << 36;
688 mc |= bits_gr(arg2[0]) << 20;
689 mc |= bits_p(pred) << 6;
690 mc |= bits_p(pred ^ 1) << 27;
691 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], arg1[0] ^ 1, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
695 if (!reg_is_gr(arg3[0]))
700 case COND_B: mc = IA64_A_CMP_LTU; break;
701 case COND_AE: mc = IA64_A_CMP_LTU; swap_preds = true; break;
702 case COND_E: mc = IA64_A_CMP_EQ; break;
703 case COND_NE: mc = IA64_A_CMP_EQ; swap_preds = true; break;
704 case COND_BE: mc = IA64_A_CMP_LTU; swap_regs = true; swap_preds = true; break;
705 case COND_A: mc = IA64_A_CMP_LTU; swap_regs = true; break;
706 case COND_L: mc = IA64_A_CMP_LT; break;
707 case COND_GE: mc = IA64_A_CMP_LT; swap_preds = true; break;
708 case COND_LE: mc = IA64_A_CMP_LT; swap_regs = true; swap_preds = true; break;
709 case COND_G: mc = IA64_A_CMP_LT; swap_regs = true; break;
710 default: goto invalid;
714 uint8_t *argx = arg2;
722 if (op_size == OP_SIZE_4)
725 mc |= bits_gr(arg2[0]) << 13;
726 mc |= bits_gr(arg3[0]) << 20;
727 mc |= bits_p(pred) << 6;
728 mc |= bits_p(pred ^ 1) << 27;
729 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], arg1[0] ^ 1, arg2[0], arg3[0], ACCESS_NOTHING));
733 internal(file_line, "cgen_cmp_dest_reg: invalid arguments %02x, %02x, %02x", arg1[0], arg2[0], arg3[0]);
737 static bool attr_w cgen_test_dest_reg(struct codegen_context *ctx, unsigned bit, bool jnz)
741 uint8_t *arg1 = ctx->code_position;
742 uint8_t *arg2 = arg1 + arg_size(*arg1);
743 ctx->code_position = arg2 + arg_size(*arg2);
745 if (unlikely(!reg_is_p(arg1[0])) || unlikely(!reg_is_gr(arg2[0])))
754 mc |= (uint64_t)bit << 14;
755 mc |= bits_gr(arg2[0]) << 20;
756 mc |= bits_p(pred) << 6;
757 mc |= bits_p(pred ^ 1) << 27;
758 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], arg1[0] ^ 1, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
762 internal(file_line, "cgen_test_dest_reg: invalid arguments %02x, %02x", arg1[0], arg2[0]);
766 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned alu)
769 uint8_t *arg1 = ctx->code_position;
770 uint8_t *arg2 = arg1 + arg_size(*arg1);
771 uint8_t *arg3 = arg2 + arg_size(*arg2);
772 ctx->code_position = arg3 + arg_size(*arg3);
774 if (alu == ALU_ADD && arg2[0] == ARG_SHIFTED_REGISTER) {
775 uint8_t *arg_swp = arg3;
780 if (unlikely(!reg_is_gr(arg1[0])) || unlikely(!reg_is_gr(arg2[0])))
784 if (reg_is_gr(arg3[0])) {
787 case ALU_ADD: mc |= IA64_A_ALU_ADD; break;
788 case ALU_SUB: mc |= IA64_A_ALU_SUB; break;
789 case ALU_AND: mc |= IA64_A_ALU_AND; break;
790 case ALU_ANDN: mc |= IA64_A_ALU_ANDCM; break;
791 case ALU_OR: mc |= IA64_A_ALU_OR; break;
792 case ALU_XOR: mc |= IA64_A_ALU_XOR; break;
793 default: goto invalid;
795 mc |= bits_gr(arg1[0]) << 6;
796 mc |= bits_gr(arg2[0]) << 13;
797 mc |= bits_gr(arg3[0]) << 20;
798 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[0], ACCESS_NOTHING));
802 if (arg3[0] == ARG_SHIFTED_REGISTER && (arg3[1] & ARG_SHIFT_MODE) == ARG_SHIFT_LSL) {
803 unsigned amount = arg3[1] & ARG_SHIFT_AMOUNT;
808 if (unlikely(amount > 4))
811 mc |= bits_gr(arg1[0]) << 6;
812 mc |= bits_gr(arg3[2]) << 13;
813 mc |= bits_gr(arg2[0]) << 20;
814 mc |= (amount - 1) << 27;
815 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[2], ACCESS_NOTHING));
819 if (arg3[0] == ARG_IMM) {
820 int64_t imm = get_imm(&arg3[1]);
821 if (alu == ALU_SUB) {
822 imm = -(uint64_t)imm;
825 if (alu == ALU_ADD) {
826 if (unlikely(imm < -0x2000) || unlikely(imm >= 0x2000))
828 mc = IA64_A_ADD_IMM14;
829 mc |= bits_gr(arg1[0]) << 6;
830 mc |= bits_gr(arg2[0]) << 20;
831 mc |= (imm & 0x7f) << 13;
832 mc |= ((uint64_t)imm >> 7 & 0x3f) << 27;
833 mc |= ((uint64_t)imm >> 13 & 1) << 36;
834 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
836 } else if (alu == ALU_AND || alu == ALU_OR || alu == ALU_XOR) {
837 if (unlikely(imm < -0x80) || unlikely(imm >= 0x80))
839 mc = IA64_A_ALU_IMM8 | (alu == ALU_AND ? IA64_A_ALU_IMM8_AND : alu == ALU_OR ? IA64_A_ALU_IMM8_OR : IA64_A_ALU_IMM8_XOR);
840 mc |= bits_gr(arg1[0]) << 6;
841 mc |= bits_gr(arg2[0]) << 20;
842 mc |= (imm & 0x7f) << 13;
843 mc |= ((uint64_t)imm >> 7 & 1) << 36;
844 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
852 internal(file_line, "cgen_alu: invalid arguments %u, %02x, %02x, %02x", alu, arg1[0], arg2[0], arg3[0]);
856 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned alu)
859 uint8_t *arg1 = ctx->code_position;
860 uint8_t *arg2 = arg1 + arg_size(*arg1);
861 ctx->code_position = arg2 + arg_size(*arg2);
863 if (unlikely(!reg_is_gr(arg1[0])) || unlikely(!reg_is_gr(arg2[0])))
868 case ALU1_NOT: mc = IA64_A_ALU_IMM8 | IA64_A_ALU_IMM8_ANDCM;
869 mc |= bits_gr(arg1[0]) << 6;
870 mc |= bits_gr(arg2[0]) << 20;
873 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
875 case ALU1_NEG: mc = IA64_A_ALU_IMM8 | IA64_A_ALU_IMM8_SUB;
876 mc |= bits_gr(arg1[0]) << 6;
877 mc |= bits_gr(arg2[0]) << 20;
878 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
880 case ALU1_BSWAP:mc = IA64_I_MUX1_REV;
881 mc |= bits_gr(arg1[0]) << 6;
882 mc |= bits_gr(arg1[1]) << 13;
883 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
887 mc |= bits_gr(arg1[0]) << 6;
888 mc |= bits_gr(arg2[0]) << 20;
889 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
891 default: goto invalid;
895 internal(file_line, "cgen_alu1: invalid arguments %u, %02x, %02x", alu, arg1[0], arg2[0]);
900 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned rot)
903 uint8_t *arg1 = ctx->code_position;
904 uint8_t *arg2 = arg1 + arg_size(*arg1);
905 uint8_t *arg3 = arg2 + arg_size(*arg2);
906 ctx->code_position = arg3 + arg_size(*arg3);
908 if (unlikely(!reg_is_gr(arg1[0])) || unlikely(!reg_is_gr(arg2[0])))
911 if (arg3[0] == ARG_IMM) {
912 uint64_t pos = get_imm(&arg3[1]) & 63;
913 uint64_t len = 64 - pos - 1;
915 case ROT_SHL: mc = IA64_I_DEP_Z;
916 mc |= bits_gr(arg1[0]) << 6;
917 mc |= bits_gr(arg2[0]) << 13;
918 mc |= (pos ^ 0x3f) << 20;
921 case ROT_SHR: mc = IA64_I_EXTR_U;
922 mc |= bits_gr(arg1[0]) << 6;
924 mc |= bits_gr(arg2[0]) << 20;
927 case ROT_SAR: mc = IA64_I_EXTR;
928 mc |= bits_gr(arg1[0]) << 6;
930 mc |= bits_gr(arg2[0]) << 20;
933 default: goto invalid;
935 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
939 if (reg_is_gr(arg3[0])) {
941 case ROT_SHL: mc = IA64_I_SHL;
942 mc |= bits_gr(arg1[0]) << 6;
943 mc |= bits_gr(arg2[0]) << 13;
944 mc |= bits_gr(arg3[0]) << 20;
946 case ROT_SHR: mc = IA64_I_SHR_U;
947 mc |= bits_gr(arg1[0]) << 6;
948 mc |= bits_gr(arg3[0]) << 13;
949 mc |= bits_gr(arg2[0]) << 20;
951 case ROT_SAR: mc = IA64_I_SHR;
952 mc |= bits_gr(arg1[0]) << 6;
953 mc |= bits_gr(arg3[0]) << 13;
954 mc |= bits_gr(arg2[0]) << 20;
956 default: goto invalid;
958 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[0], ACCESS_NOTHING));
963 internal(file_line, "cgen_rot: invalid arguments %02x, %02x, %02x, %u", arg1[0], arg2[0], arg3[0], rot);
967 static bool attr_w cgen_btx(struct codegen_context *ctx, unsigned alu)
971 uint8_t *arg1 = ctx->code_position;
972 uint8_t *arg2 = arg1 + arg_size(*arg1);
973 uint8_t *arg3 = arg2 + arg_size(*arg2);
974 ctx->code_position = arg3 + arg_size(*arg3);
975 if (unlikely(!reg_is_gr(arg1[0])) || unlikely(!reg_is_gr(arg2[0])) || unlikely(arg3[0] != ARG_IMM))
978 imm = get_imm(&arg3[1]) & 0x3f;
983 case BTX_BTS: mc |= 1ULL << 36;
986 default: goto invalid;
989 mc |= bits_gr(arg1[0]) << 6;
990 mc |= bits_gr(arg2[0]) << 20;
992 mc |= (imm ^ 0x3f) << 14;
994 g(ia64_insn(ctx, UNIT_I, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
998 internal(file_line, "cgen_rot: invalid arguments %02x, %02x, %02x, %u", arg1[0], arg2[0], arg3[0], alu);
1002 static bool attr_w cgen_movr(struct codegen_context *ctx, unsigned aux)
1006 uint8_t *arg1 = ctx->code_position;
1007 uint8_t *arg2 = arg1 + arg_size(*arg1);
1008 uint8_t *arg3 = arg2 + arg_size(*arg2);
1009 uint8_t *arg4 = arg3 + arg_size(*arg3);
1010 ctx->code_position = arg4 + arg_size(*arg4);
1011 if (unlikely(arg1[0] != arg2[0]) || unlikely(!reg_is_gr(arg1[0])) || unlikely(!reg_is_p(arg3[0])))
1016 case COND_E: pred ^= 1; break;
1017 case COND_NE: break;
1018 default: goto invalid;
1021 if (arg4[0] == ARG_IMM) {
1022 int64_t imm = get_imm(&arg4[1]);
1023 if (unlikely(imm < -0x2000) || unlikely(imm >= 0x2000))
1025 mc = IA64_A_ADD_IMM14;
1026 mc |= bits_gr(arg1[0]) << 6;
1027 mc |= (imm & 0x7f) << 13;
1028 mc |= ((uint64_t)imm >> 7 & 0x3f) << 27;
1029 mc |= ((uint64_t)imm >> 13 & 1) << 36;
1031 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[0], ACCESS_NOTHING));
1035 if (reg_is_gr(arg4[0])) {
1036 mc = IA64_A_ADD_IMM14;
1037 mc |= bits_gr(arg1[0]) << 6;
1038 mc |= bits_gr(arg4[0]) << 20;
1040 g(ia64_insn(ctx, UNIT_A, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[0], arg4[0]));
1045 internal(file_line, "cgen_movr: invalid arguments %02x, %02x, %02x, %02x, %u", arg1[0], arg2[0], arg3[0], arg4[0], aux);
1049 static bool attr_w cgen_fp_cmp_dest_reg(struct codegen_context *ctx, unsigned aux)
1053 bool swap_preds = false, swap_regs = false;
1054 uint8_t *arg1 = ctx->code_position;
1055 uint8_t *arg2 = arg1 + arg_size(*arg1);
1056 uint8_t *arg3 = arg2 + arg_size(*arg2);
1057 ctx->code_position = arg3 + arg_size(*arg3);
1062 case FP_COND_P: mc |= IA64_F_FCMP_UNORD; break;
1063 case FP_COND_NP:mc |= IA64_F_FCMP_UNORD; swap_preds = true; break;
1064 case FP_COND_E: mc |= IA64_F_FCMP_EQ; break;
1065 case FP_COND_NE:mc |= IA64_F_FCMP_EQ; swap_preds = true; break;
1066 case FP_COND_A: mc |= IA64_F_FCMP_LT; swap_regs = true; break;
1067 case FP_COND_BE:mc |= IA64_F_FCMP_LE; break;
1068 case FP_COND_B: mc |= IA64_F_FCMP_LT; break;
1069 case FP_COND_AE:mc |= IA64_F_FCMP_LE; swap_regs = true; break;
1073 uint8_t *argx = arg2;
1081 mc |= bits_fp(arg2[0]) << 13;
1082 mc |= bits_fp(arg3[0]) << 20;
1083 mc |= bits_p(pred) << 6;
1084 mc |= bits_p(pred ^ 1) << 27;
1085 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[0], ACCESS_NOTHING));
1089 static bool attr_w cgen_fp_alu(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1091 uint64_t mc, f1, f2, f3, f4;
1092 uint8_t *arg1 = ctx->code_position;
1093 uint8_t *arg2 = arg1 + arg_size(*arg1);
1094 uint8_t *arg3 = arg2 + arg_size(*arg2);
1095 ctx->code_position = arg3 + arg_size(*arg3);
1099 f1 = bits_fp(arg1[0]);
1100 f2 = bits_fp(arg3[0]);
1101 f3 = bits_fp(arg2[0]);
1102 f4 = bits_fp(FR_ONE);
1106 f1 = bits_fp(arg1[0]);
1107 f2 = bits_fp(arg3[0]);
1108 f3 = bits_fp(arg2[0]);
1109 f4 = bits_fp(FR_ONE);
1113 f1 = bits_fp(arg1[0]);
1114 f2 = bits_fp(FR_ZERO);
1115 f3 = bits_fp(arg2[0]);
1116 f4 = bits_fp(arg3[0]);
1138 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg2[0], arg3[0], ACCESS_NOTHING));
1142 internal(file_line, "cgen_fp_alu: invalid arguments %u, %u, %02x, %02x, %02x", op_size, aux, arg1[0], arg2[0], arg3[0]);
1146 static bool attr_w cgen_fp_alu1(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1149 uint8_t *arg1 = ctx->code_position;
1150 uint8_t *arg2 = arg1 + arg_size(*arg1);
1151 ctx->code_position = arg2 + arg_size(*arg2);
1154 mc = IA64_F_FMERGE_NS;
1155 mc |= bits_fp(arg1[0]) << 6;
1156 mc |= bits_fp(arg2[0]) << 13;
1157 mc |= bits_fp(arg2[0]) << 20;
1162 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
1166 internal(file_line, "cgen_fp_alu1: invalid arguments %u, %u, %02x, %02x", op_size, aux, arg1[0], arg2[0]);
1170 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx)
1173 uint8_t *arg1 = ctx->code_position;
1174 uint8_t *arg2 = arg1 + arg_size(*arg1);
1175 ctx->code_position = arg2 + arg_size(*arg2);
1177 mc = IA64_F_FCVT_FX_TRUNC;
1178 mc |= bits_fp(arg1[0]) << 6;
1179 mc |= bits_fp(arg2[0]) << 13;
1180 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
1184 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned fp_op_size)
1187 uint8_t *arg1 = ctx->code_position;
1188 uint8_t *arg2 = arg1 + arg_size(*arg1);
1189 ctx->code_position = arg2 + arg_size(*arg2);
1191 mc = IA64_F_FCVT_XF;
1192 mc |= bits_fp(arg1[0]) << 6;
1193 mc |= bits_fp(arg2[0]) << 13;
1194 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg2[0], ACCESS_NOTHING, ACCESS_NOTHING));
1197 switch (fp_op_size) {
1209 mc |= bits_fp(arg1[0]) << 6;
1210 mc |= bits_fp(FR_ZERO) << 13;
1211 mc |= bits_fp(arg1[0]) << 20;
1212 mc |= bits_fp(FR_ONE) << 27;
1213 g(ia64_insn(ctx, UNIT_F, mc, arg1[0], ACCESS_NOTHING, arg1[0], ACCESS_NOTHING, ACCESS_NOTHING));
1218 internal(file_line, "cgen_fp_from_int: invalid arguments %u, %02x, %02x", fp_op_size, arg1[0], arg2[0]);
1222 static bool attr_w cgen_jmp(struct codegen_context *ctx, unsigned length)
1226 if (length == JMP_SHORTEST) {
1227 g(ia64_insn(ctx, UNIT_B, IA64_B_BR21, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
1228 bundle = get_free_slot(ctx) - 1;
1229 ctx->mcode_size += bundle;
1230 g(add_relocation(ctx, JMP_SHORTEST, 0, NULL));
1231 ctx->mcode_size -= bundle;
1233 g(ia64_insn(ctx, UNIT_L, 0, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
1235 g(ia64_insn(ctx, UNIT_X, mc, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
1236 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1241 static bool attr_w cgen_jmp_reg(struct codegen_context *ctx, unsigned aux, unsigned length)
1245 unsigned reg = cget_one(ctx);
1246 if (unlikely(!reg_is_p(reg)))
1257 if (likely(length == JMP_SHORTEST)) {
1258 mc = IA64_B_BR21 | IA64_BR_DPNT;
1260 g(ia64_insn(ctx, UNIT_B, mc, ACCESS_NOTHING, ACCESS_NOTHING, reg, ACCESS_NOTHING, ACCESS_NOTHING));
1261 bundle = get_free_slot(ctx) - 1;
1262 ctx->mcode_size += bundle;
1263 g(add_relocation(ctx, JMP_SHORTEST, 1, NULL));
1264 ctx->mcode_size -= bundle;
1266 g(ia64_insn(ctx, UNIT_L, 0, ACCESS_NOTHING, ACCESS_NOTHING, reg, ACCESS_NOTHING, ACCESS_NOTHING));
1267 mc = IA64_X_BRL | IA64_BR_DPNT;
1269 g(ia64_insn(ctx, UNIT_X, mc, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
1270 g(add_relocation(ctx, JMP_SHORT, 1, NULL));
1274 internal(file_line, "cgen_jmp_reg: invalid arguments %x, %x, %x", reg, aux, length);
1277 static bool attr_w cgen_jmp_indirect(struct codegen_context *ctx)
1280 unsigned reg = cget_one(ctx);
1282 mc = IA64_I_MOVE_TO_BR;
1283 mc |= bits_gr(reg) << 13;
1284 mc |= bits_b(R_SCRATCH_B) << 6;
1285 g(ia64_insn(ctx, UNIT_I, mc, R_SCRATCH_B, ACCESS_NOTHING, reg, ACCESS_NOTHING, ACCESS_NOTHING));
1287 mc = IA64_B_BR_JMP_INDIRECT;
1288 mc |= bits_b(R_SCRATCH_B) << 13;
1289 g(ia64_insn(ctx, UNIT_B, mc, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING, ACCESS_NOTHING));
1293 static uint64_t extract_bundle(uint8_t *ptr, unsigned bundle)
1296 memcpy(mc, ptr, 16);
1298 case 0: return mc[0] >> 5 & 0x1ffffffffffULL;
1300 case 1: return mc[0] >> 46 | (mc[1] & 0x7fffffULL) << 18;
1302 case 2: return mc[1] >> 23;
1304 default:internal(file_line, "extract_bundle: invalid bundle %u", bundle);
1308 static void insert_bundle(uint8_t *ptr, unsigned bundle, uint64_t instr)
1311 memcpy(mc, ptr, 16);
1313 case 0: mc[0] = (mc[0] & ~(0x1ffffffffffULL << 5)) | instr << 5;
1315 case 1: mc[0] = (mc[0] & ~(-1ULL << 46)) | instr << 46;
1316 mc[1] = (mc[1] & ~0x7fffffULL) | instr >> 18;
1318 case 2: mc[1] = (mc[1] & ~(-1ULL << 23)) | instr << 23;
1320 default:internal(file_line, "insert_bundle: invalid bundle %u", bundle);
1322 memcpy(ptr, mc, 16);
1325 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1329 unsigned bundle = reloc->position & 3;
1330 size_t position = reloc->position & ~3;
1331 int64_t offs = (int64_t)(ctx->label_to_pos[reloc->label_id] >> 4) - (int64_t)(position >> 4);
1332 /*debug("relocation: position %lx, bundle %x, offset %lx, label %lx", reloc->position, bundle, offs, ctx->label_to_pos[reloc->label_id]);*/
1333 switch (reloc->length) {
1335 if (unlikely(offs < -0x100000) || unlikely(offs >= 0x100000))
1337 mc = extract_bundle(ctx->mcode + position, bundle);
1338 mc &= ~0x011ffffe000ULL;
1339 mc |= (offs & 0xfffffULL) << 13;
1340 mc |= ((uint64_t)offs >> 20 & 1) << 36;
1341 insert_bundle(ctx->mcode + position, bundle, mc);
1344 imm41 = extract_bundle(ctx->mcode + position, 1);
1345 mc = extract_bundle(ctx->mcode + position, 2);
1346 mc &= ~0x011ffffe000ULL;
1347 mc |= (offs & 0xfffffULL) << 13;
1348 imm41 &= ~0x1fffffffffcULL;
1349 imm41 |= (offs >> 20 << 2) & 0x1fffffffffcULL;
1350 mc |= ((uint64_t)offs >> 59 & 1) << 36;
1351 insert_bundle(ctx->mcode + position, 1, imm41);
1352 insert_bundle(ctx->mcode + position, 2, mc);
1355 internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1360 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1363 switch (insn_opcode(insn)) {
1365 full = ia64_fill_bundle(ctx);
1367 ctx->mcode_size += 16;
1370 ctx->mcode_size -= 16;
1373 full = ia64_fill_bundle(ctx);
1375 ctx->mcode_size += 16;
1378 ctx->mcode_size -= 16;
1381 g(cgen_ia64_ret(ctx));
1382 g(ia64_purge_bundle(ctx));
1384 case INSN_IA64_ALLOC:
1385 g(cgen_ia64_alloc(ctx));
1387 case INSN_IA64_DEALLOC:
1388 g(cgen_ia64_dealloc(ctx));
1390 case INSN_CALL_INDIRECT:
1391 g(cgen_call_indirect(ctx));
1394 g(cgen_mov(ctx, insn_op_size(insn)));
1397 g(cgen_movsx(ctx, insn_op_size(insn)));
1399 case INSN_CMP_DEST_REG:
1400 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1402 g(cgen_cmp_dest_reg(ctx, insn_op_size(insn), insn_aux(insn)));
1404 case INSN_TEST_DEST_REG:
1405 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1407 g(cgen_test_dest_reg(ctx, insn_aux(insn) & 63, insn_aux(insn) >> 6));
1410 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1412 g(cgen_alu(ctx, insn_aux(insn)));
1415 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1417 g(cgen_alu1(ctx, insn_aux(insn)));
1420 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1422 g(cgen_rot(ctx, insn_aux(insn)));
1425 g(cgen_btx(ctx, insn_aux(insn)));
1428 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1430 g(cgen_movr(ctx, insn_aux(insn)));
1432 case INSN_FP_CMP_DEST_REG:
1433 g(cgen_fp_cmp_dest_reg(ctx, insn_aux(insn)));
1436 g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1439 g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1441 case INSN_FP_TO_INT64:
1442 g(cgen_fp_to_int(ctx));
1444 case INSN_FP_FROM_INT64:
1445 g(cgen_fp_from_int(ctx, insn_op_size(insn)));
1448 g(cgen_jmp(ctx, insn_jump_size(insn)));
1451 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE))
1453 g(cgen_jmp_reg(ctx, insn_aux(insn), insn_jump_size(insn)));
1455 case INSN_JMP_INDIRECT:
1456 g(cgen_jmp_indirect(ctx));
1460 internal(file_line, "cgen_insn: invalid insn %08x", insn);