x86: allocate registers on windows
[ajla.git] / c1-x86.inc
blobb6c3e68e4ef1dc957a876bb2f1ebd580162164e6
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 #ifdef ARCH_X86_32
20 #define OP_SIZE_NATIVE                  OP_SIZE_4
21 #else
22 #define OP_SIZE_NATIVE                  OP_SIZE_8
23 #endif
25 #ifndef ARCH_X86_64
26 #define OP_SIZE_ADDRESS                 OP_SIZE_4
27 #else
28 #define OP_SIZE_ADDRESS                 OP_SIZE_8
29 #endif
31 #define JMP_LIMIT                       JMP_LONG
33 #define UNALIGNED_TRAP                  0
35 #define ALU_WRITES_FLAGS(alu, im)       ((alu) != ALU_ADD ? 3 : 0)
36 #define ALU1_WRITES_FLAGS(alu)          ((alu) == ALU1_INC || (alu) == ALU1_DEC ? 1 : (alu) == ALU1_NOT || (alu) == ALU1_BSWAP ? 0 : 3)
37 #define ROT_WRITES_FLAGS(alu)           1
38 #define COND_IS_LOGICAL(cond)           0
40 #define ARCH_PARTIAL_ALU(size)          ((size) <= OP_SIZE_2)
41 #define ARCH_IS_3ADDRESS                0
42 #define ARCH_HAS_FLAGS                  1
43 #define ARCH_PREFERS_SX(size)           0
44 #define ARCH_HAS_BWX                    1
45 #define ARCH_HAS_MUL                    1
46 #define ARCH_HAS_DIV                    1
47 #define ARCH_HAS_ANDN                   0
48 #define ARCH_HAS_BTX(btx, size, cnst)   ((btx) != BTX_BTEXT && (size) >= OP_SIZE_2)
49 #define ARCH_HAS_SHIFTED_ADD(bits)      ((bits) <= 3)
50 #define ARCH_SHIFT_SIZE                 OP_SIZE_4
51 #define ARCH_NEEDS_BARRIER              0
53 #define i_size(size)                    (size)
54 #define i_size_rot(size)                (size)
56 #define R_AX            0x0
57 #define R_CX            0x1
58 #define R_DX            0x2
59 #define R_BX            0x3
60 #define R_SP            0x4
61 #define R_BP            0x5
62 #define R_SI            0x6
63 #define R_DI            0x7
64 #define R_R8            0x8
65 #define R_R9            0x9
66 #define R_R10           0xa
67 #define R_R11           0xb
68 #define R_R12           0xc
69 #define R_R13           0xd
70 #define R_R14           0xe
71 #define R_R15           0xf
73 #define R_ST0           0x10
74 #define R_ST1           0x11
75 #define R_ST2           0x12
76 #define R_ST3           0x13
77 #define R_ST4           0x14
78 #define R_ST5           0x15
79 #define R_ST6           0x16
80 #define R_ST7           0x17
82 #define R_XMM0          0x20
83 #define R_XMM1          0x21
84 #define R_XMM2          0x22
85 #define R_XMM3          0x23
86 #define R_XMM4          0x24
87 #define R_XMM5          0x25
88 #define R_XMM6          0x26
89 #define R_XMM7          0x27
90 #define R_XMM8          0x28
91 #define R_XMM9          0x29
92 #define R_XMM10         0x2a
93 #define R_XMM11         0x2b
94 #define R_XMM12         0x2c
95 #define R_XMM13         0x2d
96 #define R_XMM14         0x2e
97 #define R_XMM15         0x2f
98 #define R_XMM16         0x30
99 #define R_XMM17         0x31
100 #define R_XMM18         0x32
101 #define R_XMM19         0x33
102 #define R_XMM20         0x34
103 #define R_XMM21         0x35
104 #define R_XMM22         0x36
105 #define R_XMM23         0x37
106 #define R_XMM24         0x38
107 #define R_XMM25         0x39
108 #define R_XMM26         0x3a
109 #define R_XMM27         0x3b
110 #define R_XMM28         0x3c
111 #define R_XMM29         0x3d
112 #define R_XMM30         0x3e
113 #define R_XMM31         0x3f
115 #define R_IS_GPR(r)     ((r) < 16)
116 #define R_IS_XMM(r)     ((r) >= R_XMM0 && (r) <= R_XMM31)
118 /*#define TIMESTAMP_IN_REGISTER*/
120 #ifndef ARCH_X86_32
121 #define R_UPCALL        R_R15
122 #ifdef TIMESTAMP_IN_REGISTER
123 #define R_TIMESTAMP     R_R14
124 #endif
125 #define R_CONST_IMM     R_R11
126 #else
127 #define R_CONST_IMM     255     /* this should not be used */
128 #endif
129 #define R_OFFSET_IMM    255     /* this should not be used */
131 #if defined(ARCH_X86_32)
132 #define R_FRAME         R_BP
133 #define R_SCRATCH_1     R_AX
134 #define R_SCRATCH_2     R_DX
135 #define R_SCRATCH_3     R_CX
136 #define R_SCRATCH_4     R_SAVED_2
137 #define R_SAVED_1       R_SI
138 #define R_SAVED_2       R_DI
139 #elif defined(ARCH_X86_WIN_ABI)
140 #define R_FRAME         R_BP
141 #define R_SCRATCH_1     R_AX
142 #define R_SCRATCH_2     R_DX
143 #define R_SCRATCH_3     R_CX
144 #define R_SCRATCH_4     R_SAVED_2
145 #define R_SAVED_1       R_SI
146 #define R_SAVED_2       R_DI
147 #else
148 #define R_FRAME         R_BX
149 #define R_SCRATCH_1     R_AX
150 #define R_SCRATCH_2     R_DX
151 #define R_SCRATCH_3     R_CX
152 #define R_SCRATCH_4     R_SAVED_2
153 #define R_SAVED_1       R_BP
154 #define R_SAVED_2       R_R12
155 #endif
157 #define FR_SCRATCH_1    R_XMM0
158 #define FR_SCRATCH_2    R_XMM1
160 #if defined(ARCH_X86_32)
161 #define R_ARG0          R_AX
162 #define R_ARG1          R_AX
163 #define R_ARG2          R_AX
164 #define R_ARG3          R_AX
165 #elif defined(ARCH_X86_WIN_ABI)
166 #define R_ARG0          R_CX
167 #define R_ARG1          R_DX
168 #define R_ARG2          R_R8
169 #define R_ARG3          R_R9
170 #else
171 #define R_ARG0          R_DI
172 #define R_ARG1          R_SI
173 #define R_ARG2          R_DX
174 #define R_ARG3          R_CX
175 #endif
176 #define R_RET0          R_AX
178 #if defined(ARCH_X86_32)
179 #define ARG_SPACE       0x1c            /* must be 0xc modulo 0x10 */
180 #define ARG_OFFSET      0x14
181 #elif defined(ARCH_X86_WIN_ABI) && !defined(TIMESTAMP_IN_REGISTER)
182 #define ARG_SPACE       0x28            /* must be 0x8 modulo 0x10 */
183 #define ARG_OFFSET      0xa0
184 #elif defined(ARCH_X86_WIN_ABI)
185 #define ARG_SPACE       0x20            /* must be 0x0 modulo 0x10 */
186 #define ARG_OFFSET      0x90
187 #endif
189 #define SUPPORTED_FP            (cpu_test_feature(CPU_FEATURE_sse) * 0x2 + cpu_test_feature(CPU_FEATURE_sse2) * 0x4)
190 #define SUPPORTED_FP_X87        0xe
191 #define SUPPORTED_FP_HALF_CVT   (cpu_test_feature(CPU_FEATURE_f16c) * 0x1)
193 static bool reg_is_fp(unsigned reg)
195         return reg >= 0x20 && reg < 0x40;
198 #if defined(ARCH_X86_32)
200 static const uint8_t regs_saved[] = { R_BX };
201 static const uint8_t regs_volatile[] = { 0 };
202 #define n_regs_volatile 0U
203 static const uint8_t fp_saved[] = { 0 };
204 #define n_fp_saved 0U
205 static const uint8_t fp_volatile[] = { R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7 };
206 #define reg_is_saved(r) ((r) == R_BX)
208 #elif defined(ARCH_X86_WIN_ABI)
210 static const uint8_t regs_saved[] = { R_BX, R_R12, R_R13,
211 #ifndef TIMESTAMP_IN_REGISTER
212         R_R14,
213 #endif
214         };
215 static const uint8_t regs_volatile[] = { R_R8, R_R9, R_R10 };
216 static const uint8_t fp_saved[] = { 0 };
217 #define n_fp_saved 0U
218 static const uint8_t fp_volatile[] = { R_XMM2, R_XMM3, R_XMM4, R_XMM5 };
219 #define reg_is_saved(r) ((r) == R_BX || ((r) >= R_R12 && ((r) <= R_R15)))
221 #else
223 static const uint8_t regs_saved[] = { R_R13,
224 #ifndef TIMESTAMP_IN_REGISTER
225         R_R14,
226 #endif
227         };
228 static const uint8_t regs_volatile[] = { R_SI, R_DI, R_R8, R_R9, R_R10 };
229 static const uint8_t fp_saved[] = { 0 };
230 #define n_fp_saved 0U
231 static const uint8_t fp_volatile[] = { R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15 };
232 #define reg_is_saved(r) ((r) == R_R13 || (r) == R_R14)
233 #endif
235 static bool attr_w imm_is_8bit(int64_t imm)
237         return imm >= -0x80 && imm < 0x80;
240 static bool attr_w imm_is_32bit(int64_t attr_unused imm)
242 #ifdef ARCH_X86_32
243         return true;
244 #else
245         return imm >= -0x80000000LL && imm < 0x80000000LL;
246 #endif
249 static bool attr_w gen_load_constant(struct codegen_context *ctx, unsigned reg, uint64_t c)
251         if (OP_SIZE_NATIVE == OP_SIZE_4)
252                 c = (int32_t)c;
253         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
254         gen_one(reg);
255         gen_one(ARG_IMM);
256         gen_eight(c);
257         return true;
260 static bool attr_w gen_address(struct codegen_context *ctx, unsigned base, int64_t imm, unsigned purpose, unsigned attr_unused size)
262         ctx->offset_imm = imm;
263         ctx->offset_reg = false;
264         ctx->base_reg = base;
265         switch (purpose) {
266                 case IMM_PURPOSE_LDR_OFFSET:
267                 case IMM_PURPOSE_LDR_SX_OFFSET:
268                 case IMM_PURPOSE_STR_OFFSET:
269                 case IMM_PURPOSE_VLDR_VSTR_OFFSET:
270                 case IMM_PURPOSE_MVI_CLI_OFFSET:
271                         break;
272                 default:
273                         internal(file_line, "gen_address: invalid purpose %d", purpose);
274         }
275 #ifndef ARCH_X86_32
276         if (unlikely(!imm_is_32bit(imm)))
277                 return false;
278 #endif
279         return true;
282 static bool is_direct_const(int64_t attr_unused imm, unsigned attr_unused purpose, unsigned attr_unused size)
284 #ifdef ARCH_X86_32
285         return true;
286 #else
287         return imm_is_32bit(imm);
288 #endif
291 static bool attr_w gen_imm(struct codegen_context *ctx, int64_t imm, unsigned purpose, unsigned size)
293 #if 0
294         if (size == OP_SIZE_1 && (unlikely(imm < -0x80LL) || unlikely(imm >= 0x80LL)))
295                 internal(file_line, "invalid imm for size 1: %016llx", (long long)imm);
296         if (size == OP_SIZE_2 && (unlikely(imm < -0x8000LL) || unlikely(imm >= 0x8000LL)))
297                 internal(file_line, "invalid imm for size 2 : %016llx", (long long)imm);
298         if (size == OP_SIZE_4 && (unlikely(imm < -0x80000000LL) || unlikely(imm >= 0x80000000LL)))
299                 internal(file_line, "invalid imm for size 3: %016llx", (long long)imm);
300 #endif
301         if (is_direct_const(imm, purpose, size)) {
302                 ctx->const_imm = imm;
303                 ctx->const_reg = false;
304         } else {
305                 gen_insn(INSN_MOV, OP_SIZE_8, 0, 0);
306                 gen_one(R_CONST_IMM);
307                 gen_one(ARG_IMM);
308                 gen_eight(imm);
309                 ctx->const_reg = true;
310         }
311         return true;
314 static bool attr_w gen_entry(struct codegen_context *ctx)
316 #if defined(ARCH_X86_32)
317         gen_insn(INSN_PUSH, OP_SIZE_4, 0, 0);
318         gen_one(R_BX);
320         gen_insn(INSN_PUSH, OP_SIZE_4, 0, 0);
321         gen_one(R_BP);
323         gen_insn(INSN_PUSH, OP_SIZE_4, 0, 0);
324         gen_one(R_SI);
326         gen_insn(INSN_PUSH, OP_SIZE_4, 0, 0);
327         gen_one(R_DI);
329         gen_insn(INSN_ALU, OP_SIZE_4, ALU_SUB, 1);
330         gen_one(R_SP);
331         gen_one(R_SP);
332         gen_one(ARG_IMM);
333         gen_eight(ARG_SPACE);
335         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
336         gen_one(R_FRAME);
337         gen_one(ARG_ADDRESS_1);
338         gen_one(R_SP);
339         gen_eight(ARG_SPACE + ARG_OFFSET);
341         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
342         gen_one(ARG_ADDRESS_1);
343         gen_one(R_SP);
344         gen_eight(ARG_SPACE + ARG_OFFSET + 12);
345 #elif defined(ARCH_X86_WIN_ABI)
346         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
347         gen_one(R_BX);
349         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
350         gen_one(R_BP);
352         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
353         gen_one(R_SI);
355         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
356         gen_one(R_DI);
358         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
359         gen_one(R_R12);
361         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
362         gen_one(R_R13);
364         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
365         gen_one(R_R14);
367         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
368         gen_one(R_R15);
370         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
371         gen_one(R_ARG0);
372 #ifndef TIMESTAMP_IN_REGISTER
373         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
374         gen_one(R_ARG3);
375 #endif
376         gen_insn(INSN_ALU, OP_SIZE_8, ALU_SUB, 1);
377         gen_one(R_SP);
378         gen_one(R_SP);
379         gen_one(ARG_IMM);
380         gen_eight(ARG_SPACE);
382         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
383         gen_one(R_FRAME);
384         gen_one(R_ARG1);
386         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
387         gen_one(R_UPCALL);
388         gen_one(R_ARG2);
389 #ifdef TIMESTAMP_IN_REGISTER
390         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
391         gen_one(R_TIMESTAMP);
392         gen_one(R_ARG3);
393 #endif
394         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
395         gen_one(ARG_ADDRESS_1);
396         gen_one(R_SP);
397         gen_eight(ARG_OFFSET);
398 #else
399         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
400         gen_one(R_FRAME);
402         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
403         gen_one(R_SAVED_1);
405         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
406         gen_one(R_SAVED_2);
408         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
409         gen_one(R_R13);
411         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
412         gen_one(R_R14);
414         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
415         gen_one(R_UPCALL);
417         gen_insn(INSN_PUSH, OP_SIZE_8, 0, 0);
418         gen_one(R_ARG2);
419         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
420         gen_one(R_FRAME);
421         gen_one(R_ARG0);
423         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
424         gen_one(R_UPCALL);
425         gen_one(R_ARG1);
426 #ifdef TIMESTAMP_IN_REGISTER
427         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
428         gen_one(R_TIMESTAMP);
429         gen_one(R_ARG2);
430 #endif
431         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
432         gen_one(R_ARG3);
433 #endif
434         return true;
437 static bool attr_w gen_escape_arg(struct codegen_context *ctx, ip_t ip, uint32_t escape_label)
439 #if defined(ARCH_X86_32) || defined(ARCH_X86_64)
440         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
441         gen_one(R_DX);
442         gen_one(ARG_IMM);
443         gen_eight(ip);
444 #else
445         gen_insn(INSN_MOV, OP_SIZE_8, 0, 0);
446         gen_one(R_AX);
447         gen_one(ARG_IMM);
448         gen_eight((uint64_t)ip << 32);
449 #endif
450         gen_insn(INSN_JMP, 0, 0, 0);
451         gen_four(escape_label);
453         return true;
456 static bool attr_w gen_escape(struct codegen_context *ctx)
458 #if defined(ARCH_X86_32)
459         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
460         gen_one(R_AX);
461         gen_one(R_FRAME);
463         gen_insn(INSN_ALU, OP_SIZE_4, ALU_ADD, 1);
464         gen_one(R_SP);
465         gen_one(R_SP);
466         gen_one(ARG_IMM);
467         gen_eight(ARG_SPACE);
469         gen_insn(INSN_POP, OP_SIZE_4, 0, 0);
470         gen_one(R_DI);
472         gen_insn(INSN_POP, OP_SIZE_4, 0, 0);
473         gen_one(R_SI);
475         gen_insn(INSN_POP, OP_SIZE_4, 0, 0);
476         gen_one(R_BP);
478         gen_insn(INSN_POP, OP_SIZE_4, 0, 0);
479         gen_one(R_BX);
481         gen_insn(INSN_RET, 0, 0, 0);
482 #elif defined(ARCH_X86_WIN_ABI)
483         gen_insn(INSN_ALU, OP_SIZE_8, ALU_ADD, 1);
484         gen_one(R_SP);
485         gen_one(R_SP);
486         gen_one(ARG_IMM);
487 #if defined(TIMESTAMP_IN_REGISTER)
488         gen_eight(ARG_SPACE);
489 #else
490         gen_eight(ARG_SPACE + 8);
491 #endif
492         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
493         gen_one(R_AX);
495         gen_insn(INSN_MOV, OP_SIZE_8, 0, 0);
496         gen_one(ARG_ADDRESS_1);
497         gen_one(R_AX);
498         gen_eight(0);
499         gen_one(R_FRAME);
501         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
502         gen_one(ARG_ADDRESS_1);
503         gen_one(R_AX);
504         gen_eight(8);
505         gen_one(R_DX);
507         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
508         gen_one(R_R15);
510         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
511         gen_one(R_R14);
513         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
514         gen_one(R_R13);
516         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
517         gen_one(R_R12);
519         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
520         gen_one(R_DI);
522         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
523         gen_one(R_SI);
525         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
526         gen_one(R_BP);
528         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
529         gen_one(R_BX);
531         gen_insn(INSN_RET, 0, 0, 0);
532 #else
533 #if defined(ARCH_X86_X32)
534         gen_insn(INSN_ALU, OP_SIZE_8, ALU_ADD, 1);
535         gen_one(R_AX);
536         gen_one(R_AX);
537         gen_one(R_FRAME);
538 #else
539         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
540         gen_one(R_AX);
541         gen_one(R_FRAME);
542 #endif
543         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
544         gen_one(R_CX);
546         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
547         gen_one(R_UPCALL);
549         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
550         gen_one(R_R14);
552         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
553         gen_one(R_R13);
555         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
556         gen_one(R_SAVED_2);
558         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
559         gen_one(R_SAVED_1);
561         gen_insn(INSN_POP, OP_SIZE_8, 0, 0);
562         gen_one(R_FRAME);
564         gen_insn(INSN_RET, 0, 0, 0);
565 #endif
566         return true;
569 static bool attr_w gen_upcall_argument(struct codegen_context attr_unused *ctx, unsigned attr_unused arg)
571 #if defined(ARCH_X86_32)
572         ajla_assert_lo(arg * 4 < ARG_SPACE, (file_line, "gen_upcall_argument: argument %u", arg));
573         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
574         gen_one(ARG_ADDRESS_1);
575         gen_one(R_SP);
576         gen_eight(arg * 4);
577         gen_one(R_ARG0);
578 #endif
579         return true;
582 static bool attr_w gen_upcall(struct codegen_context *ctx, unsigned offset, unsigned n_args)
584 #if defined(ARCH_X86_32)
585         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
586         gen_one(R_AX);
587         gen_one(ARG_ADDRESS_1);
588         gen_one(R_SP);
589         gen_eight(ARG_SPACE + ARG_OFFSET + 4);
591         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_4, 0, 0);
592         gen_one(ARG_ADDRESS_1);
593         gen_one(R_AX);
594         gen_eight(offset);
595 #elif defined(ARCH_X86_X32)
596         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
597         gen_one(R_AX);
598         gen_one(ARG_ADDRESS_1);
599         gen_one(R_UPCALL);
600         gen_eight(offset);
602         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_8, 0, 0);
603         gen_one(R_AX);
604 #else
605         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_8, 0, 0);
606         gen_one(ARG_ADDRESS_1);
607         gen_one(R_UPCALL);
608         gen_eight(offset);
609 #endif
610         g(gen_upcall_end(ctx, n_args));
612         return true;
615 static bool attr_w gen_timestamp_test(struct codegen_context *ctx, uint32_t escape_label)
617 #if defined(ARCH_X86_32)
618         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
619         gen_one(R_AX);
620         gen_one(ARG_ADDRESS_1);
621         gen_one(R_SP);
622         gen_eight(ARG_SPACE + ARG_OFFSET + 4);
624         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
625         gen_one(R_DX);
626         gen_one(ARG_ADDRESS_1);
627         gen_one(R_SP);
628         gen_eight(ARG_SPACE + ARG_OFFSET + 8);
630         gen_insn(INSN_CMP, OP_SIZE_4, 0, 1);
631         gen_one(R_DX);
632         gen_one(ARG_ADDRESS_1);
633         gen_one(R_AX);
634         gen_eight(offsetof(struct cg_upcall_vector_s, ts));
635 #elif defined(TIMESTAMP_IN_REGISTER)
636         gen_insn(INSN_CMP, OP_SIZE_4, 0, 1);
637         gen_one(R_TIMESTAMP);
638         gen_one(ARG_ADDRESS_1);
639         gen_one(R_UPCALL);
640         gen_eight(offsetof(struct cg_upcall_vector_s, ts));
641 #else
642         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
643         gen_one(R_AX);
644         gen_one(ARG_ADDRESS_1);
645         gen_one(R_SP);
646 #if defined(ARCH_X86_WIN_ABI)
647         gen_eight(ARG_SPACE);
648 #else
649         gen_eight(0);
650 #endif
651         gen_insn(INSN_CMP, OP_SIZE_4, 0, 1);
652         gen_one(R_AX);
653         gen_one(ARG_ADDRESS_1);
654         gen_one(R_UPCALL);
655         gen_eight(offsetof(struct cg_upcall_vector_s, ts));
656 #endif
657         gen_insn(INSN_JMP_COND, OP_SIZE_4, COND_NE, 0);
658         gen_four(escape_label);
660         return true;