alpha: fix compilation failure in do_cvt_to_int
[ajla.git] / c1-ia64.inc
blobd106badd338511df1dfd5ff376134c30ae5200bc
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 OP_SIZE_NATIVE                  OP_SIZE_8
20 #define OP_SIZE_ADDRESS                 OP_SIZE_NATIVE
22 #define JMP_LIMIT                       (cpu_test_feature(CPU_FEATURE_brl) ? JMP_SHORT : JMP_SHORTEST)
24 #define UNALIGNED_TRAP                  1
26 #define ALU_WRITES_FLAGS(alu, im)       0
27 #define ALU1_WRITES_FLAGS(alu)          0
28 #define ROT_WRITES_FLAGS(alu, size, im) 0
29 #define COND_IS_LOGICAL(cond)           0
31 #define ARCH_PARTIAL_ALU(size)          0
32 #define ARCH_IS_3ADDRESS(alu, f)        1
33 #define ARCH_IS_3ADDRESS_IMM(alu, f)    1
34 #define ARCH_IS_3ADDRESS_ROT(alu, size) 1
35 #define ARCH_IS_3ADDRESS_ROT_IMM(alu)   1
36 #define ARCH_IS_2ADDRESS(alu)           1
37 #define ARCH_IS_3ADDRESS_FP             1
38 #define ARCH_HAS_FLAGS                  0
39 #define ARCH_PREFERS_SX(size)           0
40 #define ARCH_HAS_BWX                    1
41 #define ARCH_HAS_MUL                    0
42 #define ARCH_HAS_DIV                    0
43 #define ARCH_HAS_ANDN                   1
44 #define ARCH_HAS_SHIFTED_ADD(bits)      ((bits) <= 4)
45 #define ARCH_HAS_BTX(btx, size, cnst)   (((btx) == BTX_BTS || (btx) == BTX_BTR) && (cnst))
46 #define ARCH_SHIFT_SIZE                 32
47 #define ARCH_NEEDS_BARRIER              0
49 #define i_size(size)                    OP_SIZE_NATIVE
50 #define i_size_rot(size)                OP_SIZE_NATIVE
51 #define i_size_cmp(size)                maximum(size, OP_SIZE_4)
53 #define N_SAVED_REGS    0x40
55 #define R_ZERO          0x00
56 #define R_GP            0x01
57 #define R_2             0x02
58 #define R_3             0x03
59 #define R_4             0x04
60 #define R_5             0x05
61 #define R_6             0x06
62 #define R_7             0x07
63 #define R_8             0x08
64 #define R_9             0x09
65 #define R_10            0x0a
66 #define R_11            0x0b
67 #define R_SP            0x0c
68 #define R_TP            0x0d
69 #define R_14            0x0e
70 #define R_15            0x0f
71 #define R_16            0x10
72 #define R_17            0x11
73 #define R_18            0x12
74 #define R_19            0x13
75 #define R_20            0x14
76 #define R_21            0x15
77 #define R_22            0x16
78 #define R_23            0x17
79 #define R_24            0x18
80 #define R_25            0x19
81 #define R_26            0x1a
82 #define R_27            0x1b
83 #define R_28            0x1c
84 #define R_29            0x1d
85 #define R_30            0x1e
86 #define R_31            0x1f
87 #define R_32            0x20
88 #define R_33            0x21
89 #define R_34            0x22
90 #define R_35            0x23
91 #define R_36            0x24
92 #define R_37            0x25
93 #define R_38            0x26
94 #define R_39            0x27
95 #define R_40            0x28
96 #define R_41            0x29
97 #define R_42            0x2a
98 #define R_43            0x2b
99 #define R_44            0x2c
100 #define R_45            0x2d
101 #define R_46            0x2e
102 #define R_47            0x2f
103 #define R_48            0x30
104 #define R_49            0x31
105 #define R_50            0x32
106 #define R_51            0x33
107 #define R_52            0x34
108 #define R_53            0x35
109 #define R_54            0x36
110 #define R_55            0x37
111 #define R_56            0x38
112 #define R_57            0x39
113 #define R_58            0x3a
114 #define R_59            0x3b
115 #define R_60            0x3c
116 #define R_61            0x3d
117 #define R_62            0x3e
118 #define R_63            0x3f
119 #define R_64            0x40
120 #define R_65            0x41
121 #define R_66            0x42
122 #define R_67            0x43
123 #define R_68            0x44
124 #define R_69            0x45
125 #define R_70            0x46
126 #define R_71            0x47
127 #define R_72            0x48
128 #define R_73            0x49
129 #define R_74            0x4a
130 #define R_75            0x4b
131 #define R_76            0x4c
132 #define R_77            0x4d
133 #define R_78            0x4e
134 #define R_79            0x4f
135 #define R_80            0x50
136 #define R_81            0x51
137 #define R_82            0x52
138 #define R_83            0x53
139 #define R_84            0x54
140 #define R_85            0x55
141 #define R_86            0x56
142 #define R_87            0x57
143 #define R_88            0x58
144 #define R_89            0x59
145 #define R_90            0x5a
146 #define R_91            0x5b
147 #define R_92            0x5c
148 #define R_93            0x5d
149 #define R_94            0x5e
150 #define R_95            0x5f
152 #define FR_ZERO         0x60
153 #define FR_ONE          0x61
154 #define FR_2            0x62
155 #define FR_3            0x63
156 #define FR_4            0x64
157 #define FR_5            0x65
158 #define FR_6            0x66
159 #define FR_7            0x67
160 #define FR_8            0x68
161 #define FR_9            0x69
162 #define FR_10           0x6a
163 #define FR_11           0x6b
164 #define FR_12           0x6c
165 #define FR_13           0x6d
166 #define FR_14           0x6e
167 #define FR_15           0x6f
168 #define FR_16           0x70
169 #define FR_17           0x71
170 #define FR_18           0x72
171 #define FR_19           0x73
172 #define FR_20           0x74
173 #define FR_21           0x75
174 #define FR_22           0x76
175 #define FR_23           0x77
176 #define FR_24           0x78
177 #define FR_25           0x79
178 #define FR_26           0x7a
179 #define FR_27           0x7b
180 #define FR_28           0x7c
181 #define FR_29           0x7d
182 #define FR_30           0x7e
183 #define FR_31           0x7f
184 #define FR_32           0x80
185 #define FR_33           0x81
186 #define FR_34           0x82
187 #define FR_35           0x83
188 #define FR_36           0x84
189 #define FR_37           0x85
190 #define FR_38           0x86
191 #define FR_39           0x87
192 #define FR_40           0x88
193 #define FR_41           0x89
194 #define FR_42           0x8a
195 #define FR_43           0x8b
196 #define FR_44           0x8c
197 #define FR_45           0x8d
198 #define FR_46           0x8e
199 #define FR_47           0x8f
200 #define FR_48           0x90
201 #define FR_49           0x91
202 #define FR_50           0x92
203 #define FR_51           0x93
204 #define FR_52           0x94
205 #define FR_53           0x95
206 #define FR_54           0x96
207 #define FR_55           0x97
208 #define FR_56           0x98
209 #define FR_57           0x99
210 #define FR_58           0x9a
211 #define FR_59           0x9b
212 #define FR_60           0x9c
213 #define FR_61           0x9d
214 #define FR_62           0x9e
215 #define FR_63           0x9f
217 #define P_0             0xa0
218 #define P_1             0xa1
219 #define P_2             0xa2
220 #define P_3             0xa3
221 #define P_4             0xa4
222 #define P_5             0xa5
223 #define P_6             0xa6
224 #define P_7             0xa7
226 #define B_0             0xb0
227 #define B_1             0xb1
228 #define B_2             0xb2
229 #define B_3             0xb3
230 #define B_4             0xb4
231 #define B_5             0xb5
232 #define B_6             0xb6
233 #define B_7             0xb7
235 #define R_FRAME         R_32
236 #define R_UPCALL        R_33
237 #define R_TIMESTAMP     R_34
238 #define R_ENTRY         R_35
239 #define R_SAVED_1       R_35
240 #define R_SAVED_2       R_36
241 #define R_SAVED_B0      R_37
242 #define R_SAVED_AR_PFS  R_38
243 #define R_ARG0          (R_32 + N_SAVED_REGS - 4)
244 #define R_ARG1          (R_32 + N_SAVED_REGS - 3)
245 #define R_ARG2          (R_32 + N_SAVED_REGS - 2)
246 #define R_ARG3          (R_32 + N_SAVED_REGS - 1)
248 #define R_RET0          R_8
249 #define R_RET1          R_9
250 #define R_SCRATCH_NA_1  R_14
251 #define R_SCRATCH_NA_2  R_15
252 #define R_SCRATCH_NA_3  R_16
253 #define R_SCRATCH_1     R_17
254 #define R_SCRATCH_2     R_18
255 #define R_SCRATCH_3     R_19
256 #define R_SCRATCH_4     R_20
258 #define R_OFFSET_IMM    R_2
259 #define R_CONST_IMM     R_3
260 #define R_CMP_RESULT    P_6
262 #define R_SCRATCH_B     B_6
264 #define FR_SCRATCH_1    FR_6
265 #define FR_SCRATCH_2    FR_7
267 #define SUPPORTED_FP    0xe
269 static inline bool reg_is_gr(unsigned reg)
271         return reg < 0x60;
274 static inline bool reg_is_fp(unsigned reg)
276         return reg >= 0x60 && reg < 0xa0;
279 static inline bool reg_is_p(unsigned reg)
281         return reg >= 0xa0 && reg < 0xa8;
284 static inline bool reg_is_b(unsigned reg)
286         return reg >= 0xb0 && reg < 0xb8;
289 static inline uint64_t bits_gr(unsigned reg)
291         ajla_assert_lo(reg_is_gr(reg), (file_line, "bits_gr: register %x", reg));
292         return reg;
295 static inline uint64_t bits_fp(unsigned reg)
297         ajla_assert_lo(reg_is_fp(reg), (file_line, "bits_fp: register %x", reg));
298         return reg - 0x60;
301 static inline uint64_t bits_p(unsigned reg)
303         ajla_assert_lo(reg_is_p(reg), (file_line, "bits_p: register %x", reg));
304         return reg - 0xa0;
307 static inline uint64_t bits_b(unsigned reg)
309         ajla_assert_lo(reg_is_b(reg), (file_line, "bits_b: register %x", reg));
310         return reg - 0xb0;
313 static const uint8_t regs_saved[] = {
314         R_39,
315         R_40,
316         R_41,
317         R_42,
318         R_43,
319         R_44,
320         R_45,
321         R_46,
322         R_47,
323         R_48,
324         R_49,
325         R_50,
326         R_51,
327         R_52,
328         R_53,
329         R_54,
330         R_55,
331         R_56,
332         R_57,
333         R_58,
334         R_59,
335         R_60,
336         R_61,
337         R_62,
338         R_63,
339         R_64,
340         R_65,
341         R_66,
342         R_67,
343         R_68,
344         R_69,
345         R_70,
346         R_71,
347         R_72,
348         R_73,
349         R_74,
350         R_75,
351         R_76,
352         R_77,
353         R_78,
354         R_79,
355         R_80,
356         R_81,
357         R_82,
358         R_83,
359         R_84,
360         R_85,
361         R_86,
362         R_87,
363         R_88,
364         R_89,
365         R_90,
366         R_91,
368 static const uint8_t regs_volatile[] = {
369         R_10,
370         R_11,
371         R_21,
372         R_22,
373         R_23,
374         R_24,
375         R_25,
376         R_26,
377         R_27,
378         R_28,
379         R_29,
380         R_30,
381         R_31,
383 static const uint8_t fp_saved[] = { 0 };
384 #define n_fp_saved 0U
385 static const uint8_t fp_volatile[] = {
386         FR_8,
387         FR_9,
388         FR_10,
389         FR_11,
390         FR_12,
391         FR_13,
392         FR_14,
393         FR_15,
394         FR_32,
395         FR_33,
396         FR_34,
397         FR_35,
398         FR_36,
399         FR_37,
400         FR_38,
401         FR_39,
402         FR_40,
403         FR_41,
404         FR_42,
405         FR_43,
406         FR_44,
407         FR_45,
408         FR_46,
409         FR_47,
410         FR_48,
411         FR_49,
412         FR_50,
413         FR_51,
414         FR_52,
415         FR_53,
416         FR_54,
417         FR_55,
418         FR_56,
419         FR_57,
420         FR_58,
421         FR_59,
422         FR_60,
423         FR_61,
424         FR_62,
425         FR_63,
427 #define reg_is_saved(r) ((r) >= R_32 && (r) <= R_95)
429 static bool attr_w gen_load_constant(struct codegen_context *ctx, unsigned reg, uint64_t c)
431         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
432         gen_one(reg);
433         gen_one(ARG_IMM);
434         gen_eight(c);
435         return true;
438 static bool attr_w gen_imm(struct codegen_context *ctx, int64_t imm, unsigned purpose, unsigned size);
440 static bool attr_w gen_address(struct codegen_context *ctx, unsigned base, int64_t imm, unsigned attr_unused purpose, unsigned attr_unused size)
442         if (!imm) {
443                 ctx->offset_imm = imm;
444                 ctx->offset_reg = false;
445                 ctx->base_reg = base;
446         } else {
447                 g(gen_imm(ctx, imm, IMM_PURPOSE_ADD, OP_SIZE_NATIVE));
448                 gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_ADD, 0);
449                 gen_one(R_OFFSET_IMM);
450                 gen_one(base);
451                 gen_imm_offset();
452                 ctx->offset_imm = 0;
453                 ctx->offset_reg = false;
454                 ctx->base_reg = R_OFFSET_IMM;
455         }
456         return true;
459 static bool is_direct_const(int64_t imm, unsigned purpose, unsigned size)
461         switch (purpose) {
462                 case IMM_PURPOSE_STORE_VALUE:
463                         if (!imm)
464                                 return true;
465                         break;
466                 case IMM_PURPOSE_ADD:
467                 case IMM_PURPOSE_MOVR:
468                         if (imm >= -0x2000 && imm < 0x2000)
469                                 return true;
470                         break;
471                 case IMM_PURPOSE_SUB:
472                         if (imm > -0x2000 && imm <= 0x2000)
473                                 return true;
474                         break;
475                 case IMM_PURPOSE_AND:
476                 case IMM_PURPOSE_OR:
477                 case IMM_PURPOSE_XOR:
478                         if (imm >= -0x80 && imm < 0x80)
479                                 return true;
480                         break;
481                 case IMM_PURPOSE_CMP:
482                 case IMM_PURPOSE_CMP_LOGICAL:
483                         if (imm > -0x80 && imm < 0x80)
484                                 return true;
485                         break;
486                 case IMM_PURPOSE_ANDN:
487                         break;
488                 case IMM_PURPOSE_TEST:
489                         break;
490                 case IMM_PURPOSE_BITWISE:
491                         return true;
492                 default:
493                         internal(file_line, "is_direct_const: invalid purpose %u (imm %"PRIxMAX", size %u)", purpose, (uintmax_t)imm, size);
494         }
495         return false;
498 static bool attr_w gen_imm(struct codegen_context *ctx, int64_t imm, unsigned purpose, unsigned size)
500         if (is_direct_const(imm, purpose, size)) {
501                 ctx->const_imm = imm;
502                 ctx->const_reg = false;
503         } else {
504                 g(gen_load_constant(ctx, R_CONST_IMM, imm));
505                 ctx->const_reg = true;
506         }
507         return true;
510 static bool attr_w gen_entry(struct codegen_context *ctx)
512         gen_insn(INSN_IA64_ALLOC, OP_SIZE_NATIVE, 0, 0);
513         gen_one(R_SAVED_AR_PFS);
514         gen_one(ARG_IMM);
515         gen_eight(N_SAVED_REGS);
516         gen_one(ARG_IMM);
517         gen_eight(N_SAVED_REGS - 4);
519         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
520         gen_one(R_SAVED_B0);
521         gen_one(B_0);
523         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
524         gen_one(R_ENTRY);
526         gen_insn(INSN_RET, 0, 0, 0);
528         return true;
531 static bool attr_w gen_escape_arg(struct codegen_context *ctx, ip_t ip, uint32_t escape_label)
533         g(gen_load_constant(ctx, R_RET1, ip));
535         gen_insn(INSN_JMP, 0, 0, 0);
536         gen_four(escape_label);
538         return true;
541 static bool attr_w gen_escape(struct codegen_context *ctx)
543         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
544         gen_one(R_RET0);
545         gen_one(R_FRAME);
547         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
548         gen_one(B_0);
549         gen_one(R_SAVED_B0);
551         gen_insn(INSN_IA64_DEALLOC, OP_SIZE_NATIVE, 0, 0);
552         gen_one(R_SAVED_AR_PFS);
554         gen_insn(INSN_RET, 0, 0, 0);
556         return true;
559 static bool attr_w gen_upcall_argument(struct codegen_context attr_unused *ctx, unsigned attr_unused arg)
561         return true;
564 static bool attr_w gen_upcall(struct codegen_context *ctx, unsigned offset, unsigned n_args)
566         g(gen_address(ctx, R_UPCALL, offset, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
567         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
568         gen_one(R_SCRATCH_NA_1);
569         gen_address_offset();
571         g(gen_address(ctx, R_SCRATCH_NA_1, 0, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
572         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
573         gen_one(R_SCRATCH_NA_2);
574         gen_address_offset();
576         g(gen_address(ctx, R_SCRATCH_NA_1, 8, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
577         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
578         gen_one(R_GP);
579         gen_address_offset();
581         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
582         gen_one(R_SCRATCH_B);
583         gen_one(R_SCRATCH_NA_2);
585         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_8, 0, 0);
586         gen_one(R_SCRATCH_B);
588         g(gen_upcall_end(ctx, n_args));
590         return true;
593 static bool attr_w gen_cmp_test_jmp(struct codegen_context *ctx, unsigned insn, unsigned op_size, unsigned reg1, unsigned reg2, unsigned cond, uint32_t label);
595 static bool attr_w gen_timestamp_test(struct codegen_context *ctx, uint32_t escape_label)
597         g(gen_address(ctx, R_UPCALL, offsetof(struct cg_upcall_vector_s, ts), IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
598         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
599         gen_one(R_SCRATCH_1);
600         gen_address_offset();
602         g(gen_cmp_test_jmp(ctx, INSN_CMP, OP_SIZE_4, R_SCRATCH_1, R_TIMESTAMP, COND_NE, escape_label));
604         return true;