codegen: introduce gen_mov and use it instead of explicit coding
[ajla.git] / c1-power.inc
blob7deebe4ff912b0bd1532e683ba5f8c331fe98398
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 _CALL_AIXDESC
20 #define AIX_CALL
21 #endif
23 #if !defined(ARCH_POWER64)
25 #define OP_SIZE_NATIVE                  OP_SIZE_4
26 #define OP_SIZE_ADDRESS                 OP_SIZE_4
27 #ifdef AIX_CALL
28 #define FRAME_SIZE                      128
29 #define REGS_OFFSET                     56
30 #define LR_OFFSET                       (FRAME_SIZE + 8)
31 #else
32 #define FRAME_SIZE                      80
33 #define REGS_OFFSET                     8
34 #define LR_OFFSET                       (FRAME_SIZE + 4)
35 #endif
37 #else
39 #define OP_SIZE_NATIVE                  OP_SIZE_8
40 #define OP_SIZE_ADDRESS                 OP_SIZE_8
41 #ifdef AIX_CALL
42 #define FRAME_SIZE                      256
43 #define REGS_OFFSET                     112
44 #define LR_OFFSET                       (FRAME_SIZE + 16)
45 #define STRUCT_RET_OFFSET               304
46 #else
47 #define FRAME_SIZE                      176
48 #define REGS_OFFSET                     32
49 #define LR_OFFSET                       (FRAME_SIZE + 16)
50 #endif
52 #endif
54 #define JMP_LIMIT                       JMP_SHORT
56 #define UNALIGNED_TRAP                  0
58 #define ALU_WRITES_FLAGS(alu, im)       (!(im) ?                        \
59                                                 ((alu) == ALU_SUB && !cpu_test_feature(CPU_FEATURE_ppc) ? 2 : (alu) == ALU_ADC || (alu) == ALU_SBB ? 2 : 0) :\
60                                                 ((alu) == ALU_AND ? 1 : 0)\
61                                         )
62 #define ALU1_WRITES_FLAGS(alu)          0
63 #define ROT_WRITES_FLAGS(alu)           0
64 #define COND_IS_LOGICAL(cond)           ((cond) == COND_B || (cond) == COND_AE || (cond) == COND_BE || (cond) == COND_A)
66 #define ARCH_PARTIAL_ALU(size)          0
67 #define ARCH_IS_3ADDRESS                1
68 #define ARCH_HAS_FLAGS                  1
69 #define ARCH_PREFERS_SX(size)           0
70 #define ARCH_HAS_BWX                    1
71 #define ARCH_HAS_MUL                    1
72 #define ARCH_HAS_DIV                    cpu_test_feature(CPU_FEATURE_ppc)
73 #define ARCH_HAS_ANDN                   1
74 #define ARCH_HAS_SHIFTED_ADD(bits)      0
75 #define ARCH_HAS_BTX(btx, size, cnst)   0
76 #define ARCH_SHIFT_SIZE                 OP_SIZE_16
77 #define ARCH_NEEDS_BARRIER              0
79 #define i_size(size)                    OP_SIZE_NATIVE
80 #define i_size_rot(size)                maximum(size, OP_SIZE_4)
82 #define R_0                             0x00
83 #define R_1                             0x01
84 #define R_2                             0x02
85 #define R_3                             0x03
86 #define R_4                             0x04
87 #define R_5                             0x05
88 #define R_6                             0x06
89 #define R_7                             0x07
90 #define R_8                             0x08
91 #define R_9                             0x09
92 #define R_10                            0x0a
93 #define R_11                            0x0b
94 #define R_12                            0x0c
95 #define R_13                            0x0d
96 #define R_14                            0x0e
97 #define R_15                            0x0f
98 #define R_16                            0x10
99 #define R_17                            0x11
100 #define R_18                            0x12
101 #define R_19                            0x13
102 #define R_20                            0x14
103 #define R_21                            0x15
104 #define R_22                            0x16
105 #define R_23                            0x17
106 #define R_24                            0x18
107 #define R_25                            0x19
108 #define R_26                            0x1a
109 #define R_27                            0x1b
110 #define R_28                            0x1c
111 #define R_29                            0x1d
112 #define R_30                            0x1e
113 #define R_31                            0x1f
115 #define R_LR                            0x20
116 #define R_CTR                           0x21
118 #define R_F0                            0x40
119 #define R_F1                            0x41
120 #define R_F2                            0x42
121 #define R_F3                            0x43
122 #define R_F4                            0x44
123 #define R_F5                            0x45
124 #define R_F6                            0x46
125 #define R_F7                            0x47
126 #define R_F8                            0x48
127 #define R_F9                            0x49
128 #define R_F10                           0x4a
129 #define R_F11                           0x4b
130 #define R_F12                           0x4c
131 #define R_F13                           0x4d
132 #define R_F14                           0x4e
133 #define R_F15                           0x4f
134 #define R_F16                           0x50
135 #define R_F17                           0x51
136 #define R_F18                           0x52
137 #define R_F19                           0x53
138 #define R_F20                           0x54
139 #define R_F21                           0x55
140 #define R_F22                           0x56
141 #define R_F23                           0x57
142 #define R_F24                           0x58
143 #define R_F25                           0x59
144 #define R_F26                           0x5a
145 #define R_F27                           0x5b
146 #define R_F28                           0x5c
147 #define R_F29                           0x5d
148 #define R_F30                           0x5e
149 #define R_F31                           0x5f
150 #define R_VS32                          0x60
151 #define R_VS33                          0x61
152 #define R_VS34                          0x62
153 #define R_VS35                          0x63
154 #define R_VS36                          0x64
155 #define R_VS37                          0x65
156 #define R_VS38                          0x66
157 #define R_VS39                          0x67
158 #define R_VS40                          0x68
159 #define R_VS41                          0x69
160 #define R_VS42                          0x6a
161 #define R_VS43                          0x6b
162 #define R_VS44                          0x6c
163 #define R_VS45                          0x6d
164 #define R_VS46                          0x6e
165 #define R_VS47                          0x6f
166 #define R_VS48                          0x70
167 #define R_VS49                          0x71
168 #define R_VS50                          0x72
169 #define R_VS51                          0x73
170 #define R_VS52                          0x74
171 #define R_VS53                          0x75
172 #define R_VS54                          0x76
173 #define R_VS55                          0x77
174 #define R_VS56                          0x78
175 #define R_VS57                          0x79
176 #define R_VS58                          0x7a
177 #define R_VS59                          0x7b
178 #define R_VS60                          0x7c
179 #define R_VS61                          0x7d
180 #define R_VS62                          0x7e
181 #define R_VS63                          0x7f
183 #define R_CG_SCRATCH                    R_0
185 #define R_SP                            R_1
187 #define R_SCRATCH_1                     R_3
188 #define R_SCRATCH_2                     R_4
189 #define R_SCRATCH_3                     R_5
190 #define R_SCRATCH_4                     R_SAVED_2
192 #define R_SCRATCH_NA_1                  R_7
193 #define R_SCRATCH_NA_2                  R_8
194 #define R_SCRATCH_NA_3                  R_9
196 #define R_FRAME                         R_31
197 #define R_UPCALL                        R_30
198 #define R_TIMESTAMP                     R_29
200 #define R_SAVED_1                       R_28
201 #define R_SAVED_2                       R_27
202 #define R_ZERO                          R_26
204 #define R_LOWEST_SAVED                  R_14
206 #define R_ARG0                          R_3
207 #define R_ARG1                          R_4
208 #define R_ARG2                          R_5
209 #define R_ARG3                          R_6
210 #define R_ARG4                          R_7
211 #define R_RET0                          R_3
212 #define R_RET1                          R_4
214 #define R_OFFSET_IMM                    R_10
215 #define R_CONST_IMM                     R_11
217 #define FR_SCRATCH_1                    (real_type == 4 ? R_VS32 : R_F0)
218 #define FR_SCRATCH_2                    (real_type == 4 ? R_VS33 : R_F1)
219 #define FR_SCRATCH_3                    (real_type == 4 ? R_VS34 : R_F2)
221 #define SUPPORTED_FP                    (cpu_test_feature(CPU_FEATURE_ppc) * 0x2 + 0x4 + cpu_test_feature(CPU_FEATURE_v30) * 0x10)
223 static bool reg_is_fp(unsigned reg)
225         return reg >= 0x40 && reg < 0x80;
228 static bool reg_is_vs(unsigned reg)
230         return reg >= 0x60 && reg < 0x80;
233 static const uint8_t regs_saved[] = { R_14, R_15, R_16, R_17, R_18, R_19, R_20, R_21, R_22, R_23, R_24, R_25 };
234 static const uint8_t regs_volatile[] = { R_6, R_12 };
235 static const uint8_t fp_saved[] = { 0 };
236 #define n_fp_saved 0U
237 static const uint8_t fp_volatile[] = { 0 };
238 #define n_fp_volatile 0U
239 #define reg_is_saved(r) ((r) >= R_14 && (r) <= R_31)
241 static bool attr_w gen_load_constant(struct codegen_context *ctx, unsigned reg, uint64_t c)
243         unsigned xreg = R_ZERO;
244         if (OP_SIZE_NATIVE == OP_SIZE_4)
245                 c = (int32_t)c;
246         if (c == (uint64_t)(int32_t)c) {
247                 if (c == (uint64_t)(int16_t)c) {
248                         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
249                         gen_one(reg);
250                         gen_one(ARG_IMM);
251                         gen_eight((int16_t)c);
252                         return true;
253                 }
254                 if (c & 0xffffffffffff0000ULL) {
255                         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
256                         gen_one(reg);
257                         gen_one(ARG_IMM);
258                         gen_eight(c & 0xffffffffffff0000ULL);
259                         xreg = reg;
260                 }
261         } else {
262                 if (c >> 48) {
263                         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
264                         gen_one(reg);
265                         gen_one(ARG_IMM);
266                         gen_eight((int32_t)((c >> 32) & 0xffff0000U));
267                         xreg = reg;
268                 }
269                 if (c & 0x0000ffff00000000ULL) {
270                         gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_OR, 0);
271                         gen_one(reg);
272                         gen_one(xreg);
273                         gen_one(ARG_IMM);
274                         gen_eight((uint16_t)(c >> 32));
275                         xreg = reg;
276                 }
277                 if (xreg != R_ZERO) {
278                         gen_insn(INSN_ROT, OP_SIZE_NATIVE, ROT_SHL, 0);
279                         gen_one(reg);
280                         gen_one(reg);
281                         gen_one(ARG_IMM);
282                         gen_eight(32);
283                 }
284                 if (c & 0xffff0000U) {
285                         gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_OR, 0);
286                         gen_one(reg);
287                         gen_one(xreg);
288                         gen_one(ARG_IMM);
289                         gen_eight(c & 0xffff0000U);
290                         xreg = reg;
291                 }
292         }
293         if (c & 0xffffU) {
294                 gen_insn(INSN_ALU, OP_SIZE_NATIVE, ALU_OR, 0);
295                 gen_one(reg);
296                 gen_one(xreg);
297                 gen_one(ARG_IMM);
298                 gen_eight(c & 0xffffU);
299                 xreg = reg;
300         }
301         if (xreg == R_ZERO) {
302                 gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
303                 gen_one(reg);
304                 gen_one(ARG_IMM);
305                 gen_eight(0);
306         }
307         return true;
310 static bool attr_w gen_address(struct codegen_context *ctx, unsigned base, int64_t imm, unsigned purpose, unsigned size)
312         ctx->base_reg = base;
313         ctx->offset_imm = imm;
314         ctx->offset_reg = false;
315         switch (purpose) {
316                 case IMM_PURPOSE_VLDR_VSTR_OFFSET:
317                         if (size >= OP_SIZE_16 && imm & 15)
318                                 break;
319                         /*-fallthrough*/
320                 case IMM_PURPOSE_LDR_SX_OFFSET:
321                         if (size >= OP_SIZE_4 && imm & 3)
322                                 break;
323                         /*-fallthrough*/
324                 case IMM_PURPOSE_LDR_OFFSET:
325                 case IMM_PURPOSE_STR_OFFSET:
326                         if (size >= OP_SIZE_8 && imm & 3)
327                                 break;
328                         /*-fallthrough*/
329                 case IMM_PURPOSE_MVI_CLI_OFFSET:
330                         if (likely(imm >= -0x8000) && likely(imm < 0x8000))
331                                 return true;
332                         break;
333                 default:
334                         internal(file_line, "gen_address: invalid purpose %u (imm %"PRIxMAX", size %u)", purpose, (uintmax_t)imm, size);
335         }
336         g(gen_load_constant(ctx, R_OFFSET_IMM, imm));
337         ctx->offset_reg = true;
338         return true;
341 static bool is_direct_const(int64_t imm, unsigned purpose, unsigned size)
343         switch (purpose) {
344                 case IMM_PURPOSE_STORE_VALUE:
345                 case IMM_PURPOSE_CMOV:
346                         if (!imm)
347                                 return true;
348                         break;
349                 case IMM_PURPOSE_ANDN:
350                         break;
351                 case IMM_PURPOSE_ADD:
352                 case IMM_PURPOSE_CMP:
353                         if (likely(imm >= -0x8000) && likely(imm < 0x8000))
354                                 return true;
355                         if (imm & 0xffff)
356                                 break;
357                         if (likely(imm >= -0x80000000L) && likely(imm < 0x80000000L))
358                                 return true;
359                         break;
360                 case IMM_PURPOSE_SUB:
361                         if (likely(imm > -0x8000) && likely(imm <= 0x8000))
362                                 return true;
363                         if (imm & 0xffff)
364                                 break;
365                         if (likely(imm > -0x80000000L) && likely(imm <= 0x80000000L))
366                                 return true;
367                         break;
368                 case IMM_PURPOSE_CMP_LOGICAL:
369                 case IMM_PURPOSE_AND:
370                 case IMM_PURPOSE_OR:
371                 case IMM_PURPOSE_XOR:
372                 case IMM_PURPOSE_TEST:
373                         if (likely(imm >= 0) && likely(imm < 0x10000))
374                                 return true;
375                         if (imm & 0xffff)
376                                 break;
377                         if (likely(imm >= 0LL) && likely(imm < 0x100000000LL))
378                                 return true;
379                         break;
380                 case IMM_PURPOSE_MUL:
381                         if (size != OP_SIZE_4)
382                                 break;
383                         if (likely(imm >= -0x8000) && likely(imm < 0x8000))
384                                 return true;
385                         break;
386                 default:
387                         internal(file_line, "is_direct_const: invalid purpose %u (imm %"PRIxMAX", size %u)", purpose, (uintmax_t)imm, size);
388         }
389         return false;
392 static bool attr_w gen_imm(struct codegen_context *ctx, int64_t imm, unsigned purpose, unsigned size)
394         if (is_direct_const(imm, purpose, size)) {
395                 ctx->const_imm = imm;
396                 ctx->const_reg = false;
397         } else {
398                 g(gen_load_constant(ctx, R_CONST_IMM, imm));
399                 ctx->const_reg = true;
400         }
401         return true;
404 static bool attr_w gen_entry(struct codegen_context *ctx)
406         int i, offs;
408         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
409         gen_one(ARG_ADDRESS_1_PRE_I);
410         gen_one(R_SP);
411         gen_eight(-FRAME_SIZE);
412         gen_one(R_SP);
414         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
415         gen_one(R_SCRATCH_NA_3);
416         gen_one(R_LR);
418         for (i = R_LOWEST_SAVED, offs = REGS_OFFSET; i <= R_31; i++, offs += 1 << OP_SIZE_ADDRESS) {
419                 gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
420                 gen_one(ARG_ADDRESS_1);
421                 gen_one(R_SP);
422                 gen_eight(offs);
423                 gen_one(i);
424         }
426         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
427         gen_one(ARG_ADDRESS_1);
428         gen_one(R_SP);
429         gen_eight(LR_OFFSET);
430         gen_one(R_SCRATCH_NA_3);
432         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
433         gen_one(R_ZERO);
434         gen_one(ARG_IMM);
435         gen_eight(0);
437 #if !defined(STRUCT_RET_OFFSET)
438         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
439         gen_one(R_FRAME);
440         gen_one(R_ARG0);
442         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
443         gen_one(R_UPCALL);
444         gen_one(R_ARG1);
446         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
447         gen_one(R_TIMESTAMP);
448         gen_one(R_ARG2);
450         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
451         gen_one(R_ARG3);
452 #else
453         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
454         gen_one(ARG_ADDRESS_1);
455         gen_one(R_SP);
456         gen_eight(STRUCT_RET_OFFSET);
457         gen_one(R_ARG0);
459         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
460         gen_one(R_FRAME);
461         gen_one(R_ARG1);
463         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
464         gen_one(R_UPCALL);
465         gen_one(R_ARG2);
467         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
468         gen_one(R_TIMESTAMP);
469         gen_one(R_ARG3);
471         gen_insn(INSN_JMP_INDIRECT, 0, 0, 0);
472         gen_one(R_ARG4);
473 #endif
475         return true;
478 static bool attr_w gen_escape_arg(struct codegen_context *ctx, ip_t ip, uint32_t escape_label)
480         g(gen_load_constant(ctx, R_RET1, ip));
482         gen_insn(INSN_JMP, 0, 0, 0);
483         gen_four(escape_label);
485         return true;
488 static bool attr_w gen_escape(struct codegen_context *ctx)
490         int i, offs;
492 #if !defined(STRUCT_RET_OFFSET)
493         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
494         gen_one(R_RET0);
495         gen_one(R_FRAME);
496 #else
497         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
498         gen_one(R_RET0);
499         gen_one(ARG_ADDRESS_1);
500         gen_one(R_SP);
501         gen_eight(STRUCT_RET_OFFSET);
503         gen_insn(INSN_MOV, OP_SIZE_NATIVE, 0, 0);
504         gen_one(ARG_ADDRESS_1);
505         gen_one(R_RET0);
506         gen_eight(0);
507         gen_one(R_FRAME);
509         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
510         gen_one(ARG_ADDRESS_1);
511         gen_one(R_RET0);
512         gen_eight(1U << OP_SIZE_NATIVE);
513         gen_one(R_RET1);
514 #endif
515         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
516         gen_one(R_SCRATCH_NA_1);
517         gen_one(ARG_ADDRESS_1);
518         gen_one(R_SP);
519         gen_eight(LR_OFFSET);
521         for (i = R_LOWEST_SAVED, offs = REGS_OFFSET; i <= R_31; i++, offs += 1 << OP_SIZE_ADDRESS) {
522                 gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
523                 gen_one(i);
524                 gen_one(ARG_ADDRESS_1);
525                 gen_one(R_SP);
526                 gen_eight(offs);
527         }
529         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
530         gen_one(R_LR);
531         gen_one(R_SCRATCH_NA_1);
533         gen_insn(INSN_ALU, OP_SIZE_NATIVE, 0, 0);
534         gen_one(R_SP);
535         gen_one(R_SP);
536         gen_one(ARG_IMM);
537         gen_eight(FRAME_SIZE);
539         gen_insn(INSN_RET, 0, 0, 0);
541         return true;
544 static bool attr_w gen_upcall_argument(struct codegen_context attr_unused *ctx, unsigned attr_unused arg)
546         return true;
549 static bool attr_w gen_upcall(struct codegen_context *ctx, unsigned offset, unsigned n_args)
551 #ifndef AIX_CALL
552         g(gen_address(ctx, R_UPCALL, offset, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_ADDRESS));
553         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
554         gen_one(R_12);
555         gen_address_offset();
557         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
558         gen_one(R_CTR);
559         gen_one(R_12);
561         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_NATIVE, 0, 0);
562         gen_one(R_CTR);
563 #else
564         g(gen_address(ctx, R_UPCALL, offset, IMM_PURPOSE_LDR_OFFSET, OP_SIZE_ADDRESS));
565         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
566         gen_one(R_SCRATCH_NA_2);
567         gen_address_offset();
569         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
570         gen_one(R_SCRATCH_NA_1);
571         gen_one(ARG_ADDRESS_1);
572         gen_one(R_SCRATCH_NA_2);
573         gen_eight(0);
575         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
576         gen_one(R_CTR);
577         gen_one(R_SCRATCH_NA_1);
579         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
580         gen_one(R_2);
581         gen_one(ARG_ADDRESS_1);
582         gen_one(R_SCRATCH_NA_2);
583         gen_eight(1 << OP_SIZE_ADDRESS);
585         gen_insn(INSN_MOV, OP_SIZE_ADDRESS, 0, 0);
586         gen_one(R_11);
587         gen_one(ARG_ADDRESS_1);
588         gen_one(R_SCRATCH_NA_2);
589         gen_eight(2 << OP_SIZE_ADDRESS);
591         gen_insn(INSN_CALL_INDIRECT, OP_SIZE_NATIVE, 0, 0);
592         gen_one(R_CTR);
593 #endif
594         g(gen_upcall_end(ctx, n_args));
596         return true;
599 static bool attr_w gen_timestamp_test(struct codegen_context *ctx, uint32_t escape_label)
601         g(gen_address(ctx, R_UPCALL, offsetof(struct cg_upcall_vector_s, ts), IMM_PURPOSE_LDR_OFFSET, OP_SIZE_4));
602         gen_insn(INSN_MOV, OP_SIZE_4, 0, 0);
603         gen_one(R_SCRATCH_1);
604         gen_address_offset();
606         gen_insn(INSN_CMP, OP_SIZE_4, 0, 1);
607         gen_one(R_SCRATCH_1);
608         gen_one(R_TIMESTAMP);
610         gen_insn(INSN_JMP_COND, OP_SIZE_4, COND_NE, 0);
611         gen_four(escape_label);
613         return true;