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/>.
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)
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;
197 internal(file_line, "cmp_swap_arguments: can't swap the condition %u", cond);
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;
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;
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)
272 if (!PA_20 && PA_SPACES) {
274 mc |= (uint32_t)R_RP << 21;
278 mc |= (uint32_t)R_CG_SCRATCH << 16;
281 mc |= (uint32_t)R_RP << 21;
285 mc = PA_20 ? PARISC_BVE_RET : PARISC_BV;
286 mc |= (uint32_t)R_RP << 21;
290 cgen_four(PARISC_NOP);
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);
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);
315 static bool attr_w cgen_call_indirect(struct codegen_context *ctx)
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));
331 static bool attr_w cgen_ld_st(struct codegen_context *ctx, bool ld, unsigned size, uint8_t reg, uint8_t *address)
336 if (address[0] == ARG_ADDRESS_1) {
337 imm = get_imm(&address[2]);
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;
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;
355 mc |= low_sign_ext_14(imm);
356 g(cgen_2reg(ctx, mc, address[1], reg));
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)
364 if (imm < 0 && address[0] == ARG_ADDRESS_1_POST_I)
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;
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;
380 mc |= low_sign_ext_14(imm);
381 g(cgen_2reg(ctx, mc, address[1], reg));
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))
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;
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;
404 g(cgen_3reg(ctx, mc, address[2], address[1], reg));
408 internal(file_line, "cgen_ld_st: invalid address: %x, %02x, %02x, %"PRIxMAX"", size, reg, address[0], (uintmax_t)imm);
412 static bool attr_w cgen_fp_ld_st(struct codegen_context *ctx, bool ld, unsigned size, uint8_t reg, uint8_t *address)
417 if (unlikely(address[0] != ARG_ADDRESS_1))
420 imm = get_imm(&address[2]);
421 if (imm >= -0x10 && imm < 0x10) {
423 mc = size == OP_SIZE_4 ? PARISC_FLDW : PARISC_FLDD;
425 mc = size == OP_SIZE_4 ? PARISC_FSTW : PARISC_FSTD;
426 mc |= low_sign_ext_5(imm) << 16;
428 mc |= (uint32_t)address[1] << 21;
433 mc = size == OP_SIZE_4 ? PARISC_FLDW_LONG : PARISC_FLDD_LONG;
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));
442 internal(file_line, "cgen_fp_ld_st: invalid address: %x, %02x, %02x, %"PRIxMAX"", size, reg, address[0], (uintmax_t)imm);
446 static bool attr_w cgen_mov_args(struct codegen_context *ctx, unsigned size, uint8_t *arg1, uint8_t *arg2)
451 if (arg1[0] < 0x20) {
452 if (arg2[0] < 0x20) {
453 if (size < OP_SIZE_NATIVE) {
454 if (OP_SIZE_NATIVE == OP_SIZE_4) {
457 mc = PARISC_EXTRW_U ^ 0x3f8U;
460 mc = PARISC_EXTRW_U ^ 0x3f0U;
463 internal(file_line, "cgen_mov_args: invalid op size %u", size);
468 mc = PARISC_EXTRD_U ^ 0x13f8U;
471 mc = PARISC_EXTRD_U ^ 0x13f0U;
474 mc = PARISC_EXTRD_U ^ 0x13e0U;
477 internal(file_line, "cgen_mov_args: invalid op size %u", size);
480 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
483 g(cgen_3reg(ctx, PARISC_OR, arg2[0], 0, arg1[0]));
486 if (arg2[0] == ARG_IMM) {
487 imm = get_imm(&arg2[1]);
488 if (imm >= -0x2000 && imm < 0x2000) {
490 mc |= low_sign_ext_14(imm);
491 g(cgen_2reg(ctx, mc, R_ZERO, arg1[0]));
497 mc |= (uint32_t)arg1[0] << 21;
498 mc |= assemble_21((uint64_t)imm >> 11);
502 return cgen_ld_st(ctx, true, size, arg1[0], arg2);
505 if (arg2[0] < 0x20) {
506 return cgen_ld_st(ctx, false, size, arg2[0], arg1);
508 if (arg2[0] == ARG_IMM) {
509 imm = get_imm(&arg2[1]);
510 if (unlikely(imm != 0))
512 return cgen_ld_st(ctx, false, size, R_ZERO, arg1);
515 if (reg_is_fp(arg1[0]) && arg2[0] == ARG_ADDRESS_1) {
516 return cgen_fp_ld_st(ctx, true, size, arg1[0], arg2);
518 if (reg_is_fp(arg2[0]) && arg1[0] == ARG_ADDRESS_1) {
519 return cgen_fp_ld_st(ctx, false, size, arg2[0], arg1);
521 if (reg_is_fp(arg1[0]) && reg_is_fp(arg2[0])) {
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);
528 g(cgen_3reg(ctx, mc, 0, arg2[0] & 0x1f, arg1[0] & 0x1f));
533 internal(file_line, "cgen_mov_args: invalid arguments %02x, %02x", arg1[0], arg2[0]);
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)
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) {
558 mc = PARISC_EXTRW_S ^ 0x3f8U;
561 mc = PARISC_EXTRW_S ^ 0x3f0U;
564 internal(file_line, "cgen_movsx: invalid op size %u", size);
569 mc = PARISC_EXTRD_S ^ 0x13f8U;
572 mc = PARISC_EXTRD_S ^ 0x13f0U;
575 mc = PARISC_EXTRD_S ^ 0x13e0U;
578 internal(file_line, "cgen_movsx: invalid op size %u", size);
581 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
584 return cgen_mov_args(ctx, size, arg1, arg2);
588 static bool attr_w cgen_cmp_dest_reg(struct codegen_context *ctx, unsigned size, unsigned cond)
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);
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]);
607 if (size == OP_SIZE_8)
608 mc |= PARISC_CMPICLR_64;
610 mc |= low_sign_ext_11(imm);
611 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
614 if (size == OP_SIZE_8)
615 mc |= PARISC_COND_64;
617 g(cgen_3reg(ctx, mc, arg2[0], arg3[0], arg1[0]));
621 mc |= low_sign_ext_14(1);
622 g(cgen_2reg(ctx, mc, R_ZERO, arg1[0]));
627 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned writes_flags, unsigned alu, bool trap, unsigned length)
630 uint8_t *arg1 = ctx->code_position;
631 uint8_t *arg2 = arg1 + arg_size(*arg1);
632 uint8_t *arg3 = arg2 + arg_size(*arg2);
633 ctx->code_position = arg3 + arg_size(*arg3);
635 if (unlikely(arg1[0] >= 0x20) || unlikely(arg2[0] >= 0x20))
638 if (arg3[0] == ARG_IMM && !trap) {
639 int64_t imm = get_imm(&arg3[1]);
640 if (unlikely(writes_flags))
644 imm = -(uint64_t)imm;
647 if (imm >= -0x2000 && imm < 0x2000) {
649 mc |= low_sign_ext_14(imm);
650 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
652 } else if (!(imm & 0x7ff) && arg1[0] == R_1) {
654 mc |= (uint32_t)arg2[0] << 21;
655 mc |= assemble_21((uint64_t)imm >> 11);
667 case ALU_ADD: mc = writes_flags ? PARISC_ADD : PARISC_ADD_L;
669 case ALU_OR: ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: or must not write flags"));
672 case ALU_ADC: ajla_assert_lo(writes_flags, (file_line, "cgen_alu: adc must write flags"));
673 mc = size == OP_SIZE_4 ? PARISC_ADD_C : PARISC_ADD_DC;
675 case ALU_SBB: ajla_assert_lo(writes_flags, (file_line, "cgen_alu: sbb must write flags"));
676 mc = size == OP_SIZE_4 ? PARISC_SUB_B : PARISC_SUB_DB;
678 case ALU_AND: ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: and must not write flags"));
681 case ALU_SUB: ajla_assert_lo(writes_flags, (file_line, "cgen_alu: sub must write flags"));
684 case ALU_XOR: ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: xor must not write flags"));
687 case ALU_ANDN: ajla_assert_lo(!writes_flags, (file_line, "cgen_alu: andn must not write flags"));
690 default: goto invalid;
693 if (alu == ALU_ADD && arg3[0] == ARG_SHIFTED_REGISTER) {
695 if (unlikely((arg3[1] >> 6) != 0))
697 if (unlikely((arg3[1] & ARG_SHIFT_AMOUNT)) >= 4)
699 mc |= (uint32_t)(arg3[1] & ARG_SHIFT_AMOUNT) << 6;
706 if (unlikely(arg3[0] >= 0x20))
710 if (alu == ALU_ADD && size == OP_SIZE_4 && arg1[0] == arg2[0] && trap && length == JMP_SHORTEST) {
713 mc |= PARISC_COND_SV;
715 g(add_relocation(ctx, JMP_SHORTEST, ctx->code_position - arg1, &need_nop));
716 g(cgen_2reg(ctx, mc, arg1[0], arg3[0]));
717 if (unlikely(need_nop))
718 cgen_four(PARISC_NOP);
724 if (length == JMP_EXTRA_LONG || (length == JMP_LONG && !PA_20))
725 mc |= PARISC_COND_SV;
727 mc |= PARISC_COND_NSV;
728 if (size == OP_SIZE_8)
729 mc |= PARISC_COND_64;
732 g(cgen_3reg(ctx, mc, arg2[0], arg3[0], arg1[0]));
735 if (length <= JMP_SHORT) {
736 g(add_relocation(ctx, JMP_SHORT, ctx->code_position - arg1, NULL));
737 cgen_four(PARISC_BL | PARISC_N);
738 } else if (length == JMP_LONG && PA_20) {
739 g(add_relocation(ctx, JMP_LONG, ctx->code_position - arg1, NULL));
740 cgen_four(PARISC_BL_L | PARISC_N);
742 cgen_four(PARISC_BL | PARISC_N | assemble_12(3));
743 g(add_relocation(ctx, JMP_EXTRA_LONG, ctx->code_position - arg1, NULL));
744 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
745 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
746 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
747 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
754 internal(file_line, "cgen_alu: invalid arguments %02x, %02x, %02x, %u, %u", arg1[0], arg2[0], arg3[0], alu, writes_flags);
758 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned writes_flags, unsigned alu, bool trap, unsigned length)
762 uint8_t *arg1 = ctx->code_position;
763 uint8_t *arg2 = arg1 + arg_size(*arg1);
764 ctx->code_position = arg2 + arg_size(*arg2);
766 if (unlikely(arg1[0] >= 0x20) || unlikely(arg2[0] >= 0x20))
770 case ALU1_NOT: ajla_assert_lo(!writes_flags, (file_line, "cgen_alu1: not must not write flags"));
776 case ALU1_NEG: ajla_assert_lo(writes_flags, (file_line, "cgen_alu1: neg must write flags"));
783 case ALU1_DEC: ajla_assert_lo(writes_flags, (file_line, "cgen_alu1: inc/dec must write flags"));
784 if (trap && size == OP_SIZE_8) {
786 mc |= low_sign_ext_14(alu == ALU1_INC ? 1 : -1);
787 g(cgen_2reg(ctx, mc, R_ZERO, R_CG_SCRATCH));
795 mc |= low_sign_ext_11(alu == ALU1_INC ? 1 : -1);
801 default: goto invalid;
805 if (length == JMP_EXTRA_LONG || (length == JMP_LONG && !PA_20))
806 mc |= PARISC_COND_SV;
808 mc |= PARISC_COND_NSV;
809 if (size == OP_SIZE_8)
810 mc |= PARISC_COND_64;
813 g(cgen_3reg(ctx, mc, r1, r2, rt));
816 if (length <= JMP_SHORT) {
817 g(add_relocation(ctx, JMP_SHORT, ctx->code_position - arg1, NULL));
818 cgen_four(PARISC_BL | PARISC_N);
819 } else if (length == JMP_LONG && PA_20) {
820 g(add_relocation(ctx, JMP_LONG, ctx->code_position - arg1, NULL));
821 cgen_four(PARISC_BL_L | PARISC_N);
823 cgen_four(PARISC_BL | PARISC_N | assemble_12(3));
824 g(add_relocation(ctx, JMP_EXTRA_LONG, ctx->code_position - arg1, NULL));
825 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
826 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
827 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
828 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
835 internal(file_line, "cgen_alu1: invalid arguments %02x, %02x, %u, %u", arg1[0], arg2[0], alu, writes_flags);
839 static bool attr_w cgen_sar(struct codegen_context *ctx, bool sar_complement, uint8_t reg)
842 if (!sar_complement) {
844 mc |= (uint32_t)reg << 16;
848 mc |= (uint32_t)reg << 16;
852 mc |= low_sign_ext_14(-1);
853 g(cgen_2reg(ctx, mc, 0, R_CG_SCRATCH));
855 g(cgen_3reg(ctx, mc, R_CG_SCRATCH, reg, R_CG_SCRATCH));
857 mc |= (uint32_t)R_CG_SCRATCH << 16;
863 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, unsigned rot)
866 uint8_t *arg1 = ctx->code_position;
867 uint8_t *arg2 = arg1 + arg_size(*arg1);
868 uint8_t *arg3 = arg2 + arg_size(*arg2);
869 ctx->code_position = arg3 + arg_size(*arg3);
870 if (arg3[0] == ARG_IMM) {
871 int64_t imm = get_imm(&arg3[1]);
872 unsigned sh = imm & (size == OP_SIZE_4 ? 31 : 63);
873 if (size == OP_SIZE_4) {
877 mc |= sh | (sh << 5);
881 mc |= sh | ((31 - sh) << 5);
885 mc |= sh | ((31 - sh) << 5);
894 mc |= (sh & 31) | ((sh & 31) << 5);
900 mc |= (sh & 31) | ((31 - (sh & 31)) << 5);
906 mc |= (sh & 31) | ((31 - (sh & 31)) << 5);
915 g(cgen_2reg(ctx, mc, arg1[0], arg2[0]));
917 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
919 } else if (arg3[0] < 0x20) {
920 bool sar_complement = rot != ROT_SHR;
921 g(cgen_sar(ctx, sar_complement, arg3[0]));
922 if (size == OP_SIZE_4) {
925 mc = PARISC_DEPW_Z_SAR;
928 mc = PARISC_SHRPW_SAR;
931 mc = PARISC_EXTRW_S_SAR;
939 mc = PARISC_DEPD_Z_SAR | 0x100;
942 mc = PARISC_SHRPD_SAR;
945 mc = PARISC_EXTRD_S_SAR | 0x100;
951 if (rot == ROT_SHL) {
952 g(cgen_2reg(ctx, mc, arg1[0], arg2[0]));
953 } else if (rot == ROT_SHR) {
954 g(cgen_3reg(ctx, mc, R_ZERO, arg2[0], arg1[0]));
956 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
962 internal(file_line, "cgen_rot: invalid arguments %02x, %02x, %02x, %u, %u", arg1[0], arg2[0], arg3[0], size, rot);
966 static bool attr_w cgen_btx(struct codegen_context *ctx, unsigned size, unsigned aux)
969 uint8_t *arg1 = ctx->code_position;
970 uint8_t *arg2 = arg1 + arg_size(*arg1);
971 uint8_t *arg3 = arg2 + arg_size(*arg2);
972 ctx->code_position = arg3 + arg_size(*arg3);
974 if (aux == BTX_BTS || aux == BTX_BTR) {
975 if (arg1[0] != arg2[0]) {
976 g(cgen_3reg(ctx, PARISC_OR, arg2[0], 0, arg1[0]));
980 if (arg3[0] == ARG_IMM) {
981 int64_t imm = get_imm(&arg3[1]);
982 unsigned bit = imm & (size == OP_SIZE_4 ? 31 : 63);
983 if (size == OP_SIZE_4) {
988 mc |= 31U | (bit << 5);
989 g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
993 mc |= 31U | ((31 - bit) << 5);
994 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1004 mc |= 31U | ((bit & 0x1f) << 5) | ((bit & 0x20) << 6);
1005 g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1008 mc = PARISC_EXTRD_U;
1009 mc |= 31U | (((63 - bit) & 0x1f) << 5) | (((63 - bit) & 0x20) << 6);
1010 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1017 g(cgen_sar(ctx, true, arg3[0]));
1018 if (size == OP_SIZE_4) {
1022 mc = PARISC_DEPWI_SAR;
1024 g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1027 mc = PARISC_EXTRW_U_SAR;
1029 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1038 mc = PARISC_DEPDI_SAR;
1040 g(cgen_2reg(ctx, mc, arg1[0], low_sign_ext_5(aux == BTX_BTS)));
1043 mc = PARISC_EXTRD_U_SAR;
1045 g(cgen_2reg(ctx, mc, arg2[0], arg1[0]));
1054 internal(file_line, "cgen_btx: invalid arguments %02x, %02x, %02x, %u, %u", arg1[0], arg2[0], arg3[0], size, aux);
1058 static bool attr_w cgen_cmp_cmov(struct codegen_context *ctx, unsigned op_size, unsigned cond)
1063 uint8_t *arg1 = ctx->code_position;
1064 uint8_t *arg2 = arg1 + arg_size(*arg1);
1065 uint8_t *arg3 = arg2 + arg_size(*arg2);
1066 uint8_t *arg4 = arg3 + arg_size(*arg3);
1067 uint8_t *arg5 = arg4 + arg_size(*arg4);
1068 ctx->code_position = arg5 + arg_size(*arg5);
1070 if (arg3[0] == ARG_IMM) {
1071 cond = cmp_swap_arguments(cond);
1074 fc = cmp_sub_cond[cond];
1075 fc ^= PARISC_COND_NEG;
1077 if (arg5[0] == ARG_IMM) {
1078 imm = get_imm(&arg5[1]);
1079 mc = PARISC_CMPICLR;
1081 mc |= low_sign_ext_11(imm);
1082 g(cgen_2reg(ctx, mc, arg4[0], R_ZERO));
1086 g(cgen_3reg(ctx, mc, arg4[0], arg5[0], R_ZERO));
1089 g(cgen_mov_args(ctx, op_size, arg1, arg3));
1094 static bool attr_w cgen_movr(struct codegen_context *ctx, unsigned cond)
1098 uint8_t *arg1 = ctx->code_position;
1099 uint8_t *arg2 = arg1 + arg_size(*arg1);
1100 uint8_t *arg3 = arg2 + arg_size(*arg2);
1101 uint8_t *arg4 = arg3 + arg_size(*arg3);
1102 ctx->code_position = arg4 + arg_size(*arg4);
1104 fc = cmp_sub_cond[cond];
1105 fc ^= PARISC_COND_NEG;
1107 if (unlikely(arg1[0] != arg2[0]) || unlikely(arg1[0] >= 0x20))
1108 internal(file_line, "cgen_movr: invalid arguments");
1112 if (OP_SIZE_NATIVE == OP_SIZE_8)
1113 mc |= PARISC_COND_64;
1115 g(cgen_3reg(ctx, mc, R_ZERO, arg3[0], R_ZERO));
1117 g(cgen_mov_args(ctx, OP_SIZE_NATIVE, arg1, arg4));
1122 static bool attr_w cgen_fp_cmp_cond(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1126 uint8_t *arg1 = ctx->code_position;
1127 uint8_t *arg2 = arg1 + arg_size(*arg1);
1128 ctx->code_position = arg2 + arg_size(*arg2);
1130 case FP_COND_P: cond = PARISC_FCMP_P; break;
1131 case FP_COND_NP: cond = PARISC_FCMP_NP; break;
1132 case FP_COND_E: cond = PARISC_FCMP_E; break;
1133 case FP_COND_NE: cond = PARISC_FCMP_NE; break;
1134 case FP_COND_A: cond = PARISC_FCMP_A; break;
1135 case FP_COND_BE: cond = PARISC_FCMP_BE; break;
1136 case FP_COND_B: cond = PARISC_FCMP_B; break;
1137 case FP_COND_AE: cond = PARISC_FCMP_AE; break;
1138 default: internal(file_line, "cgen_fp_cmp_cond: invalid condition %u", aux);
1142 if (op_size == OP_SIZE_8)
1143 mc |= PARISC_FP_DOUBLE;
1144 g(cgen_3reg(ctx, mc, arg1[0] & 0x1f, arg2[0] & 0x1f, cond));
1148 static bool attr_w cgen_fp_test_reg(struct codegen_context *ctx)
1150 unsigned reg = cget_one(ctx);
1154 mc |= low_sign_ext_14(1);
1155 g(cgen_2reg(ctx, mc, R_ZERO, reg));
1157 cgen_four(PARISC_FTEST);
1160 mc |= low_sign_ext_14(0);
1161 g(cgen_2reg(ctx, mc, R_ZERO, reg));
1166 static bool attr_w cgen_fp_alu(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1169 uint8_t *arg1 = ctx->code_position;
1170 uint8_t *arg2 = arg1 + arg_size(*arg1);
1171 uint8_t *arg3 = arg2 + arg_size(*arg2);
1172 ctx->code_position = arg3 + arg_size(*arg3);
1174 case FP_ALU_ADD: mc = PARISC_FADD; break;
1175 case FP_ALU_SUB: mc = PARISC_FSUB; break;
1176 case FP_ALU_MUL: mc = PARISC_FMPY; break;
1177 case FP_ALU_DIV: mc = PARISC_FDIV; break;
1178 default: internal(file_line, "cgen_fp_alu: invalid alu %u", aux);
1181 case OP_SIZE_4: break;
1182 case OP_SIZE_8: mc |= PARISC_FP_DOUBLE; break;
1183 default: internal(file_line, "cgen_fp_alu: invalid size %u", op_size);
1185 g(cgen_3reg(ctx, mc, arg3[0] & 0x1f, arg2[0] & 0x1f, arg1[0] & 0x1f));
1189 static bool attr_w cgen_fp_alu1(struct codegen_context *ctx, unsigned op_size, unsigned aux)
1192 uint8_t *arg1 = ctx->code_position;
1193 uint8_t *arg2 = arg1 + arg_size(*arg1);
1194 ctx->code_position = arg2 + arg_size(*arg2);
1196 case FP_ALU1_NEG: mc = PARISC_FNEG; break;
1197 case FP_ALU1_SQRT: mc = PARISC_FSQRT; break;
1198 default: internal(file_line, "cgen_fp_alu1: invalid alu %u", aux);
1201 case OP_SIZE_4: break;
1202 case OP_SIZE_8: mc |= PARISC_FP_DOUBLE; break;
1203 default: internal(file_line, "cgen_fp_alu: invalid size %u", op_size);
1205 g(cgen_3reg(ctx, mc, 0, arg2[0] & 0x1f, arg1[0] & 0x1f));
1209 static bool attr_w cgen_fp_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1212 uint8_t *arg1 = ctx->code_position;
1213 uint8_t *arg2 = arg1 + arg_size(*arg1);
1214 ctx->code_position = arg2 + arg_size(*arg2);
1216 mc = PARISC_FCNVFXT;
1217 if (int_op_size == OP_SIZE_8)
1218 mc |= PARISC_FCNVFXT_TO_LONG;
1219 if (fp_op_size == OP_SIZE_8)
1220 mc |= PARISC_FCNVFXT_FROM_DOUBLE;
1221 mc |= arg1[0] & 0x1f;
1222 mc |= (uint32_t)(arg2[0] & 0x1f) << 21;
1227 static bool attr_w cgen_fp_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1230 uint8_t *arg1 = ctx->code_position;
1231 uint8_t *arg2 = arg1 + arg_size(*arg1);
1232 ctx->code_position = arg2 + arg_size(*arg2);
1235 if (int_op_size == OP_SIZE_8)
1236 mc |= PARISC_FCNVXF_FROM_LONG;
1237 if (fp_op_size == OP_SIZE_8)
1238 mc |= PARISC_FCNVXF_TO_DOUBLE;
1239 mc |= arg1[0] & 0x1f;
1240 mc |= (uint32_t)(arg2[0] & 0x1f) << 21;
1245 static bool attr_w cgen_cond_jmp(struct codegen_context *ctx, uint32_t mc, unsigned length, unsigned reg1, unsigned reg2, int reloc_offset)
1247 if (length == JMP_SHORTEST) {
1250 g(add_relocation(ctx, JMP_SHORTEST, reloc_offset, &need_nop));
1251 g(cgen_2reg(ctx, mc, reg2, reg1));
1252 if (unlikely(need_nop))
1253 cgen_four(PARISC_NOP);
1254 } else if (length == JMP_SHORT) {
1256 g(cgen_2reg(ctx, mc, reg2, reg1));
1257 g(add_relocation(ctx, JMP_SHORT, reloc_offset, NULL));
1258 cgen_four(PARISC_BL | PARISC_N);
1259 } else if (length == JMP_LONG && PA_20) {
1261 g(cgen_2reg(ctx, mc, reg2, reg1));
1262 g(add_relocation(ctx, JMP_LONG, reloc_offset, NULL));
1263 cgen_four(PARISC_BL_L | PARISC_N);
1266 mc |= assemble_12(3);
1267 g(cgen_2reg(ctx, mc, reg2, reg1));
1268 g(add_relocation(ctx, JMP_EXTRA_LONG, reloc_offset, NULL));
1269 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
1270 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
1271 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1272 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1277 static bool attr_w cgen_jmp_12regs(struct codegen_context *ctx, unsigned size, unsigned cond, unsigned length, unsigned reg1, unsigned reg2, int reloc_offset)
1281 fc = cmp_sub_cond[cond];
1282 if (length > JMP_SHORTEST)
1283 fc ^= PARISC_COND_NEG;
1284 if (size == OP_SIZE_4)
1285 mc = !(fc & PARISC_COND_NEG) ? PARISC_CMPB : PARISC_CMPB_NOT;
1287 mc = !(fc & PARISC_COND_NEG) ? PARISC_CMPB_64 : PARISC_CMPB_64_NOT;
1288 mc |= ((uint32_t)fc & ~PARISC_COND_NEG);
1289 g(cgen_cond_jmp(ctx, mc, length, reg1, reg2, reloc_offset));
1293 static bool attr_w cgen_jmp(struct codegen_context *ctx, unsigned length)
1295 if (length <= JMP_SHORT) {
1296 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1297 cgen_four(PARISC_BL | PARISC_N);
1298 } else if (length == JMP_LONG && PA_20) {
1299 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1300 cgen_four(PARISC_BL_L | PARISC_N);
1302 g(add_relocation(ctx, JMP_EXTRA_LONG, 0, NULL));
1303 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
1304 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
1305 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1306 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1311 static bool attr_w cgen_jmp_reg(struct codegen_context *ctx, unsigned size, unsigned cond, unsigned length)
1313 unsigned reg = cget_one(ctx);
1314 return cgen_jmp_12regs(ctx, size, cond, length, reg, 0, 1);
1317 static bool attr_w cgen_jmp_reg_bit(struct codegen_context *ctx, unsigned size, unsigned bit, bool jnz, unsigned length)
1320 unsigned reg = cget_one(ctx);
1321 if (length > JMP_SHORTEST)
1323 if (size == OP_SIZE_4 || bit < 32) {
1325 mc = jnz ? PARISC_BB_1 : PARISC_BB_0;
1328 mc = jnz ? PARISC_BB_64_1 : PARISC_BB_64_0;
1330 g(cgen_cond_jmp(ctx, mc, length, reg, bit, 1));
1334 static bool attr_w cgen_jmp_2regs(struct codegen_context *ctx, unsigned size, unsigned cond, unsigned length)
1336 uint8_t *arg1 = ctx->code_position;
1337 uint8_t *arg2 = arg1 + arg_size(*arg1);
1338 ctx->code_position = arg2 + arg_size(*arg2);
1340 return cgen_jmp_12regs(ctx, size, cond, length, arg1[0], arg2[0], 2);
1341 if (arg2[0] == ARG_IMM) {
1342 int64_t imm = get_imm(&arg2[1]);
1345 cond = cmp_swap_arguments(cond);
1346 fc = cmp_sub_cond[cond];
1347 if (length > JMP_SHORTEST)
1348 fc ^= PARISC_COND_NEG;
1349 if (size == OP_SIZE_4) {
1350 mc = fc & PARISC_COND_NEG ? PARISC_CMPIB_NOT : PARISC_CMPIB;
1351 mc |= fc & ~PARISC_COND_NEG;
1353 mc = PARISC_CMPIB_64;
1355 case PARISC_COND_EQUAL: mc |= 1 << 13; break;
1356 case PARISC_COND_NOT_EQUAL: mc |= 5 << 13; break;
1357 case PARISC_COND_L_S: mc |= 2 << 13; break;
1358 case PARISC_COND_GE_S: mc |= 6 << 13; break;
1359 case PARISC_COND_LE_S: mc |= 3 << 13; break;
1360 case PARISC_COND_G_S: mc |= 7 << 13; break;
1361 case PARISC_COND_L_U: mc |= 0 << 13; break;
1362 case PARISC_COND_GE_U: mc |= 4 << 13; break;
1363 default: internal(file_line, "cgen_jmp_2regs: unsupported condition %x", fc);
1366 g(cgen_cond_jmp(ctx, mc, length, low_sign_ext_5(imm), arg1[0], 10));
1369 internal(file_line, "cgen_jmp_2regs: invalid arguments %02x, %02x", arg1[0], arg2[0]);
1373 static bool attr_w cgen_jmp_fp_test(struct codegen_context *ctx, unsigned length)
1375 cgen_four(PARISC_FTEST);
1376 if (length <= JMP_SHORT) {
1377 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1378 cgen_four(PARISC_BL | PARISC_N);
1379 } else if (length == JMP_LONG && PA_20) {
1380 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1381 cgen_four(PARISC_BL_L | PARISC_N);
1383 cgen_four(PARISC_BL | PARISC_N | assemble_12(0));
1384 cgen_four(PARISC_BL | PARISC_N | assemble_12(3));
1385 g(add_relocation(ctx, JMP_EXTRA_LONG, 0, NULL));
1386 cgen_four(PARISC_LDIL | ((uint32_t)R_CG_SCRATCH << 21));
1387 g(cgen_2reg(ctx, PARISC_LDO, R_CG_SCRATCH, R_CG_SCRATCH));
1388 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1389 g(cgen_2reg(ctx, PARISC_BLR | PARISC_N, R_ZERO, R_CG_SCRATCH));
1394 static bool attr_w cgen_jmp_indirect(struct codegen_context *ctx, unsigned reg)
1397 #ifdef ARCH_PARISC32
1400 mc = PARISC_BVE_RET;
1401 mc |= (uint32_t)reg << 21;
1403 mc = PARISC_STW_LONG;
1404 mc |= low_sign_ext_14(-0x18);
1405 g(cgen_2reg(ctx, mc, R_SP, R_RP));
1407 mc = PARISC_BVE_RET;
1408 mc |= (uint32_t)reg << 21;
1415 mc |= (uint32_t)reg << 21;
1419 mc |= (uint32_t)R_CG_SCRATCH << 16;
1422 mc |= (uint32_t)reg << 21;
1424 mc = PARISC_STW_LONG;
1425 mc |= low_sign_ext_14(-0x18);
1426 g(cgen_2reg(ctx, mc, R_SP, R_RP));
1429 mc |= (uint32_t)reg << 21;
1436 mc |= (uint32_t)reg << 21;
1440 if (unlikely(!ctx->fn))
1441 cgen_four(PARISC_NOP);
1445 static bool attr_w cgen_call_millicode(struct codegen_context attr_unused *ctx)
1447 #ifdef ARCH_PARISC32
1449 unsigned reg = R_SCRATCH_NA_1;
1454 mc |= assemble_12(1);
1456 g(cgen_2reg(ctx, mc, bit, reg));
1459 mc |= PARISC_LD_ST_W;
1460 mc |= PARISC_LD_ST_IMM;
1461 mc |= PARISC_LD_ST_LD;
1462 g(cgen_3reg(ctx, mc, low_sign_ext_5(2), reg, R_19));
1463 g(cgen_3reg(ctx, mc, low_sign_ext_5(-2), reg, reg));
1465 g(cgen_jmp_indirect(ctx, reg));
1470 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1474 int64_t offs = (int64_t)(ctx->label_to_pos[reloc->label_id] >> 2) - (int64_t)(reloc->position >> 2) - 2;
1475 switch (reloc->length) {
1477 if (unlikely(offs < -0x800) || unlikely(offs >= 0x800))
1479 memcpy(&mc, ctx->mcode + reloc->position, 4);
1481 mc |= assemble_12(offs);
1482 memcpy(ctx->mcode + reloc->position, &mc, 4);
1485 if (unlikely(offs < -0x10000) || unlikely(offs >= 0x10000))
1487 memcpy(&mc, ctx->mcode + reloc->position, 4);
1489 mc |= assemble_17(offs);
1490 memcpy(ctx->mcode + reloc->position, &mc, 4);
1493 if (unlikely(offs < -0x200000) || unlikely(offs >= 0x200000))
1495 memcpy(&mc, ctx->mcode + reloc->position, 4);
1497 mc |= assemble_22(offs);
1498 memcpy(ctx->mcode + reloc->position, &mc, 4);
1500 case JMP_EXTRA_LONG:
1502 if (unlikely(offs != (int32_t)offs))
1504 memcpy(&mc4, ctx->mcode + reloc->position, 16);
1505 mc4[0] &= ~0x001fffffU;
1506 mc4[0] |= assemble_21((uint64_t)offs >> 1 >> 11);
1507 mc4[1] &= ~0x00003fffU;
1508 mc4[1] |= low_sign_ext_14(((uint64_t)offs >> 1) & 0x7ff);
1510 mc4[2] = PARISC_NOP;
1512 mc4[3] = PARISC_NOP;
1513 memcpy(ctx->mcode + reloc->position, &mc4, 16);
1516 internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1521 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1523 /*debug("insn: %08x", insn);*/
1524 switch (insn_opcode(insn)) {
1535 g(cgen_call(ctx, insn_jump_size(insn)));
1537 case INSN_CALL_INDIRECT:
1538 g(cgen_call_indirect(ctx));
1541 g(cgen_mov(ctx, insn_op_size(insn)));
1544 g(cgen_movsx(ctx, insn_op_size(insn)));
1546 case INSN_CMP_DEST_REG:
1547 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1549 g(cgen_cmp_dest_reg(ctx, insn_op_size(insn), insn_aux(insn)));
1552 case INSN_ALU_FLAGS:
1553 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1555 g(cgen_alu(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), false, insn_jump_size(insn)));
1558 case INSN_ALU_FLAGS_TRAP:
1559 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1561 g(cgen_alu(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), true, insn_jump_size(insn)));
1564 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1566 g(cgen_alu1(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), false, insn_jump_size(insn)));
1568 case INSN_ALU1_TRAP:
1569 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1571 g(cgen_alu1(ctx, insn_op_size(insn), insn_writes_flags(insn), insn_aux(insn), true, insn_jump_size(insn)));
1574 if (unlikely(insn_op_size(insn) < OP_SIZE_4) || unlikely(insn_writes_flags(insn) != 0))
1576 g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1579 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1581 g(cgen_btx(ctx, insn_op_size(insn), insn_aux(insn)));
1584 if (unlikely(insn_writes_flags(insn) != 0))
1586 g(cgen_cmp_cmov(ctx, insn_op_size(insn), insn_aux(insn)));
1589 if (unlikely(insn_op_size(insn) != OP_SIZE_NATIVE) || unlikely(insn_writes_flags(insn) != 0))
1591 g(cgen_movr(ctx, insn_aux(insn)));
1593 case INSN_FP_CMP_COND:
1594 g(cgen_fp_cmp_cond(ctx, insn_op_size(insn), insn_aux(insn)));
1596 case INSN_FP_TEST_REG:
1597 g(cgen_fp_test_reg(ctx));
1600 g(cgen_fp_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1603 g(cgen_fp_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1605 case INSN_FP_TO_INT32:
1606 case INSN_FP_TO_INT64:
1607 g(cgen_fp_to_int(ctx, insn_opcode(insn) == INSN_FP_TO_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1609 case INSN_FP_FROM_INT32:
1610 case INSN_FP_FROM_INT64:
1611 g(cgen_fp_from_int(ctx, insn_opcode(insn) == INSN_FP_FROM_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1614 g(cgen_jmp(ctx, insn_jump_size(insn)));
1617 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1619 g(cgen_jmp_reg(ctx, insn_op_size(insn), insn_aux(insn), insn_jump_size(insn)));
1621 case INSN_JMP_REG_BIT:
1622 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1624 g(cgen_jmp_reg_bit(ctx, insn_op_size(insn), insn_aux(insn) & 63, insn_aux(insn) >> 6, insn_jump_size(insn)));
1626 case INSN_JMP_2REGS:
1627 if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1629 g(cgen_jmp_2regs(ctx, insn_op_size(insn), insn_aux(insn), insn_jump_size(insn)));
1631 case INSN_JMP_FP_TEST:
1632 g(cgen_jmp_fp_test(ctx, insn_jump_size(insn)));
1634 case INSN_JMP_INDIRECT:
1635 g(cgen_jmp_indirect(ctx, cget_one(ctx)));
1637 case INSN_CALL_MILLICODE:
1638 g(cgen_call_millicode(ctx));
1642 internal(file_line, "cgen_insn: invalid insn %08x", insn);