]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pru/pru.c
bpf: avoid potential NULL pointer dereference
[thirdparty/gcc.git] / gcc / config / pru / pru.c
CommitLineData
8d2af3a2 1/* Target machine subroutines for TI PRU.
99dee823 2 Copyright (C) 2014-2021 Free Software Foundation, Inc.
8d2af3a2
DD
3 Dimitar Dimitrov <dimitar@dinux.eu>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21#define IN_TARGET_CODE 1
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "backend.h"
27#include "target.h"
28#include "rtl.h"
29#include "tree.h"
30#include "stringpool.h"
31#include "attribs.h"
32#include "df.h"
33#include "memmodel.h"
34#include "tm_p.h"
35#include "optabs.h"
36#include "regs.h"
37#include "emit-rtl.h"
38#include "recog.h"
39#include "diagnostic-core.h"
40#include "output.h"
41#include "insn-attr.h"
42#include "flags.h"
43#include "explow.h"
44#include "calls.h"
45#include "varasm.h"
46#include "expr.h"
47#include "toplev.h"
48#include "langhooks.h"
49#include "cfgrtl.h"
50#include "stor-layout.h"
51#include "dumpfile.h"
52#include "builtins.h"
53#include "pru-protos.h"
54
55/* This file should be included last. */
56#include "target-def.h"
57
58#define INIT_ARRAY_ENTRY_BYTES 2
59
60/* Global PRU CTABLE entries, filled in by pragmas, and used for fast
61 addressing via LBCO/SBCO instructions. */
62struct pru_ctable_entry pru_ctable[32];
63
64/* Forward function declarations. */
65static bool prologue_saved_reg_p (int);
66static void pru_reorg_loop (rtx_insn *);
67
68struct GTY (()) machine_function
69{
70 /* Current frame information, to be filled in by pru_compute_frame_layout
71 with register save masks, and offsets for the current function. */
72
73 /* Mask of registers to save. */
74 HARD_REG_SET save_mask;
75 /* Number of bytes that the entire frame takes up. */
76 int total_size;
77 /* Number of bytes that variables take up. */
78 int var_size;
79 /* Number of bytes that outgoing arguments take up. */
80 int out_args_size;
81 /* Number of bytes needed to store registers in frame. */
82 int save_reg_size;
83 /* Offset from new stack pointer to store registers. */
84 int save_regs_offset;
85 /* True if final frame layout is already calculated. */
86 bool initialized;
87 /* Number of doloop tags used so far. */
88 int doloop_tags;
89 /* True if the last tag was allocated to a doloop_end. */
90 bool doloop_tag_from_end;
91};
92\f
93/* Stack layout and calling conventions.
94
95 The PRU ABI defines r4 as Argument Pointer. GCC implements the same
96 semantics, but represents it with HARD_FRAME_POINTER_REGNUM and
97 names it FP. The stack layout is shown below:
98
99 ---------------------- high address
100 | incoming args
101 ------call-boundary---
102 | pretend_args ^
103 FP ---------------- | total
104 | save_regs | frame
105 --------------- | size
106 | local vars |
107 --------------- |
108 | outgoing args V
109 SP ---------------------- low address
110
111 */
112
113#define PRU_STACK_ALIGN(LOC) ROUND_UP ((LOC), STACK_BOUNDARY / BITS_PER_UNIT)
114
115/* Implement TARGET_COMPUTE_FRAME_LAYOUT. */
116static void
117pru_compute_frame_layout (void)
118{
119 int regno;
120 HARD_REG_SET *save_mask;
121 int total_size;
122 int var_size;
123 int out_args_size;
124 int save_reg_size;
125
126 gcc_assert (!cfun->machine->initialized);
127
128 save_mask = &cfun->machine->save_mask;
129 CLEAR_HARD_REG_SET (*save_mask);
130
131 var_size = PRU_STACK_ALIGN ((HOST_WIDE_INT) get_frame_size ());
132 out_args_size = PRU_STACK_ALIGN ((HOST_WIDE_INT) crtl->outgoing_args_size);
133 total_size = var_size + out_args_size;
134
135 /* Calculate space needed for gp registers. */
136 save_reg_size = 0;
137 for (regno = 0; regno <= LAST_GP_REGNUM; regno++)
138 if (prologue_saved_reg_p (regno))
139 {
140 SET_HARD_REG_BIT (*save_mask, regno);
141 save_reg_size += 1;
142 }
143
144 save_reg_size = PRU_STACK_ALIGN (save_reg_size);
145 total_size += save_reg_size;
146 total_size += PRU_STACK_ALIGN (crtl->args.pretend_args_size);
147
148 /* Save other computed information. */
149 cfun->machine->total_size = total_size;
150 cfun->machine->var_size = var_size;
151 cfun->machine->out_args_size = out_args_size;
152 cfun->machine->save_reg_size = save_reg_size;
153 cfun->machine->initialized = reload_completed;
154 cfun->machine->save_regs_offset = out_args_size + var_size;
155}
156
157/* Emit efficient RTL equivalent of ADD3 with the given const_int for
158 frame-related registers.
159 op0 - Destination register.
160 op1 - First addendum operand (a register).
161 addendum - Second addendum operand (a constant).
162 kind - Note kind. REG_NOTE_MAX if no note must be added.
163 */
164static rtx
165pru_add3_frame_adjust (rtx op0, rtx op1, int addendum,
166 const enum reg_note kind)
167{
168 rtx insn;
169
170 rtx op0_adjust = gen_rtx_SET (op0, plus_constant (Pmode, op1, addendum));
171
172 if (UBYTE_INT (addendum) || UBYTE_INT (-addendum))
173 insn = emit_insn (op0_adjust);
174 else
175 {
176 /* Help the compiler to cope with an arbitrary integer constant.
177 Reload has finished so we can't expect the compiler to
178 auto-allocate a temporary register. But we know that call-saved
179 registers are not live yet, so we utilize them. */
180 rtx tmpreg = gen_rtx_REG (Pmode, PROLOGUE_TEMP_REGNUM);
181 if (addendum < 0)
182 {
183 emit_insn (gen_rtx_SET (tmpreg, gen_int_mode (-addendum, Pmode)));
184 insn = emit_insn (gen_sub3_insn (op0, op1, tmpreg));
185 }
186 else
187 {
188 emit_insn (gen_rtx_SET (tmpreg, gen_int_mode (addendum, Pmode)));
189 insn = emit_insn (gen_add3_insn (op0, op1, tmpreg));
190 }
191 }
192
193 /* Attach a note indicating what happened. */
194 if (kind != REG_NOTE_MAX)
195 add_reg_note (insn, kind, copy_rtx (op0_adjust));
196
197 RTX_FRAME_RELATED_P (insn) = 1;
198
199 return insn;
200}
201
202/* Add a const_int to the stack pointer register. */
203static rtx
204pru_add_to_sp (int addendum, const enum reg_note kind)
205{
206 return pru_add3_frame_adjust (stack_pointer_rtx, stack_pointer_rtx,
207 addendum, kind);
208}
209
210/* Helper function used during prologue/epilogue. Emits a single LBBO/SBBO
211 instruction for load/store of the next group of consecutive registers. */
212static int
213xbbo_next_reg_cluster (int regno_start, int *sp_offset, bool do_store)
214{
215 int regno, nregs, i;
216 rtx addr;
217 rtx_insn *insn;
218
219 nregs = 0;
220
221 /* Skip the empty slots. */
222 for (; regno_start <= LAST_GP_REGNUM;)
223 if (TEST_HARD_REG_BIT (cfun->machine->save_mask, regno_start))
224 break;
225 else
226 regno_start++;
227
228 /* Find the largest consecutive group of registers to save. */
229 for (regno = regno_start; regno <= LAST_GP_REGNUM;)
230 if (TEST_HARD_REG_BIT (cfun->machine->save_mask, regno))
231 {
232 regno++;
233 nregs++;
234 }
235 else
236 break;
237
238 if (!nregs)
239 return -1;
240
241 gcc_assert (UBYTE_INT (*sp_offset));
242
243 /* Ok, save this bunch. */
244 addr = plus_constant (Pmode, stack_pointer_rtx, *sp_offset);
245
246 if (do_store)
247 insn = targetm.gen_store_multiple (gen_frame_mem (BLKmode, addr),
248 gen_rtx_REG (QImode, regno_start),
249 GEN_INT (nregs));
250 else
251 insn = targetm.gen_load_multiple (gen_rtx_REG (QImode, regno_start),
252 gen_frame_mem (BLKmode, addr),
253 GEN_INT (nregs));
254
255 gcc_assert (reload_completed);
256 gcc_assert (insn);
257 emit_insn (insn);
258
259 /* Tag as frame-related. */
260 RTX_FRAME_RELATED_P (insn) = 1;
261
262 if (!do_store)
263 {
264 /* Tag epilogue unwind notes. */
265 for (i = regno_start; i < (regno_start + nregs); i++)
266 add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (QImode, i));
267 }
268
269 /* Increment and save offset in anticipation of the next register group. */
270 *sp_offset += nregs * UNITS_PER_WORD;
271
272 return regno_start + nregs;
273}
274
275/* Emit function prologue. */
276void
277pru_expand_prologue (void)
278{
279 int regno_start;
280 int total_frame_size;
281 int sp_offset; /* Offset from base_reg to final stack value. */
282 int save_regs_base; /* Offset from base_reg to register save area. */
283 int save_offset; /* Temporary offset to currently saved register group. */
284
285 total_frame_size = cfun->machine->total_size;
286
287 if (flag_stack_usage_info)
288 current_function_static_stack_size = total_frame_size;
289
290 /* Decrement the stack pointer. */
291 if (!UBYTE_INT (total_frame_size))
292 {
293 /* We need an intermediary point, this will point at the spill block. */
294 pru_add_to_sp (cfun->machine->save_regs_offset - total_frame_size,
295 REG_NOTE_MAX);
296 save_regs_base = 0;
297 sp_offset = -cfun->machine->save_regs_offset;
298 }
299 else if (total_frame_size)
300 {
301 pru_add_to_sp (- total_frame_size, REG_NOTE_MAX);
302 save_regs_base = cfun->machine->save_regs_offset;
303 sp_offset = 0;
304 }
305 else
306 save_regs_base = sp_offset = 0;
307
308 regno_start = 0;
309 save_offset = save_regs_base;
310 do
311 regno_start = xbbo_next_reg_cluster (regno_start, &save_offset, true);
312 while (regno_start >= 0);
313
314 /* Set FP before adjusting SP. This way fp_offset has
315 better chance to fit in UBYTE. */
316 if (frame_pointer_needed)
317 {
318 int fp_offset = total_frame_size
319 - crtl->args.pretend_args_size
320 + sp_offset;
321
322 pru_add3_frame_adjust (hard_frame_pointer_rtx, stack_pointer_rtx,
323 fp_offset, REG_NOTE_MAX);
324 }
325
326 if (sp_offset)
327 pru_add_to_sp (sp_offset, REG_FRAME_RELATED_EXPR);
328
329 /* If we are profiling, make sure no instructions are scheduled before
330 the call to mcount. */
331 if (crtl->profile)
332 emit_insn (gen_blockage ());
333}
334
335/* Emit function epilogue. */
336void
337pru_expand_epilogue (bool sibcall_p)
338{
339 int total_frame_size;
340 int sp_adjust, save_offset;
341 int regno_start;
342
343 if (!sibcall_p && pru_can_use_return_insn ())
344 {
345 emit_jump_insn (gen_return ());
346 return;
347 }
348
349 emit_insn (gen_blockage ());
350
351 total_frame_size = cfun->machine->total_size;
352
353 if (frame_pointer_needed)
354 {
355 /* Recover the stack pointer. */
356 pru_add3_frame_adjust (stack_pointer_rtx, hard_frame_pointer_rtx,
357 - cfun->machine->save_reg_size,
358 REG_CFA_ADJUST_CFA);
359
360 save_offset = 0;
361 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
362 }
363 else if (!UBYTE_INT (total_frame_size))
364 {
365 pru_add_to_sp (cfun->machine->save_regs_offset, REG_CFA_ADJUST_CFA);
366 save_offset = 0;
367 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
368 }
369 else
370 {
371 save_offset = cfun->machine->save_regs_offset;
372 sp_adjust = total_frame_size;
373 }
374
375 regno_start = 0;
376 do
377 regno_start = xbbo_next_reg_cluster (regno_start, &save_offset, false);
378 while (regno_start >= 0);
379
380 /* Emit a blockage insn here to keep these insns from being moved to
381 an earlier spot in the epilogue.
382
383 This is necessary as we must not cut the stack back before all the
384 restores are finished. */
385 emit_insn (gen_blockage ());
386
387 if (sp_adjust)
388 pru_add_to_sp (sp_adjust, REG_CFA_ADJUST_CFA);
389
390 if (!sibcall_p)
391 emit_jump_insn (gen_simple_return ());
392}
393
394/* Implement RETURN_ADDR_RTX. Note, we do not support moving
395 back to a previous frame. */
396rtx
397pru_get_return_address (int count)
398{
399 if (count != 0)
400 return NULL_RTX;
401
402 /* Return r3.w2. */
403 return get_hard_reg_initial_val (HImode, RA_REGNUM);
404}
405
406/* Implement FUNCTION_PROFILER macro. */
407void
408pru_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
409{
410 fprintf (file, "\tmov\tr1, ra\n");
411 fprintf (file, "\tcall\t_mcount\n");
412 fprintf (file, "\tmov\tra, r1\n");
413}
414
415/* Dump stack layout. */
416static void
417pru_dump_frame_layout (FILE *file)
418{
419 fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
420 fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START,
421 cfun->machine->total_size);
422 fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START,
423 cfun->machine->var_size);
424 fprintf (file, "\t%s out_args_size = %d\n", ASM_COMMENT_START,
425 cfun->machine->out_args_size);
426 fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
427 cfun->machine->save_reg_size);
428 fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
429 cfun->machine->initialized);
430 fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START,
431 cfun->machine->save_regs_offset);
432 fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
433 crtl->is_leaf);
434 fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
435 frame_pointer_needed);
436 fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
437 crtl->args.pretend_args_size);
438}
439
440/* Return true if REGNO should be saved in the prologue. */
441static bool
442prologue_saved_reg_p (int regno)
443{
444 gcc_assert (GP_REG_P (regno));
445
a365fa06 446 if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
8d2af3a2
DD
447 return true;
448
449 /* 32-bit FP. */
450 if (frame_pointer_needed
451 && regno >= HARD_FRAME_POINTER_REGNUM
452 && regno < HARD_FRAME_POINTER_REGNUM + GET_MODE_SIZE (Pmode))
453 return true;
454
455 /* 16-bit RA. */
456 if (regno == RA_REGNUM && df_regs_ever_live_p (RA_REGNUM))
457 return true;
458 if (regno == RA_REGNUM + 1 && df_regs_ever_live_p (RA_REGNUM + 1))
459 return true;
460
461 return false;
462}
463
464/* Implement TARGET_CAN_ELIMINATE. */
465static bool
466pru_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
467{
468 if (to == STACK_POINTER_REGNUM)
469 return !frame_pointer_needed;
470 return true;
471}
472
473/* Implement INITIAL_ELIMINATION_OFFSET macro. */
474int
475pru_initial_elimination_offset (int from, int to)
476{
477 int offset;
478
479 /* Set OFFSET to the offset from the stack pointer. */
480 switch (from)
481 {
482 case FRAME_POINTER_REGNUM:
483 offset = cfun->machine->out_args_size;
484 break;
485
486 case ARG_POINTER_REGNUM:
487 offset = cfun->machine->total_size;
488 offset -= crtl->args.pretend_args_size;
489 break;
490
491 default:
492 gcc_unreachable ();
493 }
494
495 /* If we are asked for the frame pointer offset, then adjust OFFSET
496 by the offset from the frame pointer to the stack pointer. */
497 if (to == HARD_FRAME_POINTER_REGNUM)
498 offset -= cfun->machine->total_size - crtl->args.pretend_args_size;
499
500
501 return offset;
502}
503
504/* Return nonzero if this function is known to have a null epilogue.
505 This allows the optimizer to omit jumps to jumps if no stack
506 was created. */
507int
508pru_can_use_return_insn (void)
509{
510 if (!reload_completed || crtl->profile)
511 return 0;
512
513 return cfun->machine->total_size == 0;
514}
515\f
516/* Implement TARGET_HARD_REGNO_MODE_OK. */
517
518static bool
519pru_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
520{
521 switch (GET_MODE_SIZE (mode))
522 {
523 case 1: return true;
524 case 2: return (regno % 4) <= 2;
525 case 4: return (regno % 4) == 0;
526 case 8: return (regno % 4) == 0;
527 case 16: return (regno % 4) == 0; /* Not sure why TImode is used. */
528 case 32: return (regno % 4) == 0; /* Not sure why CTImode is used. */
529 default:
530 /* TODO: Find out why VOIDmode and BLKmode are passed. */
531 gcc_assert (mode == BLKmode || mode == VOIDmode);
532 return (regno % 4) == 0;
533 }
534}
535
536/* Implement `TARGET_HARD_REGNO_SCRATCH_OK'.
537 Returns true if REGNO is safe to be allocated as a scratch
538 register (for a define_peephole2) in the current function. */
539
540static bool
541pru_hard_regno_scratch_ok (unsigned int regno)
542{
543 /* Don't allow hard registers that might be part of the frame pointer.
544 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
545 and don't handle a frame pointer that spans more than one register.
546 TODO: Fix those faulty places. */
547
548 if ((!reload_completed || frame_pointer_needed)
549 && (IN_RANGE (regno, HARD_FRAME_POINTER_REGNUM,
550 HARD_FRAME_POINTER_REGNUM + 3)
551 || IN_RANGE (regno, FRAME_POINTER_REGNUM,
552 FRAME_POINTER_REGNUM + 3)))
553 return false;
554
555 return true;
556}
557
558
8d2af3a2
DD
559/* Worker function for `HARD_REGNO_RENAME_OK'.
560 Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
561
562int
563pru_hard_regno_rename_ok (unsigned int old_reg,
564 unsigned int new_reg)
565{
566 /* Don't allow hard registers that might be part of the frame pointer.
567 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
568 and don't care for a frame pointer that spans more than one register.
569 TODO: Fix those faulty places. */
570 if ((!reload_completed || frame_pointer_needed)
571 && (IN_RANGE (old_reg, HARD_FRAME_POINTER_REGNUM,
572 HARD_FRAME_POINTER_REGNUM + 3)
573 || IN_RANGE (old_reg, FRAME_POINTER_REGNUM,
574 FRAME_POINTER_REGNUM + 3)
575 || IN_RANGE (new_reg, HARD_FRAME_POINTER_REGNUM,
576 HARD_FRAME_POINTER_REGNUM + 3)
577 || IN_RANGE (new_reg, FRAME_POINTER_REGNUM,
578 FRAME_POINTER_REGNUM + 3)))
579 return 0;
580
581 return 1;
582}
583\f
584/* Allocate a chunk of memory for per-function machine-dependent data. */
585static struct machine_function *
586pru_init_machine_status (void)
587{
588 return ggc_cleared_alloc<machine_function> ();
589}
590
591/* Implement TARGET_OPTION_OVERRIDE. */
592static void
593pru_option_override (void)
594{
595#ifdef SUBTARGET_OVERRIDE_OPTIONS
596 SUBTARGET_OVERRIDE_OPTIONS;
597#endif
598
599 /* Check for unsupported options. */
600 if (flag_pic == 1)
601 warning (OPT_fpic, "%<-fpic%> is not supported");
602 if (flag_pic == 2)
603 warning (OPT_fPIC, "%<-fPIC%> is not supported");
604 if (flag_pie == 1)
605 warning (OPT_fpie, "%<-fpie%> is not supported");
606 if (flag_pie == 2)
607 warning (OPT_fPIE, "%<-fPIE%> is not supported");
608
609 /* QBxx conditional branching cannot cope with block reordering. */
610 if (flag_reorder_blocks_and_partition)
611 {
612 inform (input_location, "%<-freorder-blocks-and-partition%> "
613 "not supported on this architecture");
614 flag_reorder_blocks_and_partition = 0;
615 flag_reorder_blocks = 1;
616 }
617
618 /* Function to allocate machine-dependent function status. */
619 init_machine_status = &pru_init_machine_status;
620
621 /* Save the initial options in case the user does function specific
622 options. */
623 target_option_default_node = target_option_current_node
ba948b37 624 = build_target_option_node (&global_options, &global_options_set);
8d2af3a2
DD
625
626 /* Due to difficulties in implementing the TI ABI with GCC,
627 at least check and error-out if GCC cannot compile a
628 compliant output. */
629 pru_register_abicheck_pass ();
630}
631\f
632/* Compute a (partial) cost for rtx X. Return true if the complete
633 cost has been computed, and false if subexpressions should be
634 scanned. In either case, *TOTAL contains the cost result. */
635static bool
636pru_rtx_costs (rtx x, machine_mode mode,
637 int outer_code, int opno ATTRIBUTE_UNUSED,
638 int *total, bool speed ATTRIBUTE_UNUSED)
639{
640 const int code = GET_CODE (x);
641
642 switch (code)
643 {
644 case CONST_INT:
645 if ((mode == VOIDmode && UBYTE_INT (INTVAL (x)))
646 || (mode != VOIDmode && const_ubyte_operand (x, mode)))
647 {
648 *total = COSTS_N_INSNS (0);
649 return true;
650 }
651 else if ((mode == VOIDmode && UHWORD_INT (INTVAL (x)))
652 || (mode != VOIDmode && const_uhword_operand (x, mode)))
653 {
654 *total = COSTS_N_INSNS (1);
655 return true;
656 }
657 else if (outer_code == MEM && ctable_addr_operand (x, VOIDmode))
658 {
659 *total = COSTS_N_INSNS (0);
660 return true;
661 }
662 else
663 {
664 *total = COSTS_N_INSNS (2);
665 return true;
666 }
667
668 case LABEL_REF:
669 case SYMBOL_REF:
670 case CONST:
671 {
672 *total = COSTS_N_INSNS (1);
673 return true;
674 }
675 case CONST_DOUBLE:
676 {
677 *total = COSTS_N_INSNS (2);
678 return true;
679 }
680 case CONST_WIDE_INT:
681 {
682 /* PRU declares no vector or very large integer types. */
683 gcc_unreachable ();
684 return true;
685 }
686 case SET:
687 {
688 int factor;
689
690 /* A SET doesn't have a mode, so let's look at the SET_DEST to get
691 the mode for the factor. */
692 mode = GET_MODE (SET_DEST (x));
693
694 /* SI move has the same cost as a QI move. Moves larger than
695 64 bits are costly. */
696 factor = CEIL (GET_MODE_SIZE (mode), GET_MODE_SIZE (SImode));
697 *total = factor * COSTS_N_INSNS (1);
698
699 return false;
700 }
701
702 case MULT:
703 {
704 /* Factor in that "mul" requires fixed registers, which
705 would likely require register moves. */
706 *total = COSTS_N_INSNS (7);
707 return false;
708 }
709 case PLUS:
710 {
711 rtx op0 = XEXP (x, 0);
712 rtx op1 = XEXP (x, 1);
713 machine_mode op1_mode = GET_MODE (op1);
714
715 /* Generic RTL address expressions do not enforce mode for
716 offsets, yet our UBYTE constraint requires it. Fix it here. */
717 if (op1_mode == VOIDmode && CONST_INT_P (op1) && outer_code == MEM)
718 op1_mode = Pmode;
719 if (outer_code == MEM
720 && ((REG_P (op0) && reg_or_ubyte_operand (op1, op1_mode))
721 || ctable_addr_operand (op0, VOIDmode)
722 || ctable_addr_operand (op1, VOIDmode)
723 || (ctable_base_operand (op0, VOIDmode) && REG_P (op1))
724 || (ctable_base_operand (op1, VOIDmode) && REG_P (op0))))
725 {
726 /* CTABLE or REG base addressing - PLUS comes for free. */
727 *total = COSTS_N_INSNS (0);
728 return true;
729 }
730 else
731 {
732 *total = COSTS_N_INSNS (1);
733 return false;
734 }
735 }
736 case SIGN_EXTEND:
737 {
738 *total = COSTS_N_INSNS (3);
739 return false;
740 }
741 case ASHIFTRT:
742 {
743 rtx op1 = XEXP (x, 1);
744 if (const_1_operand (op1, VOIDmode))
745 *total = COSTS_N_INSNS (3);
746 else
747 *total = COSTS_N_INSNS (7);
748 return false;
749 }
750 case ZERO_EXTRACT:
751 {
752 rtx op2 = XEXP (x, 2);
753 if ((outer_code == EQ || outer_code == NE)
754 && CONST_INT_P (op2)
755 && INTVAL (op2) == 1)
756 {
757 /* Branch if bit is set/clear is a single instruction. */
758 *total = COSTS_N_INSNS (0);
759 return true;
760 }
761 else
762 {
763 *total = COSTS_N_INSNS (2);
764 return false;
765 }
766 }
767 case ZERO_EXTEND:
768 {
769 *total = COSTS_N_INSNS (0);
770 return false;
771 }
772
773 default:
774 {
775 /* PRU ALU is 32 bit, despite GCC's UNITS_PER_WORD=1. */
776 int factor = CEIL (GET_MODE_SIZE (mode), GET_MODE_SIZE (SImode));
777 *total = factor * COSTS_N_INSNS (1);
778 return false;
779 }
780 }
781}
782\f
783static GTY(()) rtx eqdf_libfunc;
784static GTY(()) rtx nedf_libfunc;
785static GTY(()) rtx ledf_libfunc;
786static GTY(()) rtx ltdf_libfunc;
787static GTY(()) rtx gedf_libfunc;
788static GTY(()) rtx gtdf_libfunc;
789static GTY(()) rtx eqsf_libfunc;
790static GTY(()) rtx nesf_libfunc;
791static GTY(()) rtx lesf_libfunc;
792static GTY(()) rtx ltsf_libfunc;
793static GTY(()) rtx gesf_libfunc;
794static GTY(()) rtx gtsf_libfunc;
795
796/* Implement the TARGET_INIT_LIBFUNCS macro. We use this to rename library
797 functions to match the PRU ABI. */
798
799static void
800pru_init_libfuncs (void)
801{
802 /* Double-precision floating-point arithmetic. */
803 set_optab_libfunc (add_optab, DFmode, "__pruabi_addd");
804 set_optab_libfunc (sdiv_optab, DFmode, "__pruabi_divd");
805 set_optab_libfunc (smul_optab, DFmode, "__pruabi_mpyd");
806 set_optab_libfunc (neg_optab, DFmode, "__pruabi_negd");
807 set_optab_libfunc (sub_optab, DFmode, "__pruabi_subd");
808
809 /* Single-precision floating-point arithmetic. */
810 set_optab_libfunc (add_optab, SFmode, "__pruabi_addf");
811 set_optab_libfunc (sdiv_optab, SFmode, "__pruabi_divf");
812 set_optab_libfunc (smul_optab, SFmode, "__pruabi_mpyf");
813 set_optab_libfunc (neg_optab, SFmode, "__pruabi_negf");
814 set_optab_libfunc (sub_optab, SFmode, "__pruabi_subf");
815
816 /* Floating-point comparisons. */
817 eqsf_libfunc = init_one_libfunc ("__pruabi_eqf");
818 nesf_libfunc = init_one_libfunc ("__pruabi_neqf");
819 lesf_libfunc = init_one_libfunc ("__pruabi_lef");
820 ltsf_libfunc = init_one_libfunc ("__pruabi_ltf");
821 gesf_libfunc = init_one_libfunc ("__pruabi_gef");
822 gtsf_libfunc = init_one_libfunc ("__pruabi_gtf");
823 eqdf_libfunc = init_one_libfunc ("__pruabi_eqd");
824 nedf_libfunc = init_one_libfunc ("__pruabi_neqd");
825 ledf_libfunc = init_one_libfunc ("__pruabi_led");
826 ltdf_libfunc = init_one_libfunc ("__pruabi_ltd");
827 gedf_libfunc = init_one_libfunc ("__pruabi_ged");
828 gtdf_libfunc = init_one_libfunc ("__pruabi_gtd");
829
830 /* In PRU ABI, much like other TI processors, floating point
831 comparisons return non-standard values. This quirk is handled
832 by disabling the optab library functions, and handling the
833 comparison during RTL expansion. */
834 set_optab_libfunc (eq_optab, SFmode, NULL);
835 set_optab_libfunc (ne_optab, SFmode, NULL);
836 set_optab_libfunc (gt_optab, SFmode, NULL);
837 set_optab_libfunc (ge_optab, SFmode, NULL);
838 set_optab_libfunc (lt_optab, SFmode, NULL);
839 set_optab_libfunc (le_optab, SFmode, NULL);
840 set_optab_libfunc (eq_optab, DFmode, NULL);
841 set_optab_libfunc (ne_optab, DFmode, NULL);
842 set_optab_libfunc (gt_optab, DFmode, NULL);
843 set_optab_libfunc (ge_optab, DFmode, NULL);
844 set_optab_libfunc (lt_optab, DFmode, NULL);
845 set_optab_libfunc (le_optab, DFmode, NULL);
846
847 /* The isunordered function appears to be supported only by GCC. */
848 set_optab_libfunc (unord_optab, SFmode, "__pruabi_unordf");
849 set_optab_libfunc (unord_optab, DFmode, "__pruabi_unordd");
850
851 /* Floating-point to integer conversions. */
852 set_conv_libfunc (sfix_optab, SImode, DFmode, "__pruabi_fixdi");
853 set_conv_libfunc (ufix_optab, SImode, DFmode, "__pruabi_fixdu");
854 set_conv_libfunc (sfix_optab, DImode, DFmode, "__pruabi_fixdlli");
855 set_conv_libfunc (ufix_optab, DImode, DFmode, "__pruabi_fixdull");
856 set_conv_libfunc (sfix_optab, SImode, SFmode, "__pruabi_fixfi");
857 set_conv_libfunc (ufix_optab, SImode, SFmode, "__pruabi_fixfu");
858 set_conv_libfunc (sfix_optab, DImode, SFmode, "__pruabi_fixflli");
859 set_conv_libfunc (ufix_optab, DImode, SFmode, "__pruabi_fixfull");
860
861 /* Conversions between floating types. */
862 set_conv_libfunc (trunc_optab, SFmode, DFmode, "__pruabi_cvtdf");
863 set_conv_libfunc (sext_optab, DFmode, SFmode, "__pruabi_cvtfd");
864
865 /* Integer to floating-point conversions. */
866 set_conv_libfunc (sfloat_optab, DFmode, SImode, "__pruabi_fltid");
867 set_conv_libfunc (ufloat_optab, DFmode, SImode, "__pruabi_fltud");
868 set_conv_libfunc (sfloat_optab, DFmode, DImode, "__pruabi_fltllid");
869 set_conv_libfunc (ufloat_optab, DFmode, DImode, "__pruabi_fltulld");
870 set_conv_libfunc (sfloat_optab, SFmode, SImode, "__pruabi_fltif");
871 set_conv_libfunc (ufloat_optab, SFmode, SImode, "__pruabi_fltuf");
872 set_conv_libfunc (sfloat_optab, SFmode, DImode, "__pruabi_fltllif");
873 set_conv_libfunc (ufloat_optab, SFmode, DImode, "__pruabi_fltullf");
874
875 /* Long long. */
876 set_optab_libfunc (ashr_optab, DImode, "__pruabi_asrll");
877 set_optab_libfunc (smul_optab, DImode, "__pruabi_mpyll");
878 set_optab_libfunc (ashl_optab, DImode, "__pruabi_lslll");
879 set_optab_libfunc (lshr_optab, DImode, "__pruabi_lsrll");
880
881 set_optab_libfunc (sdiv_optab, SImode, "__pruabi_divi");
882 set_optab_libfunc (udiv_optab, SImode, "__pruabi_divu");
883 set_optab_libfunc (smod_optab, SImode, "__pruabi_remi");
884 set_optab_libfunc (umod_optab, SImode, "__pruabi_remu");
885 set_optab_libfunc (sdivmod_optab, SImode, "__pruabi_divremi");
886 set_optab_libfunc (udivmod_optab, SImode, "__pruabi_divremu");
887 set_optab_libfunc (sdiv_optab, DImode, "__pruabi_divlli");
888 set_optab_libfunc (udiv_optab, DImode, "__pruabi_divull");
889 set_optab_libfunc (smod_optab, DImode, "__pruabi_remlli");
890 set_optab_libfunc (umod_optab, DImode, "__pruabi_remull");
891 set_optab_libfunc (udivmod_optab, DImode, "__pruabi_divremull");
892}
893
894
895/* Emit comparison instruction if necessary, returning the expression
896 that holds the compare result in the proper mode. Return the comparison
897 that should be used in the jump insn. */
898
899rtx
900pru_expand_fp_compare (rtx comparison, machine_mode mode)
901{
902 enum rtx_code code = GET_CODE (comparison);
903 rtx op0 = XEXP (comparison, 0);
904 rtx op1 = XEXP (comparison, 1);
905 rtx cmp;
906 enum rtx_code jump_code = code;
907 machine_mode op_mode = GET_MODE (op0);
908 rtx_insn *insns;
909 rtx libfunc;
910
911 gcc_assert (op_mode == DFmode || op_mode == SFmode);
912
913 /* FP exceptions are not raised by PRU's softfp implementation. So the
914 following transformations are safe. */
915 if (code == UNGE)
916 {
917 code = LT;
918 jump_code = EQ;
919 }
920 else if (code == UNLE)
921 {
922 code = GT;
923 jump_code = EQ;
924 }
925 else
926 jump_code = NE;
927
928 switch (code)
929 {
930 case EQ:
931 libfunc = op_mode == DFmode ? eqdf_libfunc : eqsf_libfunc;
932 break;
933 case NE:
934 libfunc = op_mode == DFmode ? nedf_libfunc : nesf_libfunc;
935 break;
936 case GT:
937 libfunc = op_mode == DFmode ? gtdf_libfunc : gtsf_libfunc;
938 break;
939 case GE:
940 libfunc = op_mode == DFmode ? gedf_libfunc : gesf_libfunc;
941 break;
942 case LT:
943 libfunc = op_mode == DFmode ? ltdf_libfunc : ltsf_libfunc;
944 break;
945 case LE:
946 libfunc = op_mode == DFmode ? ledf_libfunc : lesf_libfunc;
947 break;
948 default:
949 gcc_unreachable ();
950 }
951 start_sequence ();
952
953 cmp = emit_library_call_value (libfunc, 0, LCT_CONST, SImode,
954 op0, op_mode, op1, op_mode);
955 insns = get_insns ();
956 end_sequence ();
957
958 emit_libcall_block (insns, cmp, cmp,
959 gen_rtx_fmt_ee (code, SImode, op0, op1));
960
961 return gen_rtx_fmt_ee (jump_code, mode, cmp, const0_rtx);
962}
963\f
964/* Return the sign bit position for given OP's mode. */
965static int
966sign_bit_position (const rtx op)
967{
968 const int sz = GET_MODE_SIZE (GET_MODE (op));
969
970 return sz * 8 - 1;
971}
972
973/* Output asm code for sign_extend operation. */
974const char *
975pru_output_sign_extend (rtx *operands)
976{
977 static char buf[512];
978 int bufi;
979 const int dst_sz = GET_MODE_SIZE (GET_MODE (operands[0]));
980 const int src_sz = GET_MODE_SIZE (GET_MODE (operands[1]));
981 char ext_start;
982
983 switch (src_sz)
984 {
985 case 1: ext_start = 'y'; break;
986 case 2: ext_start = 'z'; break;
987 default: gcc_unreachable ();
988 }
989
990 gcc_assert (dst_sz > src_sz);
991
992 /* Note that src and dst can be different parts of the same
993 register, e.g. "r7, r7.w1". */
994 bufi = snprintf (buf, sizeof (buf),
995 "mov\t%%0, %%1\n\t" /* Copy AND make positive. */
996 "qbbc\t.+8, %%0, %d\n\t" /* Check sign bit. */
997 "fill\t%%%c0, %d", /* Make negative. */
998 sign_bit_position (operands[1]),
999 ext_start,
1000 dst_sz - src_sz);
1001
1002 gcc_assert (bufi > 0);
1003 gcc_assert ((unsigned int) bufi < sizeof (buf));
1004
1005 return buf;
1006}
1007\f
1008/* Branches and compares. */
1009
1010/* PRU's ALU does not support signed comparison operations. That's why we
1011 emulate them. By first checking the sign bit and handling every possible
1012 operand sign combination, we can simulate signed comparisons in just
1013 5 instructions. See table below.
1014
1015.-------------------.---------------------------------------------------.
1016| Operand sign bit | Mapping the signed comparison to an unsigned one |
1017|---------+---------+------------+------------+------------+------------|
1018| OP1.b31 | OP2.b31 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 |
1019|---------+---------+------------+------------+------------+------------|
1020| 0 | 0 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 |
1021|---------+---------+------------+------------+------------+------------|
1022| 0 | 1 | false | false | true | true |
1023|---------+---------+------------+------------+------------+------------|
1024| 1 | 0 | true | true | false | false |
1025|---------+---------+------------+------------+------------+------------|
1026| 1 | 1 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 |
1027`---------'---------'------------'------------'------------+------------'
1028
1029
1030Given the table above, here is an example for a concrete op:
1031 LT:
1032 qbbc OP1_POS, OP1, 31
1033 OP1_NEG: qbbc BRANCH_TAKEN_LABEL, OP2, 31
1034 OP1_NEG_OP2_NEG: qblt BRANCH_TAKEN_LABEL, OP2, OP1
1035 ; jmp OUT -> can be eliminated because we'll take the
1036 ; following branch. OP2.b31 is guaranteed to be 1
1037 ; by the time we get here.
1038 OP1_POS: qbbs OUT, OP2, 31
1039 OP1_POS_OP2_POS: qblt BRANCH_TAKEN_LABEL, OP2, OP1
1040#if FAR_JUMP
1041 jmp OUT
1042BRANCH_TAKEN_LABEL: jmp REAL_BRANCH_TAKEN_LABEL
1043#endif
1044 OUT:
1045
1046*/
1047
1048/* Output asm code for a signed-compare LT/LE conditional branch. */
1049static const char *
1050pru_output_ltle_signed_cbranch (rtx *operands, bool is_near)
1051{
1052 static char buf[1024];
1053 enum rtx_code code = GET_CODE (operands[0]);
1054 rtx op1;
1055 rtx op2;
1056 const char *cmp_opstr;
1057 int bufi = 0;
1058
1059 op1 = operands[1];
1060 op2 = operands[2];
1061
1062 gcc_assert (GET_CODE (op1) == REG && GET_CODE (op2) == REG);
1063
1064 /* Determine the comparison operators for positive and negative operands. */
1065 if (code == LT)
1066 cmp_opstr = "qblt";
1067 else if (code == LE)
1068 cmp_opstr = "qble";
1069 else
1070 gcc_unreachable ();
1071
1072 if (is_near)
1073 bufi = snprintf (buf, sizeof (buf),
1074 "qbbc\t.+12, %%1, %d\n\t"
1075 "qbbc\t%%l3, %%2, %d\n\t" /* OP1_NEG. */
1076 "%s\t%%l3, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */
1077 "qbbs\t.+8, %%2, %d\n\t" /* OP1_POS. */
1078 "%s\t%%l3, %%2, %%1", /* OP1_POS_OP2_POS. */
1079 sign_bit_position (op1),
1080 sign_bit_position (op2),
1081 cmp_opstr,
1082 sign_bit_position (op2),
1083 cmp_opstr);
1084 else
1085 bufi = snprintf (buf, sizeof (buf),
1086 "qbbc\t.+12, %%1, %d\n\t"
1087 "qbbc\t.+20, %%2, %d\n\t" /* OP1_NEG. */
1088 "%s\t.+16, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */
1089 "qbbs\t.+16, %%2, %d\n\t" /* OP1_POS. */
1090 "%s\t.+8, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */
1091 "jmp\t.+8\n\t" /* jmp OUT. */
1092 "jmp\t%%%%label(%%l3)", /* BRANCH_TAKEN_LABEL. */
1093 sign_bit_position (op1),
1094 sign_bit_position (op2),
1095 cmp_opstr,
1096 sign_bit_position (op2),
1097 cmp_opstr);
1098
1099 gcc_assert (bufi > 0);
1100 gcc_assert ((unsigned int) bufi < sizeof (buf));
1101
1102 return buf;
1103}
1104
1105/* Output asm code for a signed-compare GT/GE conditional branch. */
1106static const char *
1107pru_output_gtge_signed_cbranch (rtx *operands, bool is_near)
1108{
1109 static char buf[1024];
1110 enum rtx_code code = GET_CODE (operands[0]);
1111 rtx op1;
1112 rtx op2;
1113 const char *cmp_opstr;
1114 int bufi = 0;
1115
1116 op1 = operands[1];
1117 op2 = operands[2];
1118
1119 gcc_assert (GET_CODE (op1) == REG && GET_CODE (op2) == REG);
1120
1121 /* Determine the comparison operators for positive and negative operands. */
1122 if (code == GT)
1123 cmp_opstr = "qbgt";
1124 else if (code == GE)
1125 cmp_opstr = "qbge";
1126 else
1127 gcc_unreachable ();
1128
1129 if (is_near)
1130 bufi = snprintf (buf, sizeof (buf),
1131 "qbbs\t.+12, %%1, %d\n\t"
1132 "qbbs\t%%l3, %%2, %d\n\t" /* OP1_POS. */
1133 "%s\t%%l3, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */
1134 "qbbc\t.+8, %%2, %d\n\t" /* OP1_NEG. */
1135 "%s\t%%l3, %%2, %%1", /* OP1_NEG_OP2_NEG. */
1136 sign_bit_position (op1),
1137 sign_bit_position (op2),
1138 cmp_opstr,
1139 sign_bit_position (op2),
1140 cmp_opstr);
1141 else
1142 bufi = snprintf (buf, sizeof (buf),
1143 "qbbs\t.+12, %%1, %d\n\t"
1144 "qbbs\t.+20, %%2, %d\n\t" /* OP1_POS. */
1145 "%s\t.+16, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */
1146 "qbbc\t.+16, %%2, %d\n\t" /* OP1_NEG. */
1147 "%s\t.+8, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */
1148 "jmp\t.+8\n\t" /* jmp OUT. */
1149 "jmp\t%%%%label(%%l3)", /* BRANCH_TAKEN_LABEL. */
1150 sign_bit_position (op1),
1151 sign_bit_position (op2),
1152 cmp_opstr,
1153 sign_bit_position (op2),
1154 cmp_opstr);
1155
1156 gcc_assert (bufi > 0);
1157 gcc_assert ((unsigned int) bufi < sizeof (buf));
1158
1159 return buf;
1160}
1161
1162/* Output asm code for a signed-compare conditional branch.
1163
1164 If IS_NEAR is true, then QBBx instructions may be used for reaching
1165 the destination label. Otherwise JMP is used, at the expense of
1166 increased code size. */
1167const char *
1168pru_output_signed_cbranch (rtx *operands, bool is_near)
1169{
1170 enum rtx_code code = GET_CODE (operands[0]);
1171
1172 if (code == LT || code == LE)
1173 return pru_output_ltle_signed_cbranch (operands, is_near);
1174 else if (code == GT || code == GE)
1175 return pru_output_gtge_signed_cbranch (operands, is_near);
1176 else
1177 gcc_unreachable ();
1178}
1179
1180/* Optimized version of pru_output_signed_cbranch for constant second
1181 operand. */
1182
1183const char *
1184pru_output_signed_cbranch_ubyteop2 (rtx *operands, bool is_near)
1185{
1186 static char buf[1024];
1187 enum rtx_code code = GET_CODE (operands[0]);
1188 int regop_sign_bit_pos = sign_bit_position (operands[1]);
1189 const char *cmp_opstr;
1190 const char *rcmp_opstr;
1191
1192 /* We must swap operands due to PRU's demand OP1 to be the immediate. */
1193 code = swap_condition (code);
1194
1195 /* Determine normal and reversed comparison operators for both positive
1196 operands. This enables us to go completely unsigned.
1197
1198 NOTE: We cannot use the R print modifier because we convert signed
1199 comparison operators to unsigned ones. */
1200 switch (code)
1201 {
1202 case LT: cmp_opstr = "qblt"; rcmp_opstr = "qbge"; break;
1203 case LE: cmp_opstr = "qble"; rcmp_opstr = "qbgt"; break;
1204 case GT: cmp_opstr = "qbgt"; rcmp_opstr = "qble"; break;
1205 case GE: cmp_opstr = "qbge"; rcmp_opstr = "qblt"; break;
1206 default: gcc_unreachable ();
1207 }
1208
1209 /* OP2 is a constant unsigned byte - utilize this info to generate
1210 optimized code. We can "remove half" of the op table above because
1211 we know that OP2.b31 = 0 (remember that 0 <= OP2 <= 255). */
1212 if (code == LT || code == LE)
1213 {
1214 if (is_near)
1215 snprintf (buf, sizeof (buf),
1216 "qbbs\t.+8, %%1, %d\n\t"
1217 "%s\t%%l3, %%1, %%u2",
1218 regop_sign_bit_pos,
1219 cmp_opstr);
1220 else
1221 snprintf (buf, sizeof (buf),
1222 "qbbs\t.+12, %%1, %d\n\t"
1223 "%s\t.+8, %%1, %%u2\n\t"
1224 "jmp\t%%%%label(%%l3)",
1225 regop_sign_bit_pos,
1226 rcmp_opstr);
1227 }
1228 else if (code == GT || code == GE)
1229 {
1230 if (is_near)
1231 snprintf (buf, sizeof (buf),
1232 "qbbs\t%%l3, %%1, %d\n\t"
1233 "%s\t%%l3, %%1, %%u2",
1234 regop_sign_bit_pos,
1235 cmp_opstr);
1236 else
1237 snprintf (buf, sizeof (buf),
1238 "qbbs\t.+8, %%1, %d\n\t"
1239 "%s\t.+8, %%1, %%u2\n\t"
1240 "jmp\t%%%%label(%%l3)",
1241 regop_sign_bit_pos,
1242 rcmp_opstr);
1243 }
1244 else
1245 gcc_unreachable ();
1246
1247 return buf;
1248}
1249
1250/* Optimized version of pru_output_signed_cbranch_ubyteop2 for constant
1251 zero second operand. */
1252
1253const char *
1254pru_output_signed_cbranch_zeroop2 (rtx *operands, bool is_near)
1255{
1256 static char buf[1024];
1257 enum rtx_code code = GET_CODE (operands[0]);
1258 int regop_sign_bit_pos = sign_bit_position (operands[1]);
1259
1260 /* OP2 is a constant zero - utilize this info to simply check the
1261 OP1 sign bit when comparing for LT or GE. */
1262 if (code == LT)
1263 {
1264 if (is_near)
1265 snprintf (buf, sizeof (buf),
1266 "qbbs\t%%l3, %%1, %d\n\t",
1267 regop_sign_bit_pos);
1268 else
1269 snprintf (buf, sizeof (buf),
1270 "qbbc\t.+8, %%1, %d\n\t"
1271 "jmp\t%%%%label(%%l3)",
1272 regop_sign_bit_pos);
1273 }
1274 else if (code == GE)
1275 {
1276 if (is_near)
1277 snprintf (buf, sizeof (buf),
1278 "qbbc\t%%l3, %%1, %d\n\t",
1279 regop_sign_bit_pos);
1280 else
1281 snprintf (buf, sizeof (buf),
1282 "qbbs\t.+8, %%1, %d\n\t"
1283 "jmp\t%%%%label(%%l3)",
1284 regop_sign_bit_pos);
1285 }
1286 else
1287 gcc_unreachable ();
1288
1289 return buf;
1290}
1291
1292/* Addressing Modes. */
1293
1294/* Return true if register REGNO is a valid base register.
1295 STRICT_P is true if REG_OK_STRICT is in effect. */
1296
1297bool
1298pru_regno_ok_for_base_p (int regno, bool strict_p)
1299{
1300 if (!HARD_REGISTER_NUM_P (regno) && !strict_p)
1301 return true;
1302
1303 /* The fake registers will be eliminated to either the stack or
1304 hard frame pointer, both of which are usually valid base registers.
1305 Reload deals with the cases where the eliminated form isn't valid. */
1306 return (GP_REG_P (regno)
1307 || regno == FRAME_POINTER_REGNUM
1308 || regno == ARG_POINTER_REGNUM);
1309}
1310
1311/* Return true if given xbbo constant OFFSET is valid. */
1312static bool
1313pru_valid_const_ubyte_offset (machine_mode mode, HOST_WIDE_INT offset)
1314{
1315 bool valid = UBYTE_INT (offset);
1316
1317 /* Reload can split multi word accesses, so make sure we can address
1318 the second word in a DI. */
1319 if (valid && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode))
1320 valid = UBYTE_INT (offset + GET_MODE_SIZE (mode) - 1);
1321
1322 return valid;
1323}
1324
1325/* Recognize a CTABLE base address. Return CTABLE entry index, or -1 if
1326 base was not found in the pragma-filled pru_ctable. */
1327int
1328pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr)
1329{
1330 unsigned int i;
1331
1332 for (i = 0; i < ARRAY_SIZE (pru_ctable); i++)
1333 {
1334 if (pru_ctable[i].valid && pru_ctable[i].base == caddr)
1335 return i;
1336 }
1337 return -1;
1338}
1339
1340
1341/* Check if the given address can be addressed via CTABLE_BASE + UBYTE_OFFS,
1342 and return the base CTABLE index if possible. */
1343int
1344pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr)
1345{
1346 unsigned int i;
1347
1348 for (i = 0; i < ARRAY_SIZE (pru_ctable); i++)
1349 {
1350 if (pru_ctable[i].valid && IN_RANGE (caddr,
1351 pru_ctable[i].base,
1352 pru_ctable[i].base + 0xff))
1353 return i;
1354 }
1355 return -1;
1356}
1357
1358
1359/* Return the offset from some CTABLE base for this address. */
1360int
1361pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr)
1362{
1363 int i;
1364
1365 i = pru_get_ctable_base_index (caddr);
1366 gcc_assert (i >= 0);
1367
1368 return caddr - pru_ctable[i].base;
1369}
1370
1371/* Return true if the address expression formed by BASE + OFFSET is
1372 valid.
1373
1374 Note that the following address is not handled here:
1375 base CTABLE constant base + UBYTE constant offset
1376 The constants will be folded. The ctable_addr_operand predicate will take
1377 care of the validation. The CTABLE base+offset split will happen during
1378 operand printing. */
1379static bool
1380pru_valid_addr_expr_p (machine_mode mode, rtx base, rtx offset, bool strict_p)
1381{
1382 if (!strict_p && GET_CODE (base) == SUBREG)
1383 base = SUBREG_REG (base);
1384 if (!strict_p && GET_CODE (offset) == SUBREG)
1385 offset = SUBREG_REG (offset);
1386
1387 if (REG_P (base)
1388 && pru_regno_ok_for_base_p (REGNO (base), strict_p)
1389 && ((CONST_INT_P (offset)
1390 && pru_valid_const_ubyte_offset (mode, INTVAL (offset)))
1391 || (REG_P (offset)
1392 && pru_regno_ok_for_index_p (REGNO (offset), strict_p))))
1393 /* base register + register offset
1394 * OR base register + UBYTE constant offset. */
1395 return true;
1396 else if (REG_P (base)
1397 && pru_regno_ok_for_index_p (REGNO (base), strict_p)
1398 && ctable_base_operand (offset, VOIDmode))
1399 /* base CTABLE constant base + register offset
1400 * Note: GCC always puts the register as a first operand of PLUS. */
1401 return true;
1402 else
1403 return false;
1404}
1405
8bafc964
DD
1406/* Return register number (either for r30 or r31) which maps to the
1407 corresponding symbol OP's name in the __regio_symbol address namespace.
1408
1409 If no mapping can be established (i.e. symbol name is invalid), then
1410 return -1. */
1411int pru_symref2ioregno (rtx op)
1412{
1413 if (!SYMBOL_REF_P (op))
1414 return -1;
1415
1416 const char *name = XSTR (op, 0);
1417 if (!strcmp (name, "__R30"))
1418 return R30_REGNUM;
1419 else if (!strcmp (name, "__R31"))
1420 return R31_REGNUM;
1421 else
1422 return -1;
1423}
1424
1425/* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P. */
8d2af3a2 1426static bool
8bafc964
DD
1427pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
1428 bool strict_p, addr_space_t as)
8d2af3a2 1429{
8bafc964
DD
1430 if (as == ADDR_SPACE_REGIO)
1431 {
1432 /* Address space constraints for __regio_symbol have been checked in
1433 TARGET_INSERT_ATTRIBUTES, and some more checks will be done
1434 during RTL expansion of "mov<mode>". */
1435 return true;
1436 }
1437 else if (as != ADDR_SPACE_GENERIC)
1438 {
1439 gcc_unreachable ();
1440 }
1441
8d2af3a2
DD
1442 switch (GET_CODE (operand))
1443 {
1444 /* Direct. */
1445 case SYMBOL_REF:
1446 case LABEL_REF:
1447 case CONST:
1448 case CONST_WIDE_INT:
1449 return false;
1450
1451 case CONST_INT:
1452 return ctable_addr_operand (operand, VOIDmode);
1453
1454 /* Register indirect. */
1455 case REG:
1456 return pru_regno_ok_for_base_p (REGNO (operand), strict_p);
1457
1458 /* Register indirect with displacement. */
1459 case PLUS:
1460 {
1461 rtx op0 = XEXP (operand, 0);
1462 rtx op1 = XEXP (operand, 1);
1463
1464 return pru_valid_addr_expr_p (mode, op0, op1, strict_p);
1465 }
1466
1467 default:
1468 break;
1469 }
1470 return false;
1471}
1472\f
1473/* Output assembly language related definitions. */
1474
1475/* Implement TARGET_ASM_CONSTRUCTOR. */
1476static void
1477pru_elf_asm_constructor (rtx symbol, int priority)
1478{
1479 char buf[23];
1480 section *s;
1481
1482 if (priority == DEFAULT_INIT_PRIORITY)
1483 snprintf (buf, sizeof (buf), ".init_array");
1484 else
1485 {
1486 /* While priority is known to be in range [0, 65535], so 18 bytes
1487 would be enough, the compiler might not know that. To avoid
1488 -Wformat-truncation false positive, use a larger size. */
1489 snprintf (buf, sizeof (buf), ".init_array.%.5u", priority);
1490 }
1491 s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL);
1492 switch_to_section (s);
1493 assemble_aligned_integer (INIT_ARRAY_ENTRY_BYTES, symbol);
1494}
1495
1496/* Implement TARGET_ASM_DESTRUCTOR. */
1497static void
1498pru_elf_asm_destructor (rtx symbol, int priority)
1499{
1500 char buf[23];
1501 section *s;
1502
1503 if (priority == DEFAULT_INIT_PRIORITY)
1504 snprintf (buf, sizeof (buf), ".fini_array");
1505 else
1506 {
1507 /* While priority is known to be in range [0, 65535], so 18 bytes
1508 would be enough, the compiler might not know that. To avoid
1509 -Wformat-truncation false positive, use a larger size. */
1510 snprintf (buf, sizeof (buf), ".fini_array.%.5u", priority);
1511 }
1512 s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL);
1513 switch_to_section (s);
1514 assemble_aligned_integer (INIT_ARRAY_ENTRY_BYTES, symbol);
1515}
1516
1517/* Map rtx_code to unsigned PRU branch op suffix. Callers must
1518 handle sign comparison themselves for signed operations. */
1519static const char *
1520pru_comparison_str (enum rtx_code cond)
1521{
1522 switch (cond)
1523 {
1524 case NE: return "ne";
1525 case EQ: return "eq";
1526 case GEU: return "ge";
1527 case GTU: return "gt";
1528 case LEU: return "le";
1529 case LTU: return "lt";
1530 default: gcc_unreachable ();
1531 }
1532}
1533
1534/* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
1535 the bit representation of X by "casting" it to CONST_INT. */
1536
1537static rtx
1538pru_to_int_mode (rtx x)
1539{
1540 machine_mode mode = GET_MODE (x);
1541
1542 return VOIDmode == mode
1543 ? x
1544 : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
1545}
1546
1547/* Translate between the MachineDescription notion
1548 of 8-bit consecutive registers, to the PRU
1549 assembler syntax of REGWORD[.SUBREG]. */
1550static const char *
1551pru_asm_regname (rtx op)
1552{
1553 static char canon_reg_names[3][LAST_GP_REGNUM][8];
1554 int speci, regi;
1555
1556 gcc_assert (REG_P (op));
1557
1558 if (!canon_reg_names[0][0][0])
1559 {
1560 for (regi = 0; regi < LAST_GP_REGNUM; regi++)
1561 for (speci = 0; speci < 3; speci++)
1562 {
1563 const int sz = (speci == 0) ? 1 : ((speci == 1) ? 2 : 4);
1564 if ((regi + sz) > (32 * 4))
1565 continue; /* Invalid entry. */
1566
1567 /* Construct the lookup table. */
1568 const char *suffix = "";
1569
1570 switch ((sz << 8) | (regi % 4))
1571 {
1572 case (1 << 8) | 0: suffix = ".b0"; break;
1573 case (1 << 8) | 1: suffix = ".b1"; break;
1574 case (1 << 8) | 2: suffix = ".b2"; break;
1575 case (1 << 8) | 3: suffix = ".b3"; break;
1576 case (2 << 8) | 0: suffix = ".w0"; break;
1577 case (2 << 8) | 1: suffix = ".w1"; break;
1578 case (2 << 8) | 2: suffix = ".w2"; break;
1579 case (4 << 8) | 0: suffix = ""; break;
1580 default:
1581 /* Invalid entry. */
1582 continue;
1583 }
1584 sprintf (&canon_reg_names[speci][regi][0],
1585 "r%d%s", regi / 4, suffix);
1586 }
1587 }
1588
1589 switch (GET_MODE_SIZE (GET_MODE (op)))
1590 {
1591 case 1: speci = 0; break;
1592 case 2: speci = 1; break;
1593 case 4: speci = 2; break;
1594 case 8: speci = 2; break; /* Existing GCC test cases are not using %F. */
1595 default: gcc_unreachable ();
1596 }
1597 regi = REGNO (op);
1598 gcc_assert (regi < LAST_GP_REGNUM);
1599 gcc_assert (canon_reg_names[speci][regi][0]);
1600
1601 return &canon_reg_names[speci][regi][0];
1602}
1603
1604/* Print the operand OP to file stream FILE modified by LETTER.
1605 LETTER can be one of:
1606
1607 b: prints the register byte start (used by LBBO/SBBO).
1608 B: prints 'c' or 'b' for CTABLE or REG base in a memory address.
1609 F: Full 32-bit register.
1610 H: Higher 16-bits of a const_int operand.
1611 L: Lower 16-bits of a const_int operand.
1612 N: prints next 32-bit register (upper 32bits of a 64bit REG couple).
1613 P: prints swapped condition.
1614 Q: prints swapped and reversed condition.
1615 R: prints reversed condition.
1616 S: print operand mode size (but do not print the operand itself).
1617 T: print exact_log2 () for const_int operands.
1618 u: print QI constant integer as unsigned. No transformation for regs.
1619 V: print exact_log2 () of negated const_int operands.
1620 w: Lower 32-bits of a const_int operand.
1621 W: Upper 32-bits of a const_int operand.
1622 y: print the next 8-bit register (regardless of op size).
1623 z: print the second next 8-bit register (regardless of op size).
1624*/
1625static void
1626pru_print_operand (FILE *file, rtx op, int letter)
1627{
1628 switch (letter)
1629 {
1630 case 'S':
1631 fprintf (file, "%d", GET_MODE_SIZE (GET_MODE (op)));
1632 return;
1633
1634 default:
1635 break;
1636 }
1637
1638 if (comparison_operator (op, VOIDmode))
1639 {
1640 enum rtx_code cond = GET_CODE (op);
1641 gcc_assert (!pru_signed_cmp_operator (op, VOIDmode));
1642
1643 switch (letter)
1644 {
1645 case 0:
1646 fprintf (file, "%s", pru_comparison_str (cond));
1647 return;
1648 case 'P':
1649 fprintf (file, "%s", pru_comparison_str (swap_condition (cond)));
1650 return;
1651 case 'Q':
1652 cond = swap_condition (cond);
3d1ca857 1653 /* Fall through. */
8d2af3a2
DD
1654 case 'R':
1655 fprintf (file, "%s", pru_comparison_str (reverse_condition (cond)));
1656 return;
1657 }
1658 }
1659
1660 switch (GET_CODE (op))
1661 {
1662 case REG:
1663 if (letter == 0 || letter == 'u')
1664 {
1665 fprintf (file, "%s", pru_asm_regname (op));
1666 return;
1667 }
1668 else if (letter == 'b')
1669 {
1670 if (REGNO (op) > LAST_NONIO_GP_REGNUM)
1671 {
1672 output_operand_lossage ("I/O register operand for '%%%c'",
1673 letter);
1674 return;
1675 }
1676 fprintf (file, "r%d.b%d", REGNO (op) / 4, REGNO (op) % 4);
1677 return;
1678 }
1679 else if (letter == 'F' || letter == 'N')
1680 {
1681 if (REGNO (op) > LAST_NONIO_GP_REGNUM - 1)
1682 {
1683 output_operand_lossage ("I/O register operand for '%%%c'",
1684 letter);
1685 return;
1686 }
1687 if (REGNO (op) % 4 != 0)
1688 {
1689 output_operand_lossage ("non 32 bit register operand for '%%%c'",
1690 letter);
1691 return;
1692 }
1693 fprintf (file, "r%d", REGNO (op) / 4 + (letter == 'N' ? 1 : 0));
1694 return;
1695 }
1696 else if (letter == 'y')
1697 {
1698 if (REGNO (op) > LAST_NONIO_GP_REGNUM - 1)
1699 {
1700 output_operand_lossage ("invalid operand for '%%%c'", letter);
1701 return;
1702 }
1703 fprintf (file, "%s", reg_names[REGNO (op) + 1]);
1704 return;
1705 }
1706 else if (letter == 'z')
1707 {
1708 if (REGNO (op) > LAST_NONIO_GP_REGNUM - 2)
1709 {
1710 output_operand_lossage ("invalid operand for '%%%c'", letter);
1711 return;
1712 }
1713 fprintf (file, "%s", reg_names[REGNO (op) + 2]);
1714 return;
1715 }
1716 break;
1717
1718 case CONST_INT:
1719 if (letter == 'H')
1720 {
1721 HOST_WIDE_INT val = INTVAL (op);
1722 val = (val >> 16) & 0xFFFF;
1723 output_addr_const (file, gen_int_mode (val, SImode));
1724 return;
1725 }
1726 else if (letter == 'L')
1727 {
1728 HOST_WIDE_INT val = INTVAL (op);
1729 val &= 0xFFFF;
1730 output_addr_const (file, gen_int_mode (val, SImode));
1731 return;
1732 }
1733 else if (letter == 'T')
1734 {
1735 /* The predicate should have already validated the 1-high-bit
1736 requirement. Use CTZ here to deal with constant's sign
1737 extension. */
1738 HOST_WIDE_INT val = wi::ctz (INTVAL (op));
1739 if (val < 0 || val > 31)
1740 {
1741 output_operand_lossage ("invalid operand for '%%%c'", letter);
1742 return;
1743 }
1744 output_addr_const (file, gen_int_mode (val, SImode));
1745 return;
1746 }
1747 else if (letter == 'V')
1748 {
1749 HOST_WIDE_INT val = wi::ctz (~INTVAL (op));
1750 if (val < 0 || val > 31)
1751 {
1752 output_operand_lossage ("invalid operand for '%%%c'", letter);
1753 return;
1754 }
1755 output_addr_const (file, gen_int_mode (val, SImode));
1756 return;
1757 }
1758 else if (letter == 'w')
1759 {
1760 HOST_WIDE_INT val = INTVAL (op) & 0xffffffff;
1761 output_addr_const (file, gen_int_mode (val, SImode));
1762 return;
1763 }
1764 else if (letter == 'W')
1765 {
1766 HOST_WIDE_INT val = (INTVAL (op) >> 32) & 0xffffffff;
1767 output_addr_const (file, gen_int_mode (val, SImode));
1768 return;
1769 }
1770 else if (letter == 'u')
1771 {
1772 /* Workaround GCC's representation of QI constants in sign-extended
1773 form, and PRU's assembler insistence on unsigned constant
1774 integers. See the notes about O constraint. */
1775 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) & 0xff);
1776 return;
1777 }
1778 /* Else, fall through. */
1779
1780 case CONST:
1781 case LABEL_REF:
1782 case SYMBOL_REF:
1783 if (letter == 0)
1784 {
1785 output_addr_const (file, op);
1786 return;
1787 }
1788 break;
1789
1790 case CONST_FIXED:
1791 {
1792 HOST_WIDE_INT ival = INTVAL (pru_to_int_mode (op));
1793 if (letter != 0)
1794 output_operand_lossage ("unsupported code '%c' for fixed-point:",
1795 letter);
1796 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
1797 return;
1798 }
1799 break;
1800
1801 case CONST_DOUBLE:
1802 if (letter == 0)
1803 {
1804 long val;
1805
1806 if (GET_MODE (op) != SFmode)
1807 {
1808 output_operand_lossage ("double constants not supported");
1809 return;
1810 }
1811 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), val);
1812 fprintf (file, "0x%lx", val);
1813 return;
1814 }
1815 else if (letter == 'w' || letter == 'W')
1816 {
1817 long t[2];
1818 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), t);
1819 fprintf (file, "0x%lx", t[letter == 'w' ? 0 : 1]);
1820 return;
1821 }
1822 else
1823 {
1824 output_operand_lossage ("invalid operand for '%%%c'", letter);
1825 return;
1826 }
1827 break;
1828
1829 case SUBREG:
1830 /* Subregs should not appear at so late stage. */
1831 gcc_unreachable ();
1832 break;
1833
1834 case MEM:
1835 if (letter == 0)
1836 {
1837 output_address (VOIDmode, op);
1838 return;
1839 }
1840 else if (letter == 'B')
1841 {
1842 rtx base = XEXP (op, 0);
1843 if (GET_CODE (base) == PLUS)
1844 {
1845 rtx op0 = XEXP (base, 0);
1846 rtx op1 = XEXP (base, 1);
1847
1848 /* PLUS cannot have two constant operands, so first one
1849 of them must be a REG, hence we must check for an
1850 exact base address. */
1851 if (ctable_base_operand (op1, VOIDmode))
1852 {
1853 fprintf (file, "c");
1854 return;
1855 }
1856 else if (REG_P (op0))
1857 {
1858 fprintf (file, "b");
1859 return;
1860 }
1861 else
1862 gcc_unreachable ();
1863 }
1864 else if (REG_P (base))
1865 {
1866 fprintf (file, "b");
1867 return;
1868 }
1869 else if (ctable_addr_operand (base, VOIDmode))
1870 {
1871 fprintf (file, "c");
1872 return;
1873 }
1874 else
1875 gcc_unreachable ();
1876 }
1877 break;
1878
1879 case CODE_LABEL:
1880 if (letter == 0)
1881 {
1882 output_addr_const (file, op);
1883 return;
1884 }
1885 break;
1886
1887 default:
1888 break;
1889 }
1890
1891 output_operand_lossage ("unsupported operand %s for code '%c'",
1892 GET_RTX_NAME (GET_CODE (op)), letter);
1893}
1894
1895/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
1896static void
1897pru_print_operand_address (FILE *file, machine_mode mode, rtx op)
1898{
1899 if (CONSTANT_ADDRESS_P (op) && text_segment_operand (op, VOIDmode))
1900 {
1901 output_operand_lossage ("unexpected text address:");
1902 return;
1903 }
1904
1905 switch (GET_CODE (op))
1906 {
1907 case CONST:
1908 case LABEL_REF:
1909 case CONST_WIDE_INT:
1910 case SYMBOL_REF:
1911 break;
1912
1913 case CONST_INT:
1914 {
1915 unsigned HOST_WIDE_INT caddr = INTVAL (op);
1916 int base = pru_get_ctable_base_index (caddr);
1917 int offs = pru_get_ctable_base_offset (caddr);
1918 if (base < 0)
1919 {
1920 output_operand_lossage ("unsupported constant address:");
1921 return;
1922 }
1923 fprintf (file, "%d, %d", base, offs);
1924 return;
1925 }
1926 break;
1927
1928 case PLUS:
1929 {
1930 int base;
1931 rtx op0 = XEXP (op, 0);
1932 rtx op1 = XEXP (op, 1);
1933
1934 if (REG_P (op0) && CONST_INT_P (op1)
1935 && pru_get_ctable_exact_base_index (INTVAL (op1)) >= 0)
1936 {
1937 base = pru_get_ctable_exact_base_index (INTVAL (op1));
1938 fprintf (file, "%d, %s", base, pru_asm_regname (op0));
1939 return;
1940 }
1941 else if (REG_P (op1) && CONST_INT_P (op0)
1942 && pru_get_ctable_exact_base_index (INTVAL (op0)) >= 0)
1943 {
1944 /* Not a valid RTL. */
1945 gcc_unreachable ();
1946 }
1947 else if (REG_P (op0) && CONSTANT_P (op1))
1948 {
1949 fprintf (file, "%s, ", pru_asm_regname (op0));
1950 output_addr_const (file, op1);
1951 return;
1952 }
1953 else if (REG_P (op1) && CONSTANT_P (op0))
1954 {
1955 /* Not a valid RTL. */
1956 gcc_unreachable ();
1957 }
1958 else if (REG_P (op1) && REG_P (op0))
1959 {
1960 fprintf (file, "%s, %s", pru_asm_regname (op0),
1961 pru_asm_regname (op1));
1962 return;
1963 }
1964 }
1965 break;
1966
1967 case REG:
1968 fprintf (file, "%s, 0", pru_asm_regname (op));
1969 return;
1970
1971 case MEM:
1972 {
1973 rtx base = XEXP (op, 0);
1974 pru_print_operand_address (file, mode, base);
1975 return;
1976 }
1977 default:
1978 break;
1979 }
1980
1981 output_operand_lossage ("unsupported memory expression:");
1982}
1983
1984/* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
1985static void
1986pru_asm_function_prologue (FILE *file)
1987{
1988 if (flag_verbose_asm || flag_debug_asm)
1989 pru_dump_frame_layout (file);
1990}
1991
1992/* Implement `TARGET_ASM_INTEGER'.
1993 Target hook for assembling integer objects. PRU version needs
1994 special handling for references to pmem. Code copied from AVR. */
1995
1996static bool
1997pru_assemble_integer (rtx x, unsigned int size, int aligned_p)
1998{
1999 if (size == POINTER_SIZE / BITS_PER_UNIT
2000 && aligned_p
2001 && text_segment_operand (x, VOIDmode))
2002 {
2003 fputs ("\t.4byte\t%pmem(", asm_out_file);
2004 output_addr_const (asm_out_file, x);
2005 fputs (")\n", asm_out_file);
2006
2007 return true;
2008 }
2009 else if (size == INIT_ARRAY_ENTRY_BYTES
2010 && aligned_p
2011 && text_segment_operand (x, VOIDmode))
2012 {
2013 fputs ("\t.2byte\t%pmem(", asm_out_file);
2014 output_addr_const (asm_out_file, x);
2015 fputs (")\n", asm_out_file);
2016
2017 return true;
2018 }
2019 else
2020 {
2021 return default_assemble_integer (x, size, aligned_p);
2022 }
2023}
2024
2025/* Implement TARGET_ASM_FILE_START. */
2026
2027static void
2028pru_file_start (void)
2029{
2030 default_file_start ();
2031
2032 /* Compiler will take care of placing %label, so there is no
2033 need to confuse users with this warning. */
2034 fprintf (asm_out_file, "\t.set no_warn_regname_label\n");
2035}
8bafc964
DD
2036
2037/* Scan type TYP for pointer references to address space other than
2038 ADDR_SPACE_GENERIC. Return true if such reference is found.
2039 Much of this code was taken from the avr port. */
2040
2041static bool
2042pru_nongeneric_pointer_addrspace (tree typ)
2043{
2044 while (ARRAY_TYPE == TREE_CODE (typ))
2045 typ = TREE_TYPE (typ);
2046
2047 if (POINTER_TYPE_P (typ))
2048 {
2049 addr_space_t as;
2050 tree target = TREE_TYPE (typ);
2051
2052 /* Pointer to function: Test the function's return type. */
2053 if (FUNCTION_TYPE == TREE_CODE (target))
2054 return pru_nongeneric_pointer_addrspace (TREE_TYPE (target));
2055
2056 /* "Ordinary" pointers... */
2057
2058 while (TREE_CODE (target) == ARRAY_TYPE)
2059 target = TREE_TYPE (target);
2060
2061 as = TYPE_ADDR_SPACE (target);
2062
2063 if (!ADDR_SPACE_GENERIC_P (as))
2064 return true;
2065
2066 /* Scan pointer's target type. */
2067 return pru_nongeneric_pointer_addrspace (target);
2068 }
2069
2070 return false;
2071}
2072
2073/* Implement `TARGET_INSERT_ATTRIBUTES'. For PRU it's used as a hook to
2074 provide better diagnostics for some invalid usages of the __regio_symbol
2075 address space.
2076
2077 Any escapes of the following checks are supposed to be caught
2078 during the "mov<mode>" pattern expansion. */
2079
2080static void
2081pru_insert_attributes (tree node, tree *attributes ATTRIBUTE_UNUSED)
2082{
2083
2084 /* Validate __regio_symbol variable declarations. */
2085 if (VAR_P (node))
2086 {
2087 const char *name = DECL_NAME (node)
2088 ? IDENTIFIER_POINTER (DECL_NAME (node))
2089 : "<unknown>";
2090 tree typ = TREE_TYPE (node);
2091 addr_space_t as = TYPE_ADDR_SPACE (typ);
2092
2093 if (as == ADDR_SPACE_GENERIC)
2094 return;
2095
2096 if (AGGREGATE_TYPE_P (typ))
2097 {
2098 error ("aggregate types are prohibited in "
2099 "%<__regio_symbol%> address space");
2100 /* Don't bother anymore. Below checks would pile
2101 meaningless errors, which would confuse user. */
2102 return;
2103 }
2104 if (DECL_INITIAL (node) != NULL_TREE)
2105 error ("variables in %<__regio_symbol%> address space "
2106 "cannot have initial value");
2107 if (DECL_REGISTER (node))
2108 error ("variables in %<__regio_symbol%> address space "
2109 "cannot be declared %<register%>");
2110 if (!TYPE_VOLATILE (typ))
2111 error ("variables in %<__regio_symbol%> address space "
2112 "must be declared %<volatile%>");
2113 if (!DECL_EXTERNAL (node))
2114 error ("variables in %<__regio_symbol%> address space "
2115 "must be declared %<extern%>");
2116 if (TYPE_MODE (typ) != SImode)
2117 error ("only 32-bit access is supported "
2118 "for %<__regio_symbol%> address space");
2119 if (strcmp (name, "__R30") != 0 && strcmp (name, "__R31") != 0)
2120 error ("register name %<%s%> not recognized "
2121 "in %<__regio_symbol%> address space", name);
2122 }
2123
2124 tree typ = NULL_TREE;
2125
2126 switch (TREE_CODE (node))
2127 {
2128 case FUNCTION_DECL:
2129 typ = TREE_TYPE (TREE_TYPE (node));
2130 break;
2131 case TYPE_DECL:
2132 case RESULT_DECL:
2133 case VAR_DECL:
2134 case FIELD_DECL:
2135 case PARM_DECL:
2136 typ = TREE_TYPE (node);
2137 break;
2138 case POINTER_TYPE:
2139 typ = node;
2140 break;
2141 default:
2142 break;
2143 }
2144 if (typ != NULL_TREE && pru_nongeneric_pointer_addrspace (typ))
2145 error ("pointers to %<__regio_symbol%> address space are prohibited");
2146}
8d2af3a2
DD
2147\f
2148/* Function argument related. */
2149
2150/* Return the number of bytes needed for storing an argument with
2151 the given MODE and TYPE. */
2152static int
2153pru_function_arg_size (machine_mode mode, const_tree type)
2154{
2155 HOST_WIDE_INT param_size;
2156
2157 if (mode == BLKmode)
2158 param_size = int_size_in_bytes (type);
2159 else
2160 param_size = GET_MODE_SIZE (mode);
2161
2162 /* Convert to words (round up). */
2163 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2164 gcc_assert (param_size >= 0);
2165
2166 return param_size;
2167}
2168
2169/* Check if argument with the given size must be
2170 passed/returned in a register.
2171
2172 Reference:
2173 https://e2e.ti.com/support/development_tools/compiler/f/343/p/650176/2393029
2174
2175 Arguments other than 8/16/24/32/64bits are passed on stack. */
2176static bool
2177pru_arg_in_reg_bysize (size_t sz)
2178{
2179 return sz == 1 || sz == 2 || sz == 3 || sz == 4 || sz == 8;
2180}
2181
2182/* Helper function to get the starting storage HW register for an argument,
2183 or -1 if it must be passed on stack. The cum_v state is not changed. */
2184static int
2185pru_function_arg_regi (cumulative_args_t cum_v,
2186 machine_mode mode, const_tree type,
2187 bool named)
2188{
2189 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2190 size_t argsize = pru_function_arg_size (mode, type);
2191 size_t i, bi;
2192 int regi = -1;
2193
2194 if (!pru_arg_in_reg_bysize (argsize))
2195 return -1;
2196
2197 if (!named)
2198 return -1;
2199
2200 /* Find the first available slot that fits. Yes, that's the PRU ABI. */
2201 for (i = 0; regi < 0 && i < ARRAY_SIZE (cum->regs_used); i++)
2202 {
2203 /* VLAs and vector types are not defined in the PRU ABI. Let's
2204 handle them the same as their same-sized counterparts. This way
2205 we do not need to treat BLKmode differently, and need only to check
2206 the size. */
2207 gcc_assert (argsize == 1 || argsize == 2 || argsize == 3
2208 || argsize == 4 || argsize == 8);
2209
2210 /* Ensure SI and DI arguments are stored in full registers only. */
2211 if ((argsize >= 4) && (i % 4) != 0)
2212 continue;
2213
2214 /* Structures with size 24 bits are passed starting at a full
2215 register boundary. */
2216 if (argsize == 3 && (i % 4) != 0)
2217 continue;
2218
2219 /* rX.w0/w1/w2 are OK. But avoid spreading the second byte
2220 into a different full register. */
2221 if (argsize == 2 && (i % 4) == 3)
2222 continue;
2223
2224 for (bi = 0;
2225 bi < argsize && (bi + i) < ARRAY_SIZE (cum->regs_used);
2226 bi++)
2227 {
2228 if (cum->regs_used[bi + i])
2229 break;
2230 }
2231 if (bi == argsize)
2232 regi = FIRST_ARG_REGNUM + i;
2233 }
2234
2235 return regi;
2236}
2237
2238/* Mark CUM_V that a function argument will occupy HW register slot starting
2239 at REGI. The number of consecutive 8-bit HW registers marked as occupied
2240 depends on the MODE and TYPE of the argument. */
2241static void
2242pru_function_arg_regi_mark_slot (int regi,
2243 cumulative_args_t cum_v,
2244 machine_mode mode, const_tree type,
2245 bool named)
2246{
2247 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2248 HOST_WIDE_INT param_size = pru_function_arg_size (mode, type);
2249
2250 gcc_assert (named);
2251
2252 /* Mark all byte sub-registers occupied by argument as used. */
2253 while (param_size--)
2254 {
2255 gcc_assert (regi >= FIRST_ARG_REGNUM && regi <= LAST_ARG_REGNUM);
2256 gcc_assert (!cum->regs_used[regi - FIRST_ARG_REGNUM]);
2257 cum->regs_used[regi - FIRST_ARG_REGNUM] = true;
2258 regi++;
2259 }
2260}
2261
2262/* Define where to put the arguments to a function. Value is zero to
2263 push the argument on the stack, or a hard register in which to
2264 store the argument.
2265
8d2af3a2
DD
2266 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2267 the preceding args and about the function being called.
6783fdb7 2268 ARG is a description of the argument. */
8d2af3a2
DD
2269
2270static rtx
6783fdb7 2271pru_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
8d2af3a2
DD
2272{
2273 rtx return_rtx = NULL_RTX;
6783fdb7 2274 int regi = pru_function_arg_regi (cum_v, arg.mode, arg.type, arg.named);
8d2af3a2
DD
2275
2276 if (regi >= 0)
6783fdb7 2277 return_rtx = gen_rtx_REG (arg.mode, regi);
8d2af3a2
DD
2278
2279 return return_rtx;
2280}
2281
2282/* Implement TARGET_ARG_PARTIAL_BYTES. PRU never splits any arguments
2283 between registers and memory, so we can return 0. */
2284
2285static int
a7c81bc1 2286pru_arg_partial_bytes (cumulative_args_t, const function_arg_info &)
8d2af3a2
DD
2287{
2288 return 0;
2289}
2290
6930c98c 2291/* Update the data in CUM to advance over argument ARG. */
8d2af3a2
DD
2292
2293static void
6930c98c
RS
2294pru_function_arg_advance (cumulative_args_t cum_v,
2295 const function_arg_info &arg)
8d2af3a2 2296{
6930c98c 2297 int regi = pru_function_arg_regi (cum_v, arg.mode, arg.type, arg.named);
8d2af3a2
DD
2298
2299 if (regi >= 0)
6930c98c
RS
2300 pru_function_arg_regi_mark_slot (regi, cum_v, arg.mode,
2301 arg.type, arg.named);
8d2af3a2
DD
2302}
2303
2304/* Implement TARGET_FUNCTION_VALUE. */
2305static rtx
2306pru_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2307 bool outgoing ATTRIBUTE_UNUSED)
2308{
2309 return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNUM);
2310}
2311
2312/* Implement TARGET_LIBCALL_VALUE. */
2313static rtx
2314pru_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2315{
2316 return gen_rtx_REG (mode, FIRST_RETVAL_REGNUM);
2317}
2318
2319/* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2320static bool
2321pru_function_value_regno_p (const unsigned int regno)
2322{
2323 return regno == FIRST_RETVAL_REGNUM;
2324}
2325
2326/* Implement TARGET_RETURN_IN_MEMORY. */
2327bool
2328pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2329{
2330 bool in_memory = (!pru_arg_in_reg_bysize (int_size_in_bytes (type))
2331 || int_size_in_bytes (type) == -1);
2332
2333 return in_memory;
2334}
2335\f
2336/* Implement TARGET_CAN_USE_DOLOOP_P. */
2337
2338static bool
2339pru_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
2340 unsigned int loop_depth, bool)
2341{
2342 /* Considering limitations in the hardware, only use doloop
2343 for innermost loops which must be entered from the top. */
2344 if (loop_depth > 1)
2345 return false;
2346 /* PRU internal loop counter is 16bits wide. Remember that iterations_max
2347 holds the maximum number of loop latch executions, while PRU loop
2348 instruction needs the count of loop body executions. */
2349 if (iterations_max == 0 || wi::geu_p (iterations_max, 0xffff))
2350 return false;
2351
2352 return true;
2353}
2354
2355/* NULL if INSN insn is valid within a low-overhead loop.
2356 Otherwise return why doloop cannot be applied. */
2357
2358static const char *
2359pru_invalid_within_doloop (const rtx_insn *insn)
2360{
2361 if (CALL_P (insn))
2362 return "Function call in the loop.";
2363
2364 if (JUMP_P (insn) && INSN_CODE (insn) == CODE_FOR_return)
2365 return "Return from a call instruction in the loop.";
2366
2367 if (NONDEBUG_INSN_P (insn)
2368 && INSN_CODE (insn) < 0
2369 && (GET_CODE (PATTERN (insn)) == ASM_INPUT
2370 || asm_noperands (PATTERN (insn)) >= 0))
2371 return "Loop contains asm statement.";
2372
2373 return NULL;
2374}
2375
2376
2377/* Figure out where to put LABEL, which is the label for a repeat loop.
2378 The loop ends just before LAST_INSN. If SHARED, insns other than the
2379 "repeat" might use LABEL to jump to the loop's continuation point.
2380
2381 Return the last instruction in the adjusted loop. */
2382
2383static rtx_insn *
2384pru_insert_loop_label_last (rtx_insn *last_insn, rtx_code_label *label,
2385 bool shared)
2386{
2387 rtx_insn *next, *prev;
2388 int count = 0, code, icode;
2389
2390 if (dump_file)
2391 fprintf (dump_file, "considering end of repeat loop at insn %d\n",
2392 INSN_UID (last_insn));
2393
2394 /* Set PREV to the last insn in the loop. */
2395 prev = PREV_INSN (last_insn);
2396
2397 /* Set NEXT to the next insn after the loop label. */
2398 next = last_insn;
2399 if (!shared)
2400 while (prev != 0)
2401 {
2402 code = GET_CODE (prev);
2403 if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER)
2404 break;
2405
2406 if (INSN_P (prev))
2407 {
2408 if (GET_CODE (PATTERN (prev)) == SEQUENCE)
2409 prev = as_a <rtx_insn *> (XVECEXP (PATTERN (prev), 0, 1));
2410
2411 /* Other insns that should not be in the last two opcodes. */
2412 icode = recog_memoized (prev);
2413 if (icode < 0
2414 || icode == CODE_FOR_pruloophi
2415 || icode == CODE_FOR_pruloopsi)
2416 break;
2417
2418 count++;
2419 next = prev;
2420 if (dump_file)
2421 print_rtl_single (dump_file, next);
2422 if (count == 2)
2423 break;
2424 }
2425 prev = PREV_INSN (prev);
2426 }
2427
2428 /* Insert the nops. */
2429 if (dump_file && count < 2)
2430 fprintf (dump_file, "Adding %d nop%s inside loop\n\n",
2431 2 - count, count == 1 ? "" : "s");
2432
2433 for (; count < 2; count++)
2434 emit_insn_before (gen_nop (), last_insn);
2435
2436 /* Insert the label. */
2437 emit_label_before (label, last_insn);
2438
2439 return last_insn;
2440}
2441
2442/* If IS_END is false, expand a canonical doloop_begin RTL into the
2443 PRU-specific doloop_begin_internal. Otherwise expand doloop_end to
2444 doloop_end_internal. */
2445void
2446pru_emit_doloop (rtx *operands, int is_end)
2447{
2448 rtx tag;
2449
2450 if (cfun->machine->doloop_tags == 0
2451 || cfun->machine->doloop_tag_from_end == is_end)
2452 {
2453 cfun->machine->doloop_tags++;
2454 cfun->machine->doloop_tag_from_end = is_end;
2455 }
2456
2457 tag = GEN_INT (cfun->machine->doloop_tags - 1);
2458 machine_mode opmode = GET_MODE (operands[0]);
f886644b
DD
2459 gcc_assert (opmode == HImode || opmode == SImode);
2460
8d2af3a2 2461 if (is_end)
f886644b
DD
2462 emit_jump_insn (gen_doloop_end_internal (opmode, operands[0],
2463 operands[1], tag));
8d2af3a2 2464 else
f886644b
DD
2465 emit_insn (gen_doloop_begin_internal (opmode, operands[0],
2466 operands[0], tag));
8d2af3a2
DD
2467}
2468
2469
2470/* Code for converting doloop_begins and doloop_ends into valid
2471 PRU instructions. Idea and code snippets borrowed from mep port.
2472
2473 A doloop_begin is just a placeholder:
2474
2475 $count = unspec ($count)
2476
2477 where $count is initially the number of iterations.
2478 doloop_end has the form:
2479
2480 if (--$count == 0) goto label
2481
2482 The counter variable is private to the doloop insns, nothing else
2483 relies on its value.
2484
2485 There are three cases, in decreasing order of preference:
2486
2487 1. A loop has exactly one doloop_begin and one doloop_end.
2488 The doloop_end branches to the first instruction after
2489 the doloop_begin.
2490
2491 In this case we can replace the doloop_begin with a LOOP
2492 instruction and remove the doloop_end. I.e.:
2493
2494 $count1 = unspec ($count1)
2495 label:
2496 ...
2497 if (--$count2 != 0) goto label
2498
2499 becomes:
2500
2501 LOOP end_label,$count1
2502 label:
2503 ...
2504 end_label:
2505 # end loop
2506
2507 2. As for (1), except there are several doloop_ends. One of them
2508 (call it X) falls through to a label L. All the others fall
2509 through to branches to L.
2510
2511 In this case, we remove X and replace the other doloop_ends
2512 with branches to the LOOP label. For example:
2513
2514 $count1 = unspec ($count1)
2515 label:
2516 ...
2517 if (--$count1 != 0) goto label
2518 end_label:
2519 ...
2520 if (--$count2 != 0) goto label
2521 goto end_label
2522
2523 becomes:
2524
2525 LOOP end_label,$count1
2526 label:
2527 ...
2528 end_label:
2529 # end repeat
2530 ...
2531 goto end_label
2532
2533 3. The fallback case. Replace doloop_begins with:
2534
2535 $count = $count
2536
2537 Replace doloop_ends with the equivalent of:
2538
2539 $count = $count - 1
2540 if ($count != 0) goto loop_label
2541
2542 */
2543
2544/* A structure describing one doloop_begin. */
2545struct pru_doloop_begin {
2546 /* The next doloop_begin with the same tag. */
2547 struct pru_doloop_begin *next;
2548
2549 /* The instruction itself. */
2550 rtx_insn *insn;
2551
2552 /* The initial counter value. */
2553 rtx loop_count;
2554
2555 /* The counter register. */
2556 rtx counter;
2557};
2558
2559/* A structure describing a doloop_end. */
2560struct pru_doloop_end {
2561 /* The next doloop_end with the same loop tag. */
2562 struct pru_doloop_end *next;
2563
2564 /* The instruction itself. */
2565 rtx_insn *insn;
2566
2567 /* The first instruction after INSN when the branch isn't taken. */
2568 rtx_insn *fallthrough;
2569
2570 /* The location of the counter value. Since doloop_end_internal is a
2571 jump instruction, it has to allow the counter to be stored anywhere
2572 (any non-fixed register). */
2573 rtx counter;
2574
2575 /* The target label (the place where the insn branches when the counter
2576 isn't zero). */
2577 rtx label;
2578
2579 /* A scratch register. Only available when COUNTER isn't stored
2580 in a general register. */
2581 rtx scratch;
2582};
2583
2584
2585/* One do-while loop. */
2586struct pru_doloop {
2587 /* All the doloop_begins for this loop (in no particular order). */
2588 struct pru_doloop_begin *begin;
2589
2590 /* All the doloop_ends. When there is more than one, arrange things
2591 so that the first one is the most likely to be X in case (2) above. */
2592 struct pru_doloop_end *end;
2593};
2594
2595
2596/* Return true if LOOP can be converted into LOOP form
2597 (that is, if it matches cases (1) or (2) above). */
2598
2599static bool
2600pru_repeat_loop_p (struct pru_doloop *loop)
2601{
2602 struct pru_doloop_end *end;
2603 rtx_insn *fallthrough;
2604
2605 /* There must be exactly one doloop_begin and at least one doloop_end. */
2606 if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0)
2607 return false;
2608
2609 /* The first doloop_end (X) must branch back to the insn after
2610 the doloop_begin. */
2611 if (prev_real_insn (as_a<rtx_insn *> (loop->end->label)) != loop->begin->insn)
2612 return false;
2613
2614 /* Check that the first doloop_end (X) can actually reach
2615 doloop_begin () with U8_PCREL relocation for LOOP instruction. */
2616 if (get_attr_length (loop->end->insn) != 4)
2617 return false;
2618
2619 /* All the other doloop_ends must branch to the same place as X.
2620 When the branch isn't taken, they must jump to the instruction
2621 after X. */
2622 fallthrough = loop->end->fallthrough;
2623 for (end = loop->end->next; end != 0; end = end->next)
2624 if (end->label != loop->end->label
2625 || !simplejump_p (end->fallthrough)
2626 || fallthrough
2627 != next_real_insn (JUMP_LABEL_AS_INSN (end->fallthrough)))
2628 return false;
2629
2630 return true;
2631}
2632
2633
2634/* The main repeat reorg function. See comment above for details. */
2635
2636static void
2637pru_reorg_loop (rtx_insn *insns)
2638{
2639 rtx_insn *insn;
2640 struct pru_doloop *loops, *loop;
2641 struct pru_doloop_begin *begin;
2642 struct pru_doloop_end *end;
2643 size_t tmpsz;
2644
2645 /* Quick exit if we haven't created any loops. */
2646 if (cfun->machine->doloop_tags == 0)
2647 return;
2648
2649 /* Create an array of pru_doloop structures. */
2650 tmpsz = sizeof (loops[0]) * cfun->machine->doloop_tags;
2651 loops = (struct pru_doloop *) alloca (tmpsz);
2652 memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags);
2653
2654 /* Search the function for do-while insns and group them by loop tag. */
2655 for (insn = insns; insn; insn = NEXT_INSN (insn))
2656 if (INSN_P (insn))
2657 switch (recog_memoized (insn))
2658 {
2659 case CODE_FOR_doloop_begin_internalhi:
2660 case CODE_FOR_doloop_begin_internalsi:
2661 insn_extract (insn);
2662 loop = &loops[INTVAL (recog_data.operand[2])];
2663
2664 tmpsz = sizeof (struct pru_doloop_begin);
2665 begin = (struct pru_doloop_begin *) alloca (tmpsz);
2666 begin->next = loop->begin;
2667 begin->insn = insn;
2668 begin->loop_count = recog_data.operand[1];
2669 begin->counter = recog_data.operand[0];
2670
2671 loop->begin = begin;
2672 break;
2673
2674 case CODE_FOR_doloop_end_internalhi:
2675 case CODE_FOR_doloop_end_internalsi:
2676 insn_extract (insn);
2677 loop = &loops[INTVAL (recog_data.operand[2])];
2678
2679 tmpsz = sizeof (struct pru_doloop_end);
2680 end = (struct pru_doloop_end *) alloca (tmpsz);
2681 end->insn = insn;
2682 end->fallthrough = next_real_insn (insn);
2683 end->counter = recog_data.operand[0];
2684 end->label = recog_data.operand[1];
2685 end->scratch = recog_data.operand[3];
2686
2687 /* If this insn falls through to an unconditional jump,
2688 give it a lower priority than the others. */
2689 if (loop->end != 0 && simplejump_p (end->fallthrough))
2690 {
2691 end->next = loop->end->next;
2692 loop->end->next = end;
2693 }
2694 else
2695 {
2696 end->next = loop->end;
2697 loop->end = end;
2698 }
2699 break;
2700 }
2701
2702 /* Convert the insns for each loop in turn. */
2703 for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++)
2704 if (pru_repeat_loop_p (loop))
2705 {
2706 /* Case (1) or (2). */
2707 rtx_code_label *repeat_label;
2708 rtx label_ref;
f886644b 2709 rtx loop_rtx;
8d2af3a2
DD
2710
2711 /* Create a new label for the repeat insn. */
2712 repeat_label = gen_label_rtx ();
2713
2714 /* Replace the doloop_begin with a repeat. We get rid
2715 of the iteration register because LOOP instruction
2716 will utilize an internal for the PRU core LOOP register. */
2717 label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label);
2718 machine_mode loop_mode = GET_MODE (loop->begin->loop_count);
f886644b 2719 if (loop_mode == VOIDmode)
8d2af3a2
DD
2720 {
2721 gcc_assert (CONST_INT_P (loop->begin->loop_count));
2722 gcc_assert (UBYTE_INT ( INTVAL (loop->begin->loop_count)));
f886644b 2723 loop_mode = SImode;
8d2af3a2 2724 }
f886644b
DD
2725 gcc_assert (loop_mode == HImode || loop_mode == SImode);
2726 loop_rtx = gen_pruloop (loop_mode, loop->begin->loop_count, label_ref);
2727 emit_insn_before (loop_rtx, loop->begin->insn);
2728
8d2af3a2
DD
2729 delete_insn (loop->begin->insn);
2730
2731 /* Insert the repeat label before the first doloop_end.
2732 Fill the gap with nops if LOOP insn is less than 2
2733 instructions away than loop->end. */
2734 pru_insert_loop_label_last (loop->end->insn, repeat_label,
2735 loop->end->next != 0);
2736
2737 /* Emit a pruloop_end (to improve the readability of the output). */
2738 emit_insn_before (gen_pruloop_end (), loop->end->insn);
2739
2740 /* HACK: TODO: This is usually not needed, but is required for
2741 a few rare cases where a JUMP that breaks the loop
2742 references the LOOP_END address. In other words, since
2743 we're missing a real "loop_end" instruction, a loop "break"
2744 may accidentally reference the loop end itself, and thus
2745 continuing the cycle. */
2746 for (insn = NEXT_INSN (loop->end->insn);
2747 insn != next_real_insn (loop->end->insn);
2748 insn = NEXT_INSN (insn))
2749 {
2750 if (LABEL_P (insn) && LABEL_NUSES (insn) > 0)
2751 emit_insn_before (gen_nop_loop_guard (), loop->end->insn);
2752 }
2753
2754 /* Delete the first doloop_end. */
2755 delete_insn (loop->end->insn);
2756
2757 /* Replace the others with branches to REPEAT_LABEL. */
2758 for (end = loop->end->next; end != 0; end = end->next)
2759 {
2760 rtx_insn *newjmp;
2761 newjmp = emit_jump_insn_before (gen_jump (repeat_label), end->insn);
2762 JUMP_LABEL (newjmp) = repeat_label;
2763 delete_insn (end->insn);
2764 delete_insn (end->fallthrough);
2765 }
2766 }
2767 else
2768 {
2769 /* Case (3). First replace all the doloop_begins with setting
2770 the HW register used for loop counter. */
2771 for (begin = loop->begin; begin != 0; begin = begin->next)
2772 {
2773 insn = gen_move_insn (copy_rtx (begin->counter),
2774 copy_rtx (begin->loop_count));
2775 emit_insn_before (insn, begin->insn);
2776 delete_insn (begin->insn);
2777 }
2778
2779 /* Replace all the doloop_ends with decrement-and-branch sequences. */
2780 for (end = loop->end; end != 0; end = end->next)
2781 {
2782 rtx reg;
2783
2784 start_sequence ();
2785
2786 /* Load the counter value into a general register. */
2787 reg = end->counter;
2788 if (!REG_P (reg) || REGNO (reg) > LAST_NONIO_GP_REGNUM)
2789 {
2790 reg = end->scratch;
2791 emit_move_insn (copy_rtx (reg), copy_rtx (end->counter));
2792 }
2793
2794 /* Decrement the counter. */
2795 emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg),
2796 constm1_rtx));
2797
2798 /* Copy it back to its original location. */
2799 if (reg != end->counter)
2800 emit_move_insn (copy_rtx (end->counter), copy_rtx (reg));
2801
2802 /* Jump back to the start label. */
2803 insn = emit_jump_insn (gen_cbranchsi4 (gen_rtx_NE (VOIDmode, reg,
2804 const0_rtx),
2805 reg,
2806 const0_rtx,
2807 end->label));
2808
2809 JUMP_LABEL (insn) = end->label;
2810 LABEL_NUSES (end->label)++;
2811
2812 /* Emit the whole sequence before the doloop_end. */
2813 insn = get_insns ();
2814 end_sequence ();
2815 emit_insn_before (insn, end->insn);
2816
2817 /* Delete the doloop_end. */
2818 delete_insn (end->insn);
2819 }
2820 }
2821}
2822
2823/* Implement TARGET_MACHINE_DEPENDENT_REORG. */
2824static void
2825pru_reorg (void)
2826{
2827 rtx_insn *insns = get_insns ();
2828
2829 compute_bb_for_insn ();
2830 df_analyze ();
2831
2832 /* Need correct insn lengths for allowing LOOP instruction
2833 emitting due to U8_PCREL limitations. */
2834 shorten_branches (get_insns ());
2835
2836 /* The generic reorg_loops () is not suitable for PRU because
2837 it doesn't handle doloop_begin/end tying. And we need our
2838 doloop_begin emitted before reload. It is difficult to coalesce
2839 UBYTE constant initial loop values into the LOOP insn during
2840 machine reorg phase. */
2841 pru_reorg_loop (insns);
2842
2843 df_finish_pass (false);
2844}
2845\f
2846/* Enumerate all PRU-specific builtins. */
2847enum pru_builtin
2848{
2849 PRU_BUILTIN_DELAY_CYCLES,
5ace1776
DD
2850 PRU_BUILTIN_HALT,
2851 PRU_BUILTIN_LMBD,
8d2af3a2
DD
2852 PRU_BUILTIN_max
2853};
2854
2855static GTY(()) tree pru_builtins [(int) PRU_BUILTIN_max];
2856
2857/* Implement TARGET_INIT_BUILTINS. */
2858
2859static void
2860pru_init_builtins (void)
2861{
2862 tree void_ftype_longlong
2863 = build_function_type_list (void_type_node,
2864 long_long_integer_type_node,
2865 NULL);
5ace1776
DD
2866 tree uint_ftype_uint_uint
2867 = build_function_type_list (unsigned_type_node,
2868 unsigned_type_node,
2869 unsigned_type_node,
2870 NULL);
2871
2872 tree void_ftype_void
2873 = build_function_type_list (void_type_node,
2874 void_type_node,
2875 NULL);
8d2af3a2
DD
2876
2877 pru_builtins[PRU_BUILTIN_DELAY_CYCLES]
2878 = add_builtin_function ("__delay_cycles", void_ftype_longlong,
2879 PRU_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL,
2880 NULL_TREE);
5ace1776
DD
2881
2882 pru_builtins[PRU_BUILTIN_HALT]
2883 = add_builtin_function ("__halt", void_ftype_void,
2884 PRU_BUILTIN_HALT, BUILT_IN_MD, NULL,
2885 NULL_TREE);
2886
2887 pru_builtins[PRU_BUILTIN_LMBD]
2888 = add_builtin_function ("__lmbd", uint_ftype_uint_uint,
2889 PRU_BUILTIN_LMBD, BUILT_IN_MD, NULL,
2890 NULL_TREE);
8d2af3a2
DD
2891}
2892
2893/* Implement TARGET_BUILTIN_DECL. */
2894
2895static tree
2896pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2897{
2898 switch (code)
2899 {
2900 case PRU_BUILTIN_DELAY_CYCLES:
5ace1776
DD
2901 case PRU_BUILTIN_HALT:
2902 case PRU_BUILTIN_LMBD:
8d2af3a2
DD
2903 return pru_builtins[code];
2904 default:
2905 return error_mark_node;
2906 }
2907}
2908\f
2909/* Emit a sequence of one or more delay_cycles_X insns, in order to generate
2910 code that delays exactly ARG cycles. */
2911
2912static rtx
2913pru_expand_delay_cycles (rtx arg)
2914{
2915 HOST_WIDE_INT c, n;
2916
2917 if (GET_CODE (arg) != CONST_INT)
2918 {
2919 error ("%<__delay_cycles%> only takes constant arguments");
2920 return NULL_RTX;
2921 }
2922
2923 c = INTVAL (arg);
2924
2925 gcc_assert (HOST_BITS_PER_WIDE_INT > 32);
2926 if (c < 0)
2927 {
2928 error ("%<__delay_cycles%> only takes non-negative cycle counts");
2929 return NULL_RTX;
2930 }
2931
2932 emit_insn (gen_delay_cycles_start (arg));
2933
2934 /* For 32-bit loops, there's 2 + 2x cycles. */
2935 if (c > 2 * 0xffff + 1)
2936 {
2937 n = (c - 2) / 2;
2938 c -= (n * 2) + 2;
2939 if ((unsigned long long) n > 0xffffffffULL)
2940 {
2941 error ("%<__delay_cycles%> is limited to 32-bit loop counts");
2942 return NULL_RTX;
2943 }
2944 emit_insn (gen_delay_cycles_2x_plus2_si (GEN_INT (n)));
2945 }
2946
2947 /* For 16-bit loops, there's 1 + 2x cycles. */
2948 if (c > 2)
2949 {
2950 n = (c - 1) / 2;
2951 c -= (n * 2) + 1;
2952
2953 emit_insn (gen_delay_cycles_2x_plus1_hi (GEN_INT (n)));
2954 }
2955
2956 while (c > 0)
2957 {
2958 emit_insn (gen_delay_cycles_1 ());
2959 c -= 1;
2960 }
2961
2962 emit_insn (gen_delay_cycles_end (arg));
2963
2964 return NULL_RTX;
2965}
2966
2967
2968/* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2969 a built-in function, with result going to TARGET if that's convenient
2970 (and in mode MODE if that's convenient).
2971 SUBTARGET may be used as the target for computing one of EXP's operands.
2972 IGNORE is nonzero if the value is to be ignored. */
2973
2974static rtx
5ace1776 2975pru_expand_builtin (tree exp, rtx target,
8d2af3a2 2976 rtx subtarget ATTRIBUTE_UNUSED,
5ace1776 2977 machine_mode mode,
8d2af3a2
DD
2978 int ignore ATTRIBUTE_UNUSED)
2979{
2980 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
4d732405 2981 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
8d2af3a2 2982
5ace1776
DD
2983 switch (fcode)
2984 {
2985 case PRU_BUILTIN_DELAY_CYCLES:
2986 {
2987 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2988 return pru_expand_delay_cycles (arg1);
2989 }
2990 break;
2991 case PRU_BUILTIN_HALT:
2992 {
2993 emit_insn (gen_pru_halt ());
2994 return NULL_RTX;
2995 }
2996 break;
2997 case PRU_BUILTIN_LMBD:
2998 {
2999 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
3000 rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
3001
3002 if (target == NULL_RTX || GET_MODE (target) != mode)
3003 {
3004 target = gen_reg_rtx (mode);
3005 }
8d2af3a2 3006
5ace1776
DD
3007 emit_insn (gen_pru_lmbd (mode, target, arg1, arg2));
3008 return target;
3009 }
3010 break;
3011 default:
3012 internal_error ("bad builtin code");
3013 }
8d2af3a2
DD
3014
3015 return NULL_RTX;
3016}
3017\f
3018/* Remember the last target of pru_set_current_function. */
3019static GTY(()) tree pru_previous_fndecl;
3020
3021/* Establish appropriate back-end context for processing the function
3022 FNDECL. The argument might be NULL to indicate processing at top
3023 level, outside of any function scope. */
3024static void
3025pru_set_current_function (tree fndecl)
3026{
3027 tree old_tree = (pru_previous_fndecl
3028 ? DECL_FUNCTION_SPECIFIC_TARGET (pru_previous_fndecl)
3029 : NULL_TREE);
3030
3031 tree new_tree = (fndecl
3032 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3033 : NULL_TREE);
3034
3035 if (fndecl && fndecl != pru_previous_fndecl)
3036 {
3037 pru_previous_fndecl = fndecl;
3038 if (old_tree == new_tree)
3039 ;
3040
3041 else if (new_tree)
3042 {
ba948b37 3043 cl_target_option_restore (&global_options, &global_options_set,
8d2af3a2
DD
3044 TREE_TARGET_OPTION (new_tree));
3045 target_reinit ();
3046 }
3047
3048 else if (old_tree)
3049 {
3050 struct cl_target_option *def
3051 = TREE_TARGET_OPTION (target_option_current_node);
3052
ba948b37 3053 cl_target_option_restore (&global_options, &global_options_set, def);
8d2af3a2
DD
3054 target_reinit ();
3055 }
3056 }
3057}
3058\f
3059/* Implement TARGET_UNWIND_WORD_MODE.
3060
3061 Since PRU is really a 32-bit CPU, the default word_mode is not suitable. */
3062static scalar_int_mode
3063pru_unwind_word_mode (void)
3064{
3065 return SImode;
3066}
3067\f
3068
3069/* Initialize the GCC target structure. */
3070#undef TARGET_ASM_FUNCTION_PROLOGUE
3071#define TARGET_ASM_FUNCTION_PROLOGUE pru_asm_function_prologue
3072#undef TARGET_ASM_INTEGER
3073#define TARGET_ASM_INTEGER pru_assemble_integer
3074
3075#undef TARGET_ASM_FILE_START
3076#define TARGET_ASM_FILE_START pru_file_start
3077
8bafc964
DD
3078#undef TARGET_INSERT_ATTRIBUTES
3079#define TARGET_INSERT_ATTRIBUTES pru_insert_attributes
3080
8d2af3a2
DD
3081#undef TARGET_INIT_BUILTINS
3082#define TARGET_INIT_BUILTINS pru_init_builtins
3083#undef TARGET_EXPAND_BUILTIN
3084#define TARGET_EXPAND_BUILTIN pru_expand_builtin
3085#undef TARGET_BUILTIN_DECL
3086#define TARGET_BUILTIN_DECL pru_builtin_decl
3087
3088#undef TARGET_COMPUTE_FRAME_LAYOUT
3089#define TARGET_COMPUTE_FRAME_LAYOUT pru_compute_frame_layout
3090
3091#undef TARGET_FUNCTION_OK_FOR_SIBCALL
3092#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3093
3094#undef TARGET_CAN_ELIMINATE
3095#define TARGET_CAN_ELIMINATE pru_can_eliminate
3096
3097#undef TARGET_HARD_REGNO_MODE_OK
3098#define TARGET_HARD_REGNO_MODE_OK pru_hard_regno_mode_ok
3099
3100#undef TARGET_HARD_REGNO_SCRATCH_OK
3101#define TARGET_HARD_REGNO_SCRATCH_OK pru_hard_regno_scratch_ok
8d2af3a2
DD
3102
3103#undef TARGET_FUNCTION_ARG
3104#define TARGET_FUNCTION_ARG pru_function_arg
3105
3106#undef TARGET_FUNCTION_ARG_ADVANCE
3107#define TARGET_FUNCTION_ARG_ADVANCE pru_function_arg_advance
3108
3109#undef TARGET_ARG_PARTIAL_BYTES
3110#define TARGET_ARG_PARTIAL_BYTES pru_arg_partial_bytes
3111
3112#undef TARGET_FUNCTION_VALUE
3113#define TARGET_FUNCTION_VALUE pru_function_value
3114
3115#undef TARGET_LIBCALL_VALUE
3116#define TARGET_LIBCALL_VALUE pru_libcall_value
3117
3118#undef TARGET_FUNCTION_VALUE_REGNO_P
3119#define TARGET_FUNCTION_VALUE_REGNO_P pru_function_value_regno_p
3120
3121#undef TARGET_RETURN_IN_MEMORY
3122#define TARGET_RETURN_IN_MEMORY pru_return_in_memory
3123
3124#undef TARGET_MUST_PASS_IN_STACK
3125#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3126
8bafc964
DD
3127#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
3128#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
3129 pru_addr_space_legitimate_address_p
8d2af3a2
DD
3130
3131#undef TARGET_INIT_LIBFUNCS
3132#define TARGET_INIT_LIBFUNCS pru_init_libfuncs
3133#undef TARGET_LIBFUNC_GNU_PREFIX
3134#define TARGET_LIBFUNC_GNU_PREFIX true
3135
3136#undef TARGET_RTX_COSTS
3137#define TARGET_RTX_COSTS pru_rtx_costs
3138
3139#undef TARGET_PRINT_OPERAND
3140#define TARGET_PRINT_OPERAND pru_print_operand
3141
3142#undef TARGET_PRINT_OPERAND_ADDRESS
3143#define TARGET_PRINT_OPERAND_ADDRESS pru_print_operand_address
3144
3145#undef TARGET_OPTION_OVERRIDE
3146#define TARGET_OPTION_OVERRIDE pru_option_override
3147
3148#undef TARGET_SET_CURRENT_FUNCTION
3149#define TARGET_SET_CURRENT_FUNCTION pru_set_current_function
3150
3151#undef TARGET_MACHINE_DEPENDENT_REORG
3152#define TARGET_MACHINE_DEPENDENT_REORG pru_reorg
3153
3154#undef TARGET_CAN_USE_DOLOOP_P
3155#define TARGET_CAN_USE_DOLOOP_P pru_can_use_doloop_p
3156
3157#undef TARGET_INVALID_WITHIN_DOLOOP
3158#define TARGET_INVALID_WITHIN_DOLOOP pru_invalid_within_doloop
3159
3160#undef TARGET_UNWIND_WORD_MODE
3161#define TARGET_UNWIND_WORD_MODE pru_unwind_word_mode
3162
3163#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
3164#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
3165
3166struct gcc_target targetm = TARGET_INITIALIZER;
3167
3168#include "gt-pru.h"