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