1 /* Auxiliary functions for output asm template or expand rtl
2 pattern of Andes NDS32 cpu for GNU compiler
3 Copyright (C) 2012-2015 Free Software Foundation, Inc.
4 Contributed by Andes Technology Corporation.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 3, or (at your
11 option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* ------------------------------------------------------------------------ */
26 #include "coretypes.h"
32 #include "stor-layout.h"
36 #include "insn-config.h" /* Required by recog.h. */
37 #include "conditions.h"
39 #include "insn-attr.h" /* For DFA state_t. */
40 #include "insn-codes.h" /* For CODE_FOR_xxx. */
41 #include "reload.h" /* For push_reload(). */
43 #include "insn-config.h"
51 #include "diagnostic-core.h"
56 #include "cfgcleanup.h"
58 #include "tm-constrs.h"
59 #include "optabs.h" /* For GEN_FCN. */
61 #include "langhooks.h" /* For add_builtin_function(). */
64 /* ------------------------------------------------------------------------ */
66 /* A helper function to return character based on byte size. */
68 nds32_byte_to_size (int byte
)
79 /* Normally it should not be here. */
84 /* A helper function to return memory format. */
85 enum nds32_16bit_address_type
86 nds32_mem_format (rtx op
)
88 machine_mode mode_test
;
93 return ADDRESS_NOT_16BIT_FORMAT
;
95 mode_test
= GET_MODE (op
);
100 if (GET_CODE (op
) == REG
&& (mode_test
== SImode
))
103 /* 333 format for QI/HImode. */
104 if (GET_CODE (op
) == REG
&& (REGNO (op
) < R8_REGNUM
))
105 return ADDRESS_LO_REG_IMM3U
;
107 /* post_inc 333 format. */
108 if ((GET_CODE (op
) == POST_INC
) && (mode_test
== SImode
))
110 regno
= REGNO(XEXP (op
, 0));
113 return ADDRESS_POST_INC_LO_REG_IMM3U
;
116 /* post_inc 333 format. */
117 if ((GET_CODE (op
) == POST_MODIFY
)
118 && (mode_test
== SImode
)
119 && (REG_P (XEXP (XEXP (op
, 1), 0)))
120 && (CONST_INT_P (XEXP (XEXP (op
, 1), 1))))
122 regno
= REGNO (XEXP (XEXP (op
, 1), 0));
123 val
= INTVAL (XEXP (XEXP (op
, 1), 1));
124 if (regno
< 8 && val
< 32)
125 return ADDRESS_POST_INC_LO_REG_IMM3U
;
128 if ((GET_CODE (op
) == PLUS
)
129 && (GET_CODE (XEXP (op
, 0)) == REG
)
130 && (GET_CODE (XEXP (op
, 1)) == CONST_INT
))
132 val
= INTVAL (XEXP (op
, 1));
134 regno
= REGNO(XEXP (op
, 0));
137 && regno
!= SP_REGNUM
138 && regno
!= FP_REGNUM
)
139 return ADDRESS_NOT_16BIT_FORMAT
;
145 if (val
>= 0 && val
< 8 && regno
< 8)
146 return ADDRESS_LO_REG_IMM3U
;
151 if (val
>= 0 && val
< 16 && (val
% 2 == 0) && regno
< 8)
152 return ADDRESS_LO_REG_IMM3U
;
158 /* fp imply 37 format. */
159 if ((regno
== FP_REGNUM
) &&
160 (val
>= 0 && val
< 512 && (val
% 4 == 0)))
161 return ADDRESS_FP_IMM7U
;
162 /* sp imply 37 format. */
163 else if ((regno
== SP_REGNUM
) &&
164 (val
>= 0 && val
< 512 && (val
% 4 == 0)))
165 return ADDRESS_SP_IMM7U
;
167 else if (val
>= 0 && val
< 32 && (val
% 4 == 0) && regno
< 8)
168 return ADDRESS_LO_REG_IMM3U
;
176 return ADDRESS_NOT_16BIT_FORMAT
;
179 /* Output 16-bit store. */
181 nds32_output_16bit_store (rtx
*operands
, int byte
)
185 rtx code
= XEXP (operands
[0], 0);
187 size
= nds32_byte_to_size (byte
);
189 switch (nds32_mem_format (operands
[0]))
193 output_asm_insn ("swi450\t%1, [%0]", operands
);
195 case ADDRESS_LO_REG_IMM3U
:
196 snprintf (pattern
, sizeof (pattern
), "s%ci333\t%%1, %%0", size
);
197 output_asm_insn (pattern
, operands
);
199 case ADDRESS_POST_INC_LO_REG_IMM3U
:
200 snprintf (pattern
, sizeof (pattern
), "s%ci333.bi\t%%1, %%0", size
);
201 output_asm_insn (pattern
, operands
);
203 case ADDRESS_FP_IMM7U
:
204 output_asm_insn ("swi37\t%1, %0", operands
);
206 case ADDRESS_SP_IMM7U
:
207 /* Get immediate value and set back to operands[1]. */
208 operands
[0] = XEXP (code
, 1);
209 output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands
);
218 /* Output 16-bit load. */
220 nds32_output_16bit_load (rtx
*operands
, int byte
)
224 rtx code
= XEXP (operands
[1], 0);
226 size
= nds32_byte_to_size (byte
);
228 switch (nds32_mem_format (operands
[1]))
232 output_asm_insn ("lwi450\t%0, [%1]", operands
);
234 case ADDRESS_LO_REG_IMM3U
:
235 snprintf (pattern
, sizeof (pattern
), "l%ci333\t%%0, %%1", size
);
236 output_asm_insn (pattern
, operands
);
238 case ADDRESS_POST_INC_LO_REG_IMM3U
:
239 snprintf (pattern
, sizeof (pattern
), "l%ci333.bi\t%%0, %%1", size
);
240 output_asm_insn (pattern
, operands
);
242 case ADDRESS_FP_IMM7U
:
243 output_asm_insn ("lwi37\t%0, %1", operands
);
245 case ADDRESS_SP_IMM7U
:
246 /* Get immediate value and set back to operands[0]. */
247 operands
[1] = XEXP (code
, 1);
248 output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands
);
257 /* Output 32-bit store. */
259 nds32_output_32bit_store (rtx
*operands
, int byte
)
263 rtx code
= XEXP (operands
[0], 0);
265 size
= nds32_byte_to_size (byte
);
267 switch (GET_CODE (code
))
271 => access location by using register,
272 use "sbi / shi / swi" */
273 snprintf (pattern
, sizeof (pattern
), "s%ci\t%%1, %%0", size
);
278 /* (mem (symbol_ref X))
280 => access global variables,
281 use "sbi.gp / shi.gp / swi.gp" */
282 operands
[0] = XEXP (operands
[0], 0);
283 snprintf (pattern
, sizeof (pattern
), "s%ci.gp\t%%1, [ + %%0]", size
);
287 /* (mem (post_inc reg))
288 => access location by using register which will be post increment,
289 use "sbi.bi / shi.bi / swi.bi" */
290 snprintf (pattern
, sizeof (pattern
),
291 "s%ci.bi\t%%1, %%0, %d", size
, byte
);
295 /* (mem (post_dec reg))
296 => access location by using register which will be post decrement,
297 use "sbi.bi / shi.bi / swi.bi" */
298 snprintf (pattern
, sizeof (pattern
),
299 "s%ci.bi\t%%1, %%0, -%d", size
, byte
);
303 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
307 /* (mem (post_modify (reg) (plus (reg) (reg))))
308 => access location by using register which will be
309 post modified with reg,
310 use "sb.bi/ sh.bi / sw.bi" */
311 snprintf (pattern
, sizeof (pattern
), "s%c.bi\t%%1, %%0", size
);
314 /* (mem (post_modify (reg) (plus (reg) (const_int))))
315 => access location by using register which will be
316 post modified with const_int,
317 use "sbi.bi/ shi.bi / swi.bi" */
318 snprintf (pattern
, sizeof (pattern
), "s%ci.bi\t%%1, %%0", size
);
326 switch (GET_CODE (XEXP (code
, 1)))
330 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
331 => access location by adding two registers,
332 use "sb / sh / sw" */
333 snprintf (pattern
, sizeof (pattern
), "s%c\t%%1, %%0", size
);
336 /* (mem (plus reg const_int))
337 => access location by adding one register with const_int,
338 use "sbi / shi / swi" */
339 snprintf (pattern
, sizeof (pattern
), "s%ci\t%%1, %%0", size
);
347 operands
[2] = XEXP (code
, 1);
348 operands
[0] = XEXP (code
, 0);
349 snprintf (pattern
, sizeof (pattern
),
350 "s%ci\t%%1, [%%0 + lo12(%%2)]", size
);
357 output_asm_insn (pattern
, operands
);
361 /* Output 32-bit load. */
363 nds32_output_32bit_load (rtx
*operands
, int byte
)
369 code
= XEXP (operands
[1], 0);
371 size
= nds32_byte_to_size (byte
);
373 switch (GET_CODE (code
))
377 => access location by using register,
378 use "lbi / lhi / lwi" */
379 snprintf (pattern
, sizeof (pattern
), "l%ci\t%%0, %%1", size
);
384 /* (mem (symbol_ref X))
386 => access global variables,
387 use "lbi.gp / lhi.gp / lwi.gp" */
388 operands
[1] = XEXP (operands
[1], 0);
389 snprintf (pattern
, sizeof (pattern
), "l%ci.gp\t%%0, [ + %%1]", size
);
393 /* (mem (post_inc reg))
394 => access location by using register which will be post increment,
395 use "lbi.bi / lhi.bi / lwi.bi" */
396 snprintf (pattern
, sizeof (pattern
),
397 "l%ci.bi\t%%0, %%1, %d", size
, byte
);
401 /* (mem (post_dec reg))
402 => access location by using register which will be post decrement,
403 use "lbi.bi / lhi.bi / lwi.bi" */
404 snprintf (pattern
, sizeof (pattern
),
405 "l%ci.bi\t%%0, %%1, -%d", size
, byte
);
409 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
413 /* (mem (post_modify (reg) (plus (reg) (reg))))
414 => access location by using register which will be
415 post modified with reg,
416 use "lb.bi/ lh.bi / lw.bi" */
417 snprintf (pattern
, sizeof (pattern
), "l%c.bi\t%%0, %%1", size
);
420 /* (mem (post_modify (reg) (plus (reg) (const_int))))
421 => access location by using register which will be
422 post modified with const_int,
423 use "lbi.bi/ lhi.bi / lwi.bi" */
424 snprintf (pattern
, sizeof (pattern
), "l%ci.bi\t%%0, %%1", size
);
432 switch (GET_CODE (XEXP (code
, 1)))
436 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
437 use "lb / lh / lw" */
438 snprintf (pattern
, sizeof (pattern
), "l%c\t%%0, %%1", size
);
441 /* (mem (plus reg const_int))
442 => access location by adding one register with const_int,
443 use "lbi / lhi / lwi" */
444 snprintf (pattern
, sizeof (pattern
), "l%ci\t%%0, %%1", size
);
452 operands
[2] = XEXP (code
, 1);
453 operands
[1] = XEXP (code
, 0);
454 snprintf (pattern
, sizeof (pattern
),
455 "l%ci\t%%0, [%%1 + lo12(%%2)]", size
);
462 output_asm_insn (pattern
, operands
);
466 /* Output 32-bit load with signed extension. */
468 nds32_output_32bit_load_s (rtx
*operands
, int byte
)
474 code
= XEXP (operands
[1], 0);
476 size
= nds32_byte_to_size (byte
);
478 switch (GET_CODE (code
))
482 => access location by using register,
484 snprintf (pattern
, sizeof (pattern
), "l%csi\t%%0, %%1", size
);
489 /* (mem (symbol_ref X))
491 => access global variables,
492 use "lbsi.gp / lhsi.gp" */
493 operands
[1] = XEXP (operands
[1], 0);
494 snprintf (pattern
, sizeof (pattern
), "l%csi.gp\t%%0, [ + %%1]", size
);
498 /* (mem (post_inc reg))
499 => access location by using register which will be post increment,
500 use "lbsi.bi / lhsi.bi" */
501 snprintf (pattern
, sizeof (pattern
),
502 "l%csi.bi\t%%0, %%1, %d", size
, byte
);
506 /* (mem (post_dec reg))
507 => access location by using register which will be post decrement,
508 use "lbsi.bi / lhsi.bi" */
509 snprintf (pattern
, sizeof (pattern
),
510 "l%csi.bi\t%%0, %%1, -%d", size
, byte
);
514 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
518 /* (mem (post_modify (reg) (plus (reg) (reg))))
519 => access location by using register which will be
520 post modified with reg,
521 use "lbs.bi/ lhs.bi" */
522 snprintf (pattern
, sizeof (pattern
), "l%cs.bi\t%%0, %%1", size
);
525 /* (mem (post_modify (reg) (plus (reg) (const_int))))
526 => access location by using register which will be
527 post modified with const_int,
528 use "lbsi.bi/ lhsi.bi" */
529 snprintf (pattern
, sizeof (pattern
), "l%csi.bi\t%%0, %%1", size
);
537 switch (GET_CODE (XEXP (code
, 1)))
541 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
543 snprintf (pattern
, sizeof (pattern
), "l%cs\t%%0, %%1", size
);
546 /* (mem (plus reg const_int))
547 => access location by adding one register with const_int,
549 snprintf (pattern
, sizeof (pattern
), "l%csi\t%%0, %%1", size
);
557 operands
[2] = XEXP (code
, 1);
558 operands
[1] = XEXP (code
, 0);
559 snprintf (pattern
, sizeof (pattern
),
560 "l%csi\t%%0, [%%1 + lo12(%%2)]", size
);
567 output_asm_insn (pattern
, operands
);
571 /* Function to output stack push operation.
572 We need to deal with normal stack push multiple or stack v3push. */
574 nds32_output_stack_push (rtx par_rtx
)
576 /* A string pattern for output_asm_insn(). */
578 /* The operands array which will be used in output_asm_insn(). */
580 /* Pick up varargs first regno and last regno for further use. */
581 int rb_va_args
= cfun
->machine
->va_args_first_regno
;
582 int re_va_args
= cfun
->machine
->va_args_last_regno
;
583 int last_argument_regno
= NDS32_FIRST_GPR_REGNUM
584 + NDS32_MAX_GPR_REGS_FOR_ARGS
586 /* Pick up callee-saved first regno and last regno for further use. */
587 int rb_callee_saved
= cfun
->machine
->callee_saved_first_gpr_regno
;
588 int re_callee_saved
= cfun
->machine
->callee_saved_last_gpr_regno
;
590 /* First we need to check if we are pushing argument registers not used
591 for the named arguments. If so, we have to create 'smw.adm' (push.s)
593 if (reg_mentioned_p (gen_rtx_REG (SImode
, last_argument_regno
), par_rtx
))
595 /* Set operands[0] and operands[1]. */
596 operands
[0] = gen_rtx_REG (SImode
, rb_va_args
);
597 operands
[1] = gen_rtx_REG (SImode
, re_va_args
);
598 /* Create assembly code pattern: "Rb, Re, { }". */
599 snprintf (pattern
, sizeof (pattern
), "push.s\t%s", "%0, %1, { }");
600 /* We use output_asm_insn() to output assembly code by ourself. */
601 output_asm_insn (pattern
, operands
);
605 /* If we step here, we are going to do v3push or multiple push operation. */
607 /* The v3push/v3pop instruction should only be applied on
608 none-isr and none-variadic function. */
610 && !nds32_isr_function_p (current_function_decl
)
611 && (cfun
->machine
->va_args_size
== 0))
615 operands[1]: imm8u */
617 /* This variable is to check if 'push25 Re,imm8u' is available. */
620 /* Set operands[0]. */
621 operands
[0] = gen_rtx_REG (SImode
, re_callee_saved
);
623 /* Check if we can generate 'push25 Re,imm8u',
624 otherwise, generate 'push25 Re,0'. */
625 sp_adjust
= cfun
->machine
->local_size
626 + cfun
->machine
->out_args_size
627 + cfun
->machine
->callee_saved_area_gpr_padding_bytes
;
628 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
629 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
))
630 operands
[1] = GEN_INT (sp_adjust
);
632 operands
[1] = GEN_INT (0);
634 /* Create assembly code pattern. */
635 snprintf (pattern
, sizeof (pattern
), "push25\t%%0, %%1");
639 /* For normal stack push multiple:
644 /* This variable is used to check if we only need to generate En4 field.
645 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
646 int push_en4_only_p
= 0;
648 /* Set operands[0] and operands[1]. */
649 operands
[0] = gen_rtx_REG (SImode
, rb_callee_saved
);
650 operands
[1] = gen_rtx_REG (SImode
, re_callee_saved
);
652 /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
653 if (!cfun
->machine
->fp_size
654 && !cfun
->machine
->gp_size
655 && !cfun
->machine
->lp_size
656 && REGNO (operands
[0]) == SP_REGNUM
657 && REGNO (operands
[1]) == SP_REGNUM
)
659 /* No need to generate instruction. */
664 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
665 if (REGNO (operands
[0]) == SP_REGNUM
666 && REGNO (operands
[1]) == SP_REGNUM
)
669 /* Create assembly code pattern.
670 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
671 snprintf (pattern
, sizeof (pattern
),
672 "push.s\t%s{%s%s%s }",
673 push_en4_only_p
? "" : "%0, %1, ",
674 cfun
->machine
->fp_size
? " $fp" : "",
675 cfun
->machine
->gp_size
? " $gp" : "",
676 cfun
->machine
->lp_size
? " $lp" : "");
680 /* We use output_asm_insn() to output assembly code by ourself. */
681 output_asm_insn (pattern
, operands
);
685 /* Function to output stack pop operation.
686 We need to deal with normal stack pop multiple or stack v3pop. */
688 nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED
)
690 /* A string pattern for output_asm_insn(). */
692 /* The operands array which will be used in output_asm_insn(). */
694 /* Pick up callee-saved first regno and last regno for further use. */
695 int rb_callee_saved
= cfun
->machine
->callee_saved_first_gpr_regno
;
696 int re_callee_saved
= cfun
->machine
->callee_saved_last_gpr_regno
;
698 /* If we step here, we are going to do v3pop or multiple pop operation. */
700 /* The v3push/v3pop instruction should only be applied on
701 none-isr and none-variadic function. */
703 && !nds32_isr_function_p (current_function_decl
)
704 && (cfun
->machine
->va_args_size
== 0))
708 operands[1]: imm8u */
710 /* This variable is to check if 'pop25 Re,imm8u' is available. */
713 /* Set operands[0]. */
714 operands
[0] = gen_rtx_REG (SImode
, re_callee_saved
);
716 /* Check if we can generate 'pop25 Re,imm8u',
717 otherwise, generate 'pop25 Re,0'.
718 We have to consider alloca issue as well.
719 If the function does call alloca(), the stack pointer is not fixed.
720 In that case, we cannot use 'pop25 Re,imm8u' directly.
721 We have to caculate stack pointer from frame pointer
722 and then use 'pop25 Re,0'. */
723 sp_adjust
= cfun
->machine
->local_size
724 + cfun
->machine
->out_args_size
725 + cfun
->machine
->callee_saved_area_gpr_padding_bytes
;
726 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
727 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
)
728 && !cfun
->calls_alloca
)
729 operands
[1] = GEN_INT (sp_adjust
);
731 operands
[1] = GEN_INT (0);
733 /* Create assembly code pattern. */
734 snprintf (pattern
, sizeof (pattern
), "pop25\t%%0, %%1");
738 /* For normal stack pop multiple:
743 /* This variable is used to check if we only need to generate En4 field.
744 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
745 int pop_en4_only_p
= 0;
747 /* Set operands[0] and operands[1]. */
748 operands
[0] = gen_rtx_REG (SImode
, rb_callee_saved
);
749 operands
[1] = gen_rtx_REG (SImode
, re_callee_saved
);
751 /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
752 if (!cfun
->machine
->fp_size
753 && !cfun
->machine
->gp_size
754 && !cfun
->machine
->lp_size
755 && REGNO (operands
[0]) == SP_REGNUM
756 && REGNO (operands
[1]) == SP_REGNUM
)
758 /* No need to generate instruction. */
763 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
764 if (REGNO (operands
[0]) == SP_REGNUM
765 && REGNO (operands
[1]) == SP_REGNUM
)
768 /* Create assembly code pattern.
769 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
770 snprintf (pattern
, sizeof (pattern
),
771 "pop.s\t%s{%s%s%s }",
772 pop_en4_only_p
? "" : "%0, %1, ",
773 cfun
->machine
->fp_size
? " $fp" : "",
774 cfun
->machine
->gp_size
? " $gp" : "",
775 cfun
->machine
->lp_size
? " $lp" : "");
779 /* We use output_asm_insn() to output assembly code by ourself. */
780 output_asm_insn (pattern
, operands
);
784 /* Function to generate PC relative jump table.
785 Refer to nds32.md for more details.
787 The following is the sample for the case that diff value
788 can be presented in '.short' size.
790 addi $r1, $r1, -(case_lower_bound)
791 slti $ta, $r1, (case_number)
792 beqz $ta, .L_skip_label
794 la $ta, .L35 ! get jump table address
795 lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
812 nds32_output_casesi_pc_relative (rtx
*operands
)
817 diff_vec
= PATTERN (NEXT_INSN (as_a
<rtx_insn
*> (operands
[1])));
819 gcc_assert (GET_CODE (diff_vec
) == ADDR_DIFF_VEC
);
821 /* Step C: "t <-- operands[1]". */
822 output_asm_insn ("la\t$ta, %l1", operands
);
824 /* Get the mode of each element in the difference vector. */
825 mode
= GET_MODE (diff_vec
);
827 /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
828 where m is 0, 1, or 2 to load address-diff value from table. */
832 output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands
);
835 output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands
);
838 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands
);
844 /* Step E: "t <-- z + t".
845 Add table label_ref with address-diff value to
846 obtain target case address. */
847 output_asm_insn ("add\t$ta, %2, $ta", operands
);
849 /* Step F: jump to target with register t. */
856 /* Function to generate normal jump table. */
858 nds32_output_casesi (rtx
*operands
)
860 /* Step C: "t <-- operands[1]". */
861 output_asm_insn ("la\t$ta, %l1", operands
);
863 /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
864 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands
);
866 /* No need to perform Step E, which is only used for
867 pc relative jump table. */
869 /* Step F: jump to target with register z. */
876 /* ------------------------------------------------------------------------ */