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