codegen: introduce cg-spill.inc
[ajla.git] / c1-riscv.inc
blob35780fcbcb051e5fded6f56ba469cea5e38e90f0
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                       JMP_EXTRA_LONG
24 #define UNALIGNED_TRAP                  (!cpu_test_feature(CPU_FEATURE_unaligned))
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                    1
42 #define ARCH_HAS_DIV                    1
43 #define ARCH_HAS_ANDN                   cpu_test_feature(CPU_FEATURE_zbb)
44 #define ARCH_HAS_SHIFTED_ADD(bits)      ((bits) <= 3 && cpu_test_feature(CPU_FEATURE_zba))
45 #define ARCH_HAS_BTX(btx, size, cnst)   (((size) == OP_SIZE_8 || (cnst)) && cpu_test_feature(CPU_FEATURE_zbs))
46 #define ARCH_SHIFT_SIZE                 OP_SIZE_4
47 #define ARCH_NEEDS_BARRIER              0
49 #define i_size(size)                    OP_SIZE_NATIVE
50 #define i_size_rot(size)                maximum(size, OP_SIZE_4)
51 #define i_size_cmp(size)                OP_SIZE_NATIVE
53 #define R_ZERO          0x00
54 #define R_RA            0x01
55 #define R_SP            0x02
56 #define R_GP            0x03
57 #define R_TP            0x04
58 #define R_T0            0x05
59 #define R_T1            0x06
60 #define R_T2            0x07
61 #define R_S0            0x08
62 #define R_S1            0x09
63 #define R_A0            0x0a
64 #define R_A1            0x0b
65 #define R_A2            0x0c
66 #define R_A3            0x0d
67 #define R_A4            0x0e
68 #define R_A5            0x0f
69 #define R_A6            0x10
70 #define R_A7            0x11
71 #define R_S2            0x12
72 #define R_S3            0x13
73 #define R_S4            0x14
74 #define R_S5            0x15
75 #define R_S6            0x16
76 #define R_S7            0x17
77 #define R_S8            0x18
78 #define R_S9            0x19
79 #define R_S10           0x1a
80 #define R_S11           0x1b
81 #define R_T3            0x1c
82 #define R_T4            0x1d
83 #define R_T5            0x1e
84 #define R_T6            0x1f
86 #define R_FT0           0x20
87 #define R_FT1           0x21
88 #define R_FT2           0x22
89 #define R_FT3           0x23
90 #define R_FT4           0x24
91 #define R_FT5           0x25
92 #define R_FT6           0x26
93 #define R_FT7           0x27
94 #define R_FS0           0x28
95 #define R_FS1           0x29
96 #define R_FA0           0x2a
97 #define R_FA1           0x2b
98 #define R_FA2           0x2c
99 #define R_FA3           0x2d
100 #define R_FA4           0x2e
101 #define R_FA5           0x2f
102 #define R_FA6           0x30
103 #define R_FA7           0x31
104 #define R_FS2           0x32
105 #define R_FS3           0x33
106 #define R_FS4           0x34
107 #define R_FS5           0x35
108 #define R_FS6           0x36
109 #define R_FS7           0x37
110 #define R_FS8           0x38
111 #define R_FS9           0x39
112 #define R_FS10          0x3a
113 #define R_FS11          0x3b
114 #define R_FT8           0x3c
115 #define R_FT9           0x3d
116 #define R_FT10          0x3e
117 #define R_FT11          0x3f
119 #define R_FRAME         R_S0
120 #define R_UPCALL        R_S1
121 #define R_TIMESTAMP     R_S2
123 #define R_SCRATCH_1     R_A0
124 #define R_SCRATCH_2     R_A1
125 #define R_SCRATCH_3     R_A2
126 #define R_SCRATCH_4     R_A3
127 #define R_SCRATCH_NA_1  R_A4
128 #define R_SCRATCH_NA_2  R_A5
129 #ifdef HAVE_BITWISE_FRAME
130 #define R_SCRATCH_NA_3  R_A6
131 #endif
133 #define R_SAVED_1       R_S3
134 #define R_SAVED_2       R_S4
136 #define R_ARG0          R_A0
137 #define R_ARG1          R_A1
138 #define R_ARG2          R_A2
139 #define R_ARG3          R_A3
140 #define R_RET0          R_A0
141 #define R_RET1          R_A1
143 #define R_OFFSET_IMM    R_T0
144 #define R_CONST_IMM     R_T1
145 #define R_CONST_HELPER  R_T2
146 #define R_CMP_RESULT    R_T3
148 #define FR_SCRATCH_1    R_FT0
149 #define FR_SCRATCH_2    R_FT1
151 #define SUPPORTED_FP    0x6
153 #define FRAME_SIZE      0x70
155 static bool reg_is_fp(unsigned reg)
157         return reg >= 0x20 && reg < 0x40;
160 static const uint8_t regs_saved[] = { R_S5, R_S6, R_S7, R_S8, R_S9, R_S10, R_S11 };
161 static const uint8_t regs_volatile[] = { R_RA,
162 #ifndef HAVE_BITWISE_FRAME
163         R_A6,
164 #endif
165         R_A7, R_T4, R_T5, R_T6 };
166 static const uint8_t fp_saved[] = { 0 };
167 #define n_fp_saved 0U
168 static const uint8_t fp_volatile[] = { R_FT2, R_FT3, R_FT4, R_FT5, R_FT6, R_FT7, R_FA0, R_FA1, R_FA2, R_FA3, R_FA4, R_FA5, R_FA6, R_FA7, R_FT8, R_FT9, R_FT10, R_FT11 };
169 #define reg_is_saved(r) (((r) >= R_S0 && (r) <= R_S1) || ((r) >= R_S2 && (r) <= R_S11) || ((r) >= R_FS0 && (r) <= R_FS1) || ((r) >= R_FS2 && (r) <= R_FS11))
171 static const struct {
172         uint32_t l;
173         uint16_t s;
174 } riscv_compress[] = {
175 #include "riscv-c.inc"
178 static bool attr_w gen_load_constant(struct codegen_context *ctx, unsigned reg, uint64_t c)
180         unsigned r = R_ZERO;
181         int32_t c1, c2, c3, c4;
183         c1 = c & 0xfffUL;
184         if (c1 & 0x800)
185                 c1 |= -0x800;
186         if (c1 < 0)
187                 c += 0x1000UL;
189         c2 = (c >> 12) & 0xfffffUL;
190         if (c2 & 0x80000)
191                 c2 |= -0x80000;
192         if (c2 < 0)
193                 c += 0x100000000UL;
195         c3 = (c >> 32) & 0xfffUL;
196         if (c3 & 0x800)
197                 c3 |= -0x800;
198         if (c3 < 0)
199                 c += 0x100000000000UL;
201         c4 = c >> 44;
202         if (c4 & 0x80000)
203                 c4 |= -0x80000;
205         if (c4) {
206                 gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
207                 gen_one(reg);
208                 gen_one(ARG_IMM);
209                 gen_eight((uint64_t)c4 << 12);
210                 r = reg;
211         }
212         if (c3) {
213                 gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_ADD, 0);
214                 gen_one(reg);
215                 gen_one(r);
216                 gen_one(ARG_IMM);
217                 gen_eight(c3);
218                 r = reg;
219         }
220         if (r != R_ZERO) {
221                 gen_insn(INSN_ROT, OP_SIZE_NATIVE, ROT_SHL, 0);
222                 gen_one(r);
223                 gen_one(r);
224                 gen_one(ARG_IMM);
225                 gen_eight(32);
226         }
227         if (c2) {
228                 if (r != R_ZERO) {
229                         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
230                         gen_one(R_CONST_HELPER);
231                         gen_one(ARG_IMM);
232                         gen_eight((uint64_t)c2 << 12);
234                         gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_ADD, 0);
235                         gen_one(r);
236                         gen_one(r);
237                         gen_one(R_CONST_HELPER);
238                 } else {
239                         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
240                         gen_one(reg);
241                         gen_one(ARG_IMM);
242                         gen_eight((uint64_t)c2 << 12);
243                         r = reg;
244                 }
245         }
246         if (c1 || r == R_ZERO) {
247                 gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_ADD, 0);
248                 gen_one(reg);
249                 gen_one(r);
250                 gen_one(ARG_IMM);
251                 gen_eight(c1);
252         }
253         return true;
256 static bool attr_w gen_address(struct codegen_context *ctx, unsigned base, int64_t imm, unsigned purpose, unsigned size)
258         ctx->base_reg = base;
259         ctx->offset_imm = imm;
260         ctx->offset_reg = false;
261         switch (purpose) {
262                 case IMM_PURPOSE_LDR_OFFSET:
263                 case IMM_PURPOSE_LDR_SX_OFFSET:
264                 case IMM_PURPOSE_STR_OFFSET:
265                 case IMM_PURPOSE_VLDR_VSTR_OFFSET:
266                 case IMM_PURPOSE_MVI_CLI_OFFSET:
267                         if (likely(imm >= -0x800) && likely(imm < 0x800))
268                                 return true;
269                         break;
270                 default:
271                         internal(file_line, "gen_address: invalid purpose %u (imm %"PRIxMAX", size %u)", purpose, (uintmax_t)imm, size);
272         }
273         g(gen_load_constant(ctx, R_OFFSET_IMM, imm));
274         gen_insn(INSN_ALU, OP_SIZE_ADDRESS, ALU_ADD, 0);
275         gen_one(R_OFFSET_IMM);
276         gen_one(R_OFFSET_IMM);
277         gen_one(base);
278         ctx->base_reg = R_OFFSET_IMM;
279         ctx->offset_imm = 0;
280         return true;
283 static bool is_direct_const(int64_t imm, unsigned purpose, unsigned size)
285         switch (purpose) {
286                 case IMM_PURPOSE_STORE_VALUE:
287                         if (!imm)
288                                 return true;
289                         break;
290                 case IMM_PURPOSE_ADD:
291                 case IMM_PURPOSE_AND:
292                 case IMM_PURPOSE_OR:
293                 case IMM_PURPOSE_XOR:
294                 case IMM_PURPOSE_TEST:
295                 case IMM_PURPOSE_CMP:
296                 case IMM_PURPOSE_CMP_LOGICAL:
297                         if (likely(imm >= -0x800) && likely(imm < 0x800))
298                                 return true;
299                         break;
300                 case IMM_PURPOSE_SUB:
301                         if (likely(imm > -0x800) && likely(imm <= 0x800))
302                                 return true;
303                         break;
304                 case IMM_PURPOSE_ANDN:
305                         break;
306                 case IMM_PURPOSE_JMP_2REGS:
307                         break;
308                 case IMM_PURPOSE_MUL:
309                         break;
310                 case IMM_PURPOSE_BITWISE:
311                         return true;
312                 default:
313                         internal(file_line, "is_direct_const: invalid purpose %u (imm %"PRIxMAX", size %u)", purpose, (uintmax_t)imm, size);
314         }
315         return false;
318 static bool attr_w gen_imm(struct codegen_context *ctx, int64_t imm, unsigned purpose, unsigned size)
320         if (is_direct_const(imm, purpose, size)) {
321                 ctx->const_imm = imm;
322                 ctx->const_reg = false;
323         } else {
324                 g(gen_load_constant(ctx, R_CONST_IMM, imm));
325                 ctx->const_reg = true;
326         }
327         return true;
330 static bool attr_w gen_entry(struct codegen_context *ctx)
332         g(gen_imm(ctx, -FRAME_SIZE, IMM_PURPOSE_ADD, OP_SIZE_NATIVE));
333         gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_ADD, 0);
334         gen_one(R_SP);
335         gen_one(R_SP);
336         gen_imm_offset();
338         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x08, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
339         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
340         gen_address_offset();
341         gen_one(R_RA);
343         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x10, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
344         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
345         gen_address_offset();
346         gen_one(R_S0);
348         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x18, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
349         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
350         gen_address_offset();
351         gen_one(R_S1);
353         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x20, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
354         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
355         gen_address_offset();
356         gen_one(R_S2);
358         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x28, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
359         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
360         gen_address_offset();
361         gen_one(R_S3);
363         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x30, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
364         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
365         gen_address_offset();
366         gen_one(R_S4);
368         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x38, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
369         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
370         gen_address_offset();
371         gen_one(R_S5);
373         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x40, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
374         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
375         gen_address_offset();
376         gen_one(R_S6);
378         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x48, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
379         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
380         gen_address_offset();
381         gen_one(R_S7);
383         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x50, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
384         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
385         gen_address_offset();
386         gen_one(R_S8);
388         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x58, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
389         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
390         gen_address_offset();
391         gen_one(R_S9);
393         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x60, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
394         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
395         gen_address_offset();
396         gen_one(R_S10);
398         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x68, IMM_PURPOSE_STR_OFFSET, OP_SIZE_NATIVE));
399         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
400         gen_address_offset();
401         gen_one(R_S11);
403         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
404         gen_one(R_FRAME);
405         gen_one(R_ARG0);
407         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
408         gen_one(R_UPCALL);
409         gen_one(R_ARG1);
411         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
412         gen_one(R_TIMESTAMP);
413         gen_one(R_ARG2);
415         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
416         gen_one(R_ARG3);
418         return true;
421 static bool attr_w gen_escape_arg(struct codegen_context *ctx, ip_t ip, uint32_t escape_label)
423         g(gen_load_constant(ctx, R_RET1, (int32_t)ip));
425         gen_insn(INSN_JMP, 0, 0, 0);
426         gen_four(escape_label);
428         return true;
431 static bool attr_w gen_escape(struct codegen_context *ctx)
433         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
434         gen_one(R_RET0);
435         gen_one(R_FRAME);
437         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x08, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
438         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
439         gen_one(R_RA);
440         gen_address_offset();
442         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x10, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
443         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
444         gen_one(R_S0);
445         gen_address_offset();
447         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x18, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
448         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
449         gen_one(R_S1);
450         gen_address_offset();
452         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x20, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
453         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
454         gen_one(R_S2);
455         gen_address_offset();
457         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x28, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
458         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
459         gen_one(R_S3);
460         gen_address_offset();
462         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x30, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
463         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
464         gen_one(R_S4);
465         gen_address_offset();
467         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x38, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
468         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
469         gen_one(R_S5);
470         gen_address_offset();
472         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x40, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
473         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
474         gen_one(R_S6);
475         gen_address_offset();
477         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x48, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
478         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
479         gen_one(R_S7);
480         gen_address_offset();
482         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x50, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
483         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
484         gen_one(R_S8);
485         gen_address_offset();
487         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x58, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
488         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
489         gen_one(R_S9);
490         gen_address_offset();
492         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x60, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
493         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
494         gen_one(R_S10);
495         gen_address_offset();
497         g(gen_address(ctx, R_SP, FRAME_SIZE - 0x68, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_NATIVE));
498         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
499         gen_one(R_S11);
500         gen_address_offset();
502         g(gen_imm(ctx, FRAME_SIZE, IMM_PURPOSE_ADD, OP_SIZE_NATIVE));
503         gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_ADD, 0);
504         gen_one(R_SP);
505         gen_one(R_SP);
506         gen_imm_offset();
508         gen_insn(INSN_RET, 0, 0, 0);
510         return true;
513 static bool attr_w gen_upcall_argument(struct codegen_context attr_unused *ctx, unsigned attr_unused arg)
515         return true;
518 static bool attr_w gen_upcall(struct codegen_context *ctx, unsigned offset, unsigned n_args)
520         g(gen_address(ctx, R_UPCALL, offset, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_ADDRESS));
521         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
522         gen_one(R_SCRATCH_NA_1);
523         gen_address_offset();
525         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_ADDRESS, 0, 0);
526         gen_one(R_SCRATCH_NA_1);
528         g(gen_upcall_end(ctx, n_args));
530         return true;
533 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);
535 static bool attr_w gen_timestamp_test(struct codegen_context *ctx, uint32_t escape_label)
537         g(gen_address(ctx, R_UPCALL, offsetof(struct cg_upcall_vector_s, ts), IMM_PURPOSE_LDR_SX_OFFSET, OP_SIZE_4));
538         gen_insn(INSN_MOVSX, OP_SIZE_4, 0, 0);
539         gen_one(R_SCRATCH_1);
540         gen_address_offset();
542         g(gen_cmp_test_jmp(ctx, INSN_CMP, OP_SIZE_NATIVE, R_SCRATCH_1, R_TIMESTAMP, COND_NE, escape_label));
544         return true;