xref: /netbsd/external/gpl3/gcc/dist/gcc/config/pru/pru.cc (revision f0fbc68b)
1 /* Target machine subroutines for TI PRU.
2    Copyright (C) 2014-2022 Free Software Foundation, Inc.
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.  */
62 struct pru_ctable_entry pru_ctable[32];
63 
64 /* Forward function declarations.  */
65 static bool prologue_saved_reg_p (int);
66 static void pru_reorg_loop (rtx_insn *);
67 
68 struct 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 
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.  */
116 static void
pru_compute_frame_layout(void)117 pru_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  */
164 static rtx
pru_add3_frame_adjust(rtx op0,rtx op1,int addendum,const enum reg_note kind)165 pru_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.  */
203 static rtx
pru_add_to_sp(int addendum,const enum reg_note kind)204 pru_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.  */
212 static int
xbbo_next_reg_cluster(int regno_start,int * sp_offset,bool do_store)213 xbbo_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.  */
276 void
pru_expand_prologue(void)277 pru_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.  */
336 void
pru_expand_epilogue(bool sibcall_p)337 pru_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.  */
396 rtx
pru_get_return_address(int count)397 pru_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.  */
407 void
pru_function_profiler(FILE * file,int labelno ATTRIBUTE_UNUSED)408 pru_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.  */
416 static void
pru_dump_frame_layout(FILE * file)417 pru_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.  */
441 static bool
prologue_saved_reg_p(int regno)442 prologue_saved_reg_p (int regno)
443 {
444   gcc_assert (GP_REG_P (regno));
445 
446   if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
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.  */
465 static bool
pru_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)466 pru_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.  */
474 int
pru_initial_elimination_offset(int from,int to)475 pru_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.  */
507 int
pru_can_use_return_insn(void)508 pru_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 
516 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
517 
518 static bool
pru_hard_regno_mode_ok(unsigned int regno,machine_mode mode)519 pru_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 
540 static bool
pru_hard_regno_scratch_ok(unsigned int regno)541 pru_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 
559 /* Worker function for `HARD_REGNO_RENAME_OK'.
560    Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
561 
562 int
pru_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)563 pru_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 
584 /* Allocate a chunk of memory for per-function machine-dependent data.  */
585 static struct machine_function *
pru_init_machine_status(void)586 pru_init_machine_status (void)
587 {
588   return ggc_cleared_alloc<machine_function> ();
589 }
590 
591 /* Implement TARGET_OPTION_OVERRIDE.  */
592 static void
pru_option_override(void)593 pru_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
624     = build_target_option_node (&global_options, &global_options_set);
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 
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.  */
635 static bool
pru_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed ATTRIBUTE_UNUSED)636 pru_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 
783 static GTY(()) rtx eqdf_libfunc;
784 static GTY(()) rtx nedf_libfunc;
785 static GTY(()) rtx ledf_libfunc;
786 static GTY(()) rtx ltdf_libfunc;
787 static GTY(()) rtx gedf_libfunc;
788 static GTY(()) rtx gtdf_libfunc;
789 static GTY(()) rtx eqsf_libfunc;
790 static GTY(()) rtx nesf_libfunc;
791 static GTY(()) rtx lesf_libfunc;
792 static GTY(()) rtx ltsf_libfunc;
793 static GTY(()) rtx gesf_libfunc;
794 static 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 
799 static void
pru_init_libfuncs(void)800 pru_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 
899 rtx
pru_expand_fp_compare(rtx comparison,machine_mode mode)900 pru_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 
964 /* Return the sign bit position for given OP's mode.  */
965 static int
sign_bit_position(const rtx op)966 sign_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.  */
974 const char *
pru_output_sign_extend(rtx * operands)975 pru_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 
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 
1030 Given 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
1042 BRANCH_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.  */
1049 static const char *
pru_output_ltle_signed_cbranch(rtx * operands,bool is_near)1050 pru_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.  */
1106 static const char *
pru_output_gtge_signed_cbranch(rtx * operands,bool is_near)1107 pru_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.  */
1167 const char *
pru_output_signed_cbranch(rtx * operands,bool is_near)1168 pru_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 
1183 const char *
pru_output_signed_cbranch_ubyteop2(rtx * operands,bool is_near)1184 pru_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 
1253 const char *
pru_output_signed_cbranch_zeroop2(rtx * operands,bool is_near)1254 pru_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 
1297 bool
pru_regno_ok_for_base_p(int regno,bool strict_p)1298 pru_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.  */
1312 static bool
pru_valid_const_ubyte_offset(machine_mode mode,HOST_WIDE_INT offset)1313 pru_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.  */
1327 int
pru_get_ctable_exact_base_index(unsigned HOST_WIDE_INT caddr)1328 pru_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.  */
1343 int
pru_get_ctable_base_index(unsigned HOST_WIDE_INT caddr)1344 pru_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.  */
1360 int
pru_get_ctable_base_offset(unsigned HOST_WIDE_INT caddr)1361 pru_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.  */
1379 static bool
pru_valid_addr_expr_p(machine_mode mode,rtx base,rtx offset,bool strict_p)1380 pru_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 
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.  */
pru_symref2ioregno(rtx op)1411 int 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.  */
1426 static bool
pru_addr_space_legitimate_address_p(machine_mode mode,rtx operand,bool strict_p,addr_space_t as)1427 pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
1428 				     bool strict_p, addr_space_t as)
1429 {
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 
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 
1473 /* Output assembly language related definitions.  */
1474 
1475 /* Implement TARGET_ASM_CONSTRUCTOR.  */
1476 static void
pru_elf_asm_constructor(rtx symbol,int priority)1477 pru_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.  */
1497 static void
pru_elf_asm_destructor(rtx symbol,int priority)1498 pru_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.  */
1519 static const char *
pru_comparison_str(enum rtx_code cond)1520 pru_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 
1537 static rtx
pru_to_int_mode(rtx x)1538 pru_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].  */
1550 static const char *
pru_asm_regname(rtx op)1551 pru_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 */
1625 static void
pru_print_operand(FILE * file,rtx op,int letter)1626 pru_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);
1653 	  /* Fall through.  */
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.  */
1896 static void
pru_print_operand_address(FILE * file,machine_mode mode,rtx op)1897 pru_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.  */
1985 static void
pru_asm_function_prologue(FILE * file)1986 pru_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 
1996 static bool
pru_assemble_integer(rtx x,unsigned int size,int aligned_p)1997 pru_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_SECTION_TYPE_FLAGS.  */
2026 
2027 static unsigned int
pru_section_type_flags(tree decl,const char * name,int reloc)2028 pru_section_type_flags (tree decl, const char *name, int reloc)
2029 {
2030   unsigned int flags = default_section_type_flags (decl, name, reloc);
2031 
2032   /* The .pru_irq_map section is not meant to be loaded into the target
2033      memory.  Instead its contents are read by the host remoteproc loader.
2034      To prevent being marked as a loadable (allocated) section, the
2035      .pru_irq_map section is intercepted and marked as a debug section.  */
2036   if (!strcmp (name, ".pru_irq_map"))
2037     flags = SECTION_DEBUG | SECTION_RETAIN;
2038 
2039   return flags;
2040 }
2041 
2042 /* Implement TARGET_ASM_FILE_START.  */
2043 
2044 static void
pru_file_start(void)2045 pru_file_start (void)
2046 {
2047   default_file_start ();
2048 
2049   /* Compiler will take care of placing %label, so there is no
2050      need to confuse users with this warning.  */
2051   fprintf (asm_out_file, "\t.set no_warn_regname_label\n");
2052 }
2053 
2054 /* Scan type TYP for pointer references to address space other than
2055    ADDR_SPACE_GENERIC.  Return true if such reference is found.
2056    Much of this code was taken from the avr port.  */
2057 
2058 static bool
pru_nongeneric_pointer_addrspace(tree typ)2059 pru_nongeneric_pointer_addrspace (tree typ)
2060 {
2061   while (ARRAY_TYPE == TREE_CODE (typ))
2062     typ = TREE_TYPE (typ);
2063 
2064   if (POINTER_TYPE_P (typ))
2065     {
2066       addr_space_t as;
2067       tree target = TREE_TYPE (typ);
2068 
2069       /* Pointer to function: Test the function's return type.  */
2070       if (FUNCTION_TYPE == TREE_CODE (target))
2071 	return pru_nongeneric_pointer_addrspace (TREE_TYPE (target));
2072 
2073       /* "Ordinary" pointers... */
2074 
2075       while (TREE_CODE (target) == ARRAY_TYPE)
2076 	target = TREE_TYPE (target);
2077 
2078       as = TYPE_ADDR_SPACE (target);
2079 
2080       if (!ADDR_SPACE_GENERIC_P (as))
2081 	return true;
2082 
2083       /* Scan pointer's target type.  */
2084       return pru_nongeneric_pointer_addrspace (target);
2085     }
2086 
2087   return false;
2088 }
2089 
2090 /* Implement `TARGET_INSERT_ATTRIBUTES'.  For PRU it's used as a hook to
2091    provide better diagnostics for some invalid usages of the __regio_symbol
2092    address space.
2093 
2094    Any escapes of the following checks are supposed to be caught
2095    during the "mov<mode>" pattern expansion.  */
2096 
2097 static void
pru_insert_attributes(tree node,tree * attributes ATTRIBUTE_UNUSED)2098 pru_insert_attributes (tree node, tree *attributes ATTRIBUTE_UNUSED)
2099 {
2100 
2101   /* Validate __regio_symbol variable declarations.  */
2102   if (VAR_P (node))
2103     {
2104       const char *name = DECL_NAME (node)
2105 			  ? IDENTIFIER_POINTER (DECL_NAME (node))
2106 			  : "<unknown>";
2107       tree typ = TREE_TYPE (node);
2108       addr_space_t as = TYPE_ADDR_SPACE (typ);
2109 
2110       if (as == ADDR_SPACE_GENERIC)
2111 	return;
2112 
2113       if (AGGREGATE_TYPE_P (typ))
2114 	{
2115 	  error ("aggregate types are prohibited in "
2116 		 "%<__regio_symbol%> address space");
2117 	  /* Don't bother anymore.  Below checks would pile
2118 	     meaningless errors, which would confuse user.  */
2119 	  return;
2120 	}
2121       if (DECL_INITIAL (node) != NULL_TREE)
2122 	error ("variables in %<__regio_symbol%> address space "
2123 	       "cannot have initial value");
2124       if (DECL_REGISTER (node))
2125 	error ("variables in %<__regio_symbol%> address space "
2126 	       "cannot be declared %<register%>");
2127       if (!TYPE_VOLATILE (typ))
2128 	error ("variables in %<__regio_symbol%> address space "
2129 	       "must be declared %<volatile%>");
2130       if (!DECL_EXTERNAL (node))
2131 	error ("variables in %<__regio_symbol%> address space "
2132 	       "must be declared %<extern%>");
2133       if (TYPE_MODE (typ) != SImode)
2134 	error ("only 32-bit access is supported "
2135 	       "for %<__regio_symbol%> address space");
2136       if (strcmp (name, "__R30") != 0 && strcmp (name, "__R31") != 0)
2137 	error ("register name %<%s%> not recognized "
2138 	       "in %<__regio_symbol%> address space", name);
2139     }
2140 
2141   tree typ = NULL_TREE;
2142 
2143   switch (TREE_CODE (node))
2144     {
2145     case FUNCTION_DECL:
2146       typ = TREE_TYPE (TREE_TYPE (node));
2147       break;
2148     case TYPE_DECL:
2149     case RESULT_DECL:
2150     case VAR_DECL:
2151     case FIELD_DECL:
2152     case PARM_DECL:
2153       typ = TREE_TYPE (node);
2154       break;
2155     case POINTER_TYPE:
2156       typ = node;
2157       break;
2158     default:
2159       break;
2160     }
2161   if (typ != NULL_TREE && pru_nongeneric_pointer_addrspace (typ))
2162     error ("pointers to %<__regio_symbol%> address space are prohibited");
2163 }
2164 
2165 /* Function argument related.  */
2166 
2167 /* Return the number of bytes needed for storing an argument with
2168    the given MODE and TYPE.  */
2169 static int
pru_function_arg_size(machine_mode mode,const_tree type)2170 pru_function_arg_size (machine_mode mode, const_tree type)
2171 {
2172   HOST_WIDE_INT param_size;
2173 
2174   if (mode == BLKmode)
2175     param_size = int_size_in_bytes (type);
2176   else
2177     param_size = GET_MODE_SIZE (mode);
2178 
2179   /* Convert to words (round up).  */
2180   param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2181   gcc_assert (param_size >= 0);
2182 
2183   return param_size;
2184 }
2185 
2186 /* Check if argument with the given size must be
2187    passed/returned in a register.
2188 
2189    Reference:
2190    https://e2e.ti.com/support/development_tools/compiler/f/343/p/650176/2393029
2191 
2192    Arguments other than 8/16/24/32/64bits are passed on stack.  */
2193 static bool
pru_arg_in_reg_bysize(size_t sz)2194 pru_arg_in_reg_bysize (size_t sz)
2195 {
2196   return sz == 1 || sz == 2 || sz == 3 || sz == 4 || sz == 8;
2197 }
2198 
2199 /* Helper function to get the starting storage HW register for an argument,
2200    or -1 if it must be passed on stack.  The cum_v state is not changed.  */
2201 static int
pru_function_arg_regi(cumulative_args_t cum_v,machine_mode mode,const_tree type,bool named)2202 pru_function_arg_regi (cumulative_args_t cum_v,
2203 		       machine_mode mode, const_tree type,
2204 		       bool named)
2205 {
2206   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2207   size_t argsize = pru_function_arg_size (mode, type);
2208   size_t i, bi;
2209   int regi = -1;
2210 
2211   if (!pru_arg_in_reg_bysize (argsize))
2212     return -1;
2213 
2214   if (!named)
2215     return -1;
2216 
2217   /* Find the first available slot that fits.  Yes, that's the PRU ABI.  */
2218   for (i = 0; regi < 0 && i < ARRAY_SIZE (cum->regs_used); i++)
2219     {
2220       /* VLAs and vector types are not defined in the PRU ABI.  Let's
2221 	 handle them the same as their same-sized counterparts.  This way
2222 	 we do not need to treat BLKmode differently, and need only to check
2223 	 the size.  */
2224       gcc_assert (argsize == 1 || argsize == 2 || argsize == 3
2225 		  || argsize == 4 || argsize == 8);
2226 
2227       /* Ensure SI and DI arguments are stored in full registers only.  */
2228       if ((argsize >= 4) && (i % 4) != 0)
2229 	continue;
2230 
2231       /* Structures with size 24 bits are passed starting at a full
2232 	 register boundary.  */
2233       if (argsize == 3 && (i % 4) != 0)
2234 	continue;
2235 
2236       /* rX.w0/w1/w2 are OK.  But avoid spreading the second byte
2237 	 into a different full register.  */
2238       if (argsize == 2 && (i % 4) == 3)
2239 	continue;
2240 
2241       for (bi = 0;
2242 	   bi < argsize && (bi + i) < ARRAY_SIZE (cum->regs_used);
2243 	   bi++)
2244 	{
2245 	  if (cum->regs_used[bi + i])
2246 	    break;
2247 	}
2248       if (bi == argsize)
2249 	regi = FIRST_ARG_REGNUM + i;
2250     }
2251 
2252   return regi;
2253 }
2254 
2255 /* Mark CUM_V that a function argument will occupy HW register slot starting
2256    at REGI.  The number of consecutive 8-bit HW registers marked as occupied
2257    depends on the MODE and TYPE of the argument.  */
2258 static void
pru_function_arg_regi_mark_slot(int regi,cumulative_args_t cum_v,machine_mode mode,const_tree type,bool named)2259 pru_function_arg_regi_mark_slot (int regi,
2260 				 cumulative_args_t cum_v,
2261 				 machine_mode mode, const_tree type,
2262 				 bool named)
2263 {
2264   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2265   HOST_WIDE_INT param_size = pru_function_arg_size (mode, type);
2266 
2267   gcc_assert (named);
2268 
2269   /* Mark all byte sub-registers occupied by argument as used.  */
2270   while (param_size--)
2271     {
2272       gcc_assert (regi >= FIRST_ARG_REGNUM && regi <= LAST_ARG_REGNUM);
2273       gcc_assert (!cum->regs_used[regi - FIRST_ARG_REGNUM]);
2274       cum->regs_used[regi - FIRST_ARG_REGNUM] = true;
2275       regi++;
2276     }
2277 }
2278 
2279 /* Define where to put the arguments to a function.  Value is zero to
2280    push the argument on the stack, or a hard register in which to
2281    store the argument.
2282 
2283    CUM is a variable of type CUMULATIVE_ARGS which gives info about
2284    the preceding args and about the function being called.
2285    ARG is a description of the argument.  */
2286 
2287 static rtx
pru_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)2288 pru_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
2289 {
2290   rtx return_rtx = NULL_RTX;
2291   int regi = pru_function_arg_regi (cum_v, arg.mode, arg.type, arg.named);
2292 
2293   if (regi >= 0)
2294     return_rtx = gen_rtx_REG (arg.mode, regi);
2295 
2296   return return_rtx;
2297 }
2298 
2299 /* Implement TARGET_ARG_PARTIAL_BYTES.  PRU never splits any arguments
2300    between registers and memory, so we can return 0.  */
2301 
2302 static int
pru_arg_partial_bytes(cumulative_args_t,const function_arg_info &)2303 pru_arg_partial_bytes (cumulative_args_t, const function_arg_info &)
2304 {
2305   return 0;
2306 }
2307 
2308 /* Update the data in CUM to advance over argument ARG.  */
2309 
2310 static void
pru_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)2311 pru_function_arg_advance (cumulative_args_t cum_v,
2312 			  const function_arg_info &arg)
2313 {
2314   int regi = pru_function_arg_regi (cum_v, arg.mode, arg.type, arg.named);
2315 
2316   if (regi >= 0)
2317     pru_function_arg_regi_mark_slot (regi, cum_v, arg.mode,
2318 				     arg.type, arg.named);
2319 }
2320 
2321 /* Implement TARGET_FUNCTION_VALUE.  */
2322 static rtx
pru_function_value(const_tree ret_type,const_tree fn ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)2323 pru_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2324 		      bool outgoing ATTRIBUTE_UNUSED)
2325 {
2326   return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNUM);
2327 }
2328 
2329 /* Implement TARGET_LIBCALL_VALUE.  */
2330 static rtx
pru_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)2331 pru_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2332 {
2333   return gen_rtx_REG (mode, FIRST_RETVAL_REGNUM);
2334 }
2335 
2336 /* Implement TARGET_FUNCTION_VALUE_REGNO_P.  */
2337 static bool
pru_function_value_regno_p(const unsigned int regno)2338 pru_function_value_regno_p (const unsigned int regno)
2339 {
2340   return regno == FIRST_RETVAL_REGNUM;
2341 }
2342 
2343 /* Implement TARGET_RETURN_IN_MEMORY.  */
2344 bool
pru_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)2345 pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2346 {
2347   bool in_memory = (!pru_arg_in_reg_bysize (int_size_in_bytes (type))
2348 		    || int_size_in_bytes (type) == -1);
2349 
2350   return in_memory;
2351 }
2352 
2353 /* Implement TARGET_CAN_USE_DOLOOP_P.  */
2354 
2355 static bool
pru_can_use_doloop_p(const widest_int &,const widest_int & iterations_max,unsigned int loop_depth,bool)2356 pru_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
2357 		      unsigned int loop_depth, bool)
2358 {
2359   /* Considering limitations in the hardware, only use doloop
2360      for innermost loops which must be entered from the top.  */
2361   if (loop_depth > 1)
2362     return false;
2363   /* PRU internal loop counter is 16bits wide.  Remember that iterations_max
2364      holds the maximum number of loop latch executions, while PRU loop
2365      instruction needs the count of loop body executions.  */
2366   if (iterations_max == 0 || wi::geu_p (iterations_max, 0xffff))
2367     return false;
2368 
2369   return true;
2370 }
2371 
2372 /* NULL if INSN insn is valid within a low-overhead loop.
2373    Otherwise return why doloop cannot be applied.  */
2374 
2375 static const char *
pru_invalid_within_doloop(const rtx_insn * insn)2376 pru_invalid_within_doloop (const rtx_insn *insn)
2377 {
2378   if (CALL_P (insn))
2379     return "Function call in the loop.";
2380 
2381   if (JUMP_P (insn) && INSN_CODE (insn) == CODE_FOR_return)
2382     return "Return from a call instruction in the loop.";
2383 
2384   if (NONDEBUG_INSN_P (insn)
2385       && INSN_CODE (insn) < 0
2386       && (GET_CODE (PATTERN (insn)) == ASM_INPUT
2387 	  || asm_noperands (PATTERN (insn)) >= 0))
2388     return "Loop contains asm statement.";
2389 
2390   return NULL;
2391 }
2392 
2393 
2394 /* Figure out where to put LABEL, which is the label for a repeat loop.
2395    The loop ends just before LAST_INSN.  If SHARED, insns other than the
2396    "repeat" might use LABEL to jump to the loop's continuation point.
2397 
2398    Return the last instruction in the adjusted loop.  */
2399 
2400 static rtx_insn *
pru_insert_loop_label_last(rtx_insn * last_insn,rtx_code_label * label,bool shared)2401 pru_insert_loop_label_last (rtx_insn *last_insn, rtx_code_label *label,
2402 			    bool shared)
2403 {
2404   rtx_insn *next, *prev;
2405   int count = 0, code, icode;
2406 
2407   if (dump_file)
2408     fprintf (dump_file, "considering end of repeat loop at insn %d\n",
2409 	     INSN_UID (last_insn));
2410 
2411   /* Set PREV to the last insn in the loop.  */
2412   prev = PREV_INSN (last_insn);
2413 
2414   /* Set NEXT to the next insn after the loop label.  */
2415   next = last_insn;
2416   if (!shared)
2417     while (prev != 0)
2418       {
2419 	code = GET_CODE (prev);
2420 	if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER)
2421 	  break;
2422 
2423 	if (INSN_P (prev))
2424 	  {
2425 	    if (GET_CODE (PATTERN (prev)) == SEQUENCE)
2426 	      prev = as_a <rtx_insn *> (XVECEXP (PATTERN (prev), 0, 1));
2427 
2428 	    /* Other insns that should not be in the last two opcodes.  */
2429 	    icode = recog_memoized (prev);
2430 	    if (icode < 0
2431 		|| icode == CODE_FOR_pruloophi
2432 		|| icode == CODE_FOR_pruloopsi)
2433 	      break;
2434 
2435 	    count++;
2436 	    next = prev;
2437 	    if (dump_file)
2438 	      print_rtl_single (dump_file, next);
2439 	    if (count == 2)
2440 	      break;
2441 	  }
2442 	prev = PREV_INSN (prev);
2443       }
2444 
2445   /* Insert the nops.  */
2446   if (dump_file && count < 2)
2447     fprintf (dump_file, "Adding %d nop%s inside loop\n\n",
2448 	     2 - count, count == 1 ? "" : "s");
2449 
2450   for (; count < 2; count++)
2451     emit_insn_before (gen_nop (), last_insn);
2452 
2453   /* Insert the label.  */
2454   emit_label_before (label, last_insn);
2455 
2456   return last_insn;
2457 }
2458 
2459 /* If IS_END is false, expand a canonical doloop_begin RTL into the
2460    PRU-specific doloop_begin_internal.  Otherwise expand doloop_end to
2461    doloop_end_internal.  */
2462 void
pru_emit_doloop(rtx * operands,int is_end)2463 pru_emit_doloop (rtx *operands, int is_end)
2464 {
2465   rtx tag;
2466 
2467   if (cfun->machine->doloop_tags == 0
2468       || cfun->machine->doloop_tag_from_end == is_end)
2469     {
2470       cfun->machine->doloop_tags++;
2471       cfun->machine->doloop_tag_from_end = is_end;
2472     }
2473 
2474   tag = GEN_INT (cfun->machine->doloop_tags - 1);
2475   machine_mode opmode = GET_MODE (operands[0]);
2476   gcc_assert (opmode == HImode || opmode == SImode);
2477 
2478   if (is_end)
2479     emit_jump_insn (gen_doloop_end_internal (opmode, operands[0],
2480 					     operands[1], tag));
2481   else
2482     emit_insn (gen_doloop_begin_internal (opmode, operands[0],
2483 					  operands[0], tag));
2484 }
2485 
2486 
2487 /* Code for converting doloop_begins and doloop_ends into valid
2488    PRU instructions.  Idea and code snippets borrowed from mep port.
2489 
2490    A doloop_begin is just a placeholder:
2491 
2492 	$count = unspec ($count)
2493 
2494    where $count is initially the number of iterations.
2495    doloop_end has the form:
2496 
2497 	if (--$count == 0) goto label
2498 
2499    The counter variable is private to the doloop insns, nothing else
2500    relies on its value.
2501 
2502    There are three cases, in decreasing order of preference:
2503 
2504       1.  A loop has exactly one doloop_begin and one doloop_end.
2505 	 The doloop_end branches to the first instruction after
2506 	 the doloop_begin.
2507 
2508 	 In this case we can replace the doloop_begin with a LOOP
2509 	 instruction and remove the doloop_end.  I.e.:
2510 
2511 		$count1 = unspec ($count1)
2512 	    label:
2513 		...
2514 		if (--$count2 != 0) goto label
2515 
2516 	  becomes:
2517 
2518 		LOOP end_label,$count1
2519 	    label:
2520 		...
2521 	    end_label:
2522 		# end loop
2523 
2524       2.  As for (1), except there are several doloop_ends.  One of them
2525 	 (call it X) falls through to a label L.  All the others fall
2526 	 through to branches to L.
2527 
2528 	 In this case, we remove X and replace the other doloop_ends
2529 	 with branches to the LOOP label.  For example:
2530 
2531 		$count1 = unspec ($count1)
2532 	    label:
2533 		...
2534 		if (--$count1 != 0) goto label
2535 	    end_label:
2536 		...
2537 		if (--$count2 != 0) goto label
2538 		goto end_label
2539 
2540 	 becomes:
2541 
2542 		LOOP end_label,$count1
2543 	    label:
2544 		...
2545 	    end_label:
2546 		# end repeat
2547 		...
2548 		goto end_label
2549 
2550       3.  The fallback case.  Replace doloop_begins with:
2551 
2552 		$count = $count
2553 
2554 	 Replace doloop_ends with the equivalent of:
2555 
2556 		$count = $count - 1
2557 		if ($count != 0) goto loop_label
2558 
2559 	 */
2560 
2561 /* A structure describing one doloop_begin.  */
2562 struct pru_doloop_begin {
2563   /* The next doloop_begin with the same tag.  */
2564   struct pru_doloop_begin *next;
2565 
2566   /* The instruction itself.  */
2567   rtx_insn *insn;
2568 
2569   /* The initial counter value.  */
2570   rtx loop_count;
2571 
2572   /* The counter register.  */
2573   rtx counter;
2574 };
2575 
2576 /* A structure describing a doloop_end.  */
2577 struct pru_doloop_end {
2578   /* The next doloop_end with the same loop tag.  */
2579   struct pru_doloop_end *next;
2580 
2581   /* The instruction itself.  */
2582   rtx_insn *insn;
2583 
2584   /* The first instruction after INSN when the branch isn't taken.  */
2585   rtx_insn *fallthrough;
2586 
2587   /* The location of the counter value.  Since doloop_end_internal is a
2588      jump instruction, it has to allow the counter to be stored anywhere
2589      (any non-fixed register).  */
2590   rtx counter;
2591 
2592   /* The target label (the place where the insn branches when the counter
2593      isn't zero).  */
2594   rtx label;
2595 
2596   /* A scratch register.  Only available when COUNTER isn't stored
2597      in a general register.  */
2598   rtx scratch;
2599 };
2600 
2601 
2602 /* One do-while loop.  */
2603 struct pru_doloop {
2604   /* All the doloop_begins for this loop (in no particular order).  */
2605   struct pru_doloop_begin *begin;
2606 
2607   /* All the doloop_ends.  When there is more than one, arrange things
2608      so that the first one is the most likely to be X in case (2) above.  */
2609   struct pru_doloop_end *end;
2610 };
2611 
2612 
2613 /* Return true if LOOP can be converted into LOOP form
2614    (that is, if it matches cases (1) or (2) above).  */
2615 
2616 static bool
pru_repeat_loop_p(struct pru_doloop * loop)2617 pru_repeat_loop_p (struct pru_doloop *loop)
2618 {
2619   struct pru_doloop_end *end;
2620   rtx_insn *fallthrough;
2621 
2622   /* There must be exactly one doloop_begin and at least one doloop_end.  */
2623   if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0)
2624     return false;
2625 
2626   /* The first doloop_end (X) must branch back to the insn after
2627      the doloop_begin.  */
2628   if (prev_real_insn (as_a<rtx_insn *> (loop->end->label)) != loop->begin->insn)
2629     return false;
2630 
2631   /* Check that the first doloop_end (X) can actually reach
2632      doloop_begin () with U8_PCREL relocation for LOOP instruction.  */
2633   if (get_attr_length (loop->end->insn) != 4)
2634     return false;
2635 
2636   /* All the other doloop_ends must branch to the same place as X.
2637      When the branch isn't taken, they must jump to the instruction
2638      after X.  */
2639   fallthrough = loop->end->fallthrough;
2640   for (end = loop->end->next; end != 0; end = end->next)
2641     if (end->label != loop->end->label
2642 	|| !simplejump_p (end->fallthrough)
2643 	|| fallthrough
2644 	   != next_real_insn (JUMP_LABEL_AS_INSN (end->fallthrough)))
2645       return false;
2646 
2647   return true;
2648 }
2649 
2650 
2651 /* The main repeat reorg function.  See comment above for details.  */
2652 
2653 static void
pru_reorg_loop(rtx_insn * insns)2654 pru_reorg_loop (rtx_insn *insns)
2655 {
2656   rtx_insn *insn;
2657   struct pru_doloop *loops, *loop;
2658   struct pru_doloop_begin *begin;
2659   struct pru_doloop_end *end;
2660   size_t tmpsz;
2661 
2662   /* Quick exit if we haven't created any loops.  */
2663   if (cfun->machine->doloop_tags == 0)
2664     return;
2665 
2666   /* Create an array of pru_doloop structures.  */
2667   tmpsz = sizeof (loops[0]) * cfun->machine->doloop_tags;
2668   loops = (struct pru_doloop *) alloca (tmpsz);
2669   memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags);
2670 
2671   /* Search the function for do-while insns and group them by loop tag.  */
2672   for (insn = insns; insn; insn = NEXT_INSN (insn))
2673     if (INSN_P (insn))
2674       switch (recog_memoized (insn))
2675 	{
2676 	case CODE_FOR_doloop_begin_internalhi:
2677 	case CODE_FOR_doloop_begin_internalsi:
2678 	  insn_extract (insn);
2679 	  loop = &loops[INTVAL (recog_data.operand[2])];
2680 
2681 	  tmpsz = sizeof (struct pru_doloop_begin);
2682 	  begin = (struct pru_doloop_begin *) alloca (tmpsz);
2683 	  begin->next = loop->begin;
2684 	  begin->insn = insn;
2685 	  begin->loop_count = recog_data.operand[1];
2686 	  begin->counter = recog_data.operand[0];
2687 
2688 	  loop->begin = begin;
2689 	  break;
2690 
2691 	case CODE_FOR_doloop_end_internalhi:
2692 	case CODE_FOR_doloop_end_internalsi:
2693 	  insn_extract (insn);
2694 	  loop = &loops[INTVAL (recog_data.operand[2])];
2695 
2696 	  tmpsz = sizeof (struct pru_doloop_end);
2697 	  end = (struct pru_doloop_end *) alloca (tmpsz);
2698 	  end->insn = insn;
2699 	  end->fallthrough = next_real_insn (insn);
2700 	  end->counter = recog_data.operand[0];
2701 	  end->label = recog_data.operand[1];
2702 	  end->scratch = recog_data.operand[3];
2703 
2704 	  /* If this insn falls through to an unconditional jump,
2705 	     give it a lower priority than the others.  */
2706 	  if (loop->end != 0 && simplejump_p (end->fallthrough))
2707 	    {
2708 	      end->next = loop->end->next;
2709 	      loop->end->next = end;
2710 	    }
2711 	  else
2712 	    {
2713 	      end->next = loop->end;
2714 	      loop->end = end;
2715 	    }
2716 	  break;
2717 	}
2718 
2719   /* Convert the insns for each loop in turn.  */
2720   for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++)
2721     if (pru_repeat_loop_p (loop))
2722       {
2723 	/* Case (1) or (2).  */
2724 	rtx_code_label *repeat_label;
2725 	rtx label_ref;
2726 	rtx loop_rtx;
2727 
2728 	/* Create a new label for the repeat insn.  */
2729 	repeat_label = gen_label_rtx ();
2730 
2731 	/* Replace the doloop_begin with a repeat.  We get rid
2732 	   of the iteration register because LOOP instruction
2733 	   will utilize an internal for the PRU core LOOP register.  */
2734 	label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label);
2735 	machine_mode loop_mode = GET_MODE (loop->begin->loop_count);
2736 	if (loop_mode == VOIDmode)
2737 	  {
2738 	    gcc_assert (CONST_INT_P (loop->begin->loop_count));
2739 	    gcc_assert (UBYTE_INT ( INTVAL (loop->begin->loop_count)));
2740 	    loop_mode = SImode;
2741 	  }
2742 	gcc_assert (loop_mode == HImode || loop_mode == SImode);
2743 	loop_rtx = gen_pruloop (loop_mode, loop->begin->loop_count, label_ref);
2744 	emit_insn_before (loop_rtx, loop->begin->insn);
2745 
2746 	delete_insn (loop->begin->insn);
2747 
2748 	/* Insert the repeat label before the first doloop_end.
2749 	   Fill the gap with nops if LOOP insn is less than 2
2750 	   instructions away than loop->end.  */
2751 	pru_insert_loop_label_last (loop->end->insn, repeat_label,
2752 				    loop->end->next != 0);
2753 
2754 	/* Emit a pruloop_end (to improve the readability of the output).  */
2755 	emit_insn_before (gen_pruloop_end (), loop->end->insn);
2756 
2757 	/* HACK: TODO: This is usually not needed, but is required for
2758 	   a few rare cases where a JUMP that breaks the loop
2759 	   references the LOOP_END address.  In other words, since
2760 	   we're missing a real "loop_end" instruction, a loop "break"
2761 	   may accidentally reference the loop end itself, and thus
2762 	   continuing the cycle.  */
2763 	for (insn = NEXT_INSN (loop->end->insn);
2764 	     insn != next_real_insn (loop->end->insn);
2765 	     insn = NEXT_INSN (insn))
2766 	  {
2767 	    if (LABEL_P (insn) && LABEL_NUSES (insn) > 0)
2768 	      emit_insn_before (gen_nop_loop_guard (), loop->end->insn);
2769 	  }
2770 
2771 	/* Delete the first doloop_end.  */
2772 	delete_insn (loop->end->insn);
2773 
2774 	/* Replace the others with branches to REPEAT_LABEL.  */
2775 	for (end = loop->end->next; end != 0; end = end->next)
2776 	  {
2777 	    rtx_insn *newjmp;
2778 	    newjmp = emit_jump_insn_before (gen_jump (repeat_label), end->insn);
2779 	    JUMP_LABEL (newjmp) = repeat_label;
2780 	    delete_insn (end->insn);
2781 	    delete_insn (end->fallthrough);
2782 	  }
2783       }
2784     else
2785       {
2786 	/* Case (3).  First replace all the doloop_begins with setting
2787 	   the HW register used for loop counter.  */
2788 	for (begin = loop->begin; begin != 0; begin = begin->next)
2789 	  {
2790 	    insn = gen_move_insn (copy_rtx (begin->counter),
2791 				  copy_rtx (begin->loop_count));
2792 	    emit_insn_before (insn, begin->insn);
2793 	    delete_insn (begin->insn);
2794 	  }
2795 
2796 	/* Replace all the doloop_ends with decrement-and-branch sequences.  */
2797 	for (end = loop->end; end != 0; end = end->next)
2798 	  {
2799 	    rtx reg;
2800 
2801 	    start_sequence ();
2802 
2803 	    /* Load the counter value into a general register.  */
2804 	    reg = end->counter;
2805 	    if (!REG_P (reg) || REGNO (reg) > LAST_NONIO_GP_REGNUM)
2806 	      {
2807 		reg = end->scratch;
2808 		emit_move_insn (copy_rtx (reg), copy_rtx (end->counter));
2809 	      }
2810 
2811 	    /* Decrement the counter.  */
2812 	    emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg),
2813 				      constm1_rtx));
2814 
2815 	    /* Copy it back to its original location.  */
2816 	    if (reg != end->counter)
2817 	      emit_move_insn (copy_rtx (end->counter), copy_rtx (reg));
2818 
2819 	    /* Jump back to the start label.  */
2820 	    insn = emit_jump_insn (gen_cbranchsi4 (gen_rtx_NE (VOIDmode, reg,
2821 							       const0_rtx),
2822 						   reg,
2823 						   const0_rtx,
2824 						   end->label));
2825 
2826 	    JUMP_LABEL (insn) = end->label;
2827 	    LABEL_NUSES (end->label)++;
2828 
2829 	    /* Emit the whole sequence before the doloop_end.  */
2830 	    insn = get_insns ();
2831 	    end_sequence ();
2832 	    emit_insn_before (insn, end->insn);
2833 
2834 	    /* Delete the doloop_end.  */
2835 	    delete_insn (end->insn);
2836 	  }
2837       }
2838 }
2839 
2840 /* Implement TARGET_MACHINE_DEPENDENT_REORG.  */
2841 static void
pru_reorg(void)2842 pru_reorg (void)
2843 {
2844   rtx_insn *insns = get_insns ();
2845 
2846   compute_bb_for_insn ();
2847   df_analyze ();
2848 
2849   /* Need correct insn lengths for allowing LOOP instruction
2850      emitting due to U8_PCREL limitations.  */
2851   shorten_branches (get_insns ());
2852 
2853   /* The generic reorg_loops () is not suitable for PRU because
2854      it doesn't handle doloop_begin/end tying.  And we need our
2855      doloop_begin emitted before reload.  It is difficult to coalesce
2856      UBYTE constant initial loop values into the LOOP insn during
2857      machine reorg phase.  */
2858   pru_reorg_loop (insns);
2859 
2860   df_finish_pass (false);
2861 }
2862 
2863 /* Enumerate all PRU-specific builtins.  */
2864 enum pru_builtin
2865 {
2866   PRU_BUILTIN_DELAY_CYCLES,
2867   PRU_BUILTIN_HALT,
2868   PRU_BUILTIN_LMBD,
2869   PRU_BUILTIN_max
2870 };
2871 
2872 static GTY(()) tree pru_builtins [(int) PRU_BUILTIN_max];
2873 
2874 /* Implement TARGET_INIT_BUILTINS.  */
2875 
2876 static void
pru_init_builtins(void)2877 pru_init_builtins (void)
2878 {
2879   tree void_ftype_longlong
2880     = build_function_type_list (void_type_node,
2881 				long_long_integer_type_node,
2882 				NULL);
2883   tree uint_ftype_uint_uint
2884     = build_function_type_list (unsigned_type_node,
2885 				unsigned_type_node,
2886 				unsigned_type_node,
2887 				NULL);
2888 
2889   tree void_ftype_void
2890     = build_function_type_list (void_type_node,
2891 				void_type_node,
2892 				NULL);
2893 
2894   pru_builtins[PRU_BUILTIN_DELAY_CYCLES]
2895     = add_builtin_function ("__delay_cycles", void_ftype_longlong,
2896 			    PRU_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL,
2897 			    NULL_TREE);
2898 
2899   pru_builtins[PRU_BUILTIN_HALT]
2900     = add_builtin_function ("__halt", void_ftype_void,
2901 			    PRU_BUILTIN_HALT, BUILT_IN_MD, NULL,
2902 			    NULL_TREE);
2903 
2904   pru_builtins[PRU_BUILTIN_LMBD]
2905     = add_builtin_function ("__lmbd", uint_ftype_uint_uint,
2906 			    PRU_BUILTIN_LMBD, BUILT_IN_MD, NULL,
2907 			    NULL_TREE);
2908 }
2909 
2910 /* Implement TARGET_BUILTIN_DECL.  */
2911 
2912 static tree
pru_builtin_decl(unsigned code,bool initialize_p ATTRIBUTE_UNUSED)2913 pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2914 {
2915   switch (code)
2916     {
2917     case PRU_BUILTIN_DELAY_CYCLES:
2918     case PRU_BUILTIN_HALT:
2919     case PRU_BUILTIN_LMBD:
2920       return pru_builtins[code];
2921     default:
2922       return error_mark_node;
2923     }
2924 }
2925 
2926 /* Emit a sequence of one or more delay_cycles_X insns, in order to generate
2927    code that delays exactly ARG cycles.  */
2928 
2929 static rtx
pru_expand_delay_cycles(rtx arg)2930 pru_expand_delay_cycles (rtx arg)
2931 {
2932   HOST_WIDE_INT c, n;
2933 
2934   if (GET_CODE (arg) != CONST_INT)
2935     {
2936       error ("%<__delay_cycles%> only takes constant arguments");
2937       return NULL_RTX;
2938     }
2939 
2940   c = INTVAL (arg);
2941 
2942   gcc_assert (HOST_BITS_PER_WIDE_INT > 32);
2943   if (c < 0)
2944     {
2945       error ("%<__delay_cycles%> only takes non-negative cycle counts");
2946       return NULL_RTX;
2947     }
2948 
2949   emit_insn (gen_delay_cycles_start (arg));
2950 
2951   /* For 32-bit loops, there's 2 + 2x cycles.  */
2952   if (c > 2 * 0xffff + 1)
2953     {
2954       n = (c - 2) / 2;
2955       c -= (n * 2) + 2;
2956       if ((unsigned long long) n > 0xffffffffULL)
2957 	{
2958 	  error ("%<__delay_cycles%> is limited to 32-bit loop counts");
2959 	  return NULL_RTX;
2960 	}
2961       emit_insn (gen_delay_cycles_2x_plus2_si (GEN_INT (n)));
2962     }
2963 
2964   /* For 16-bit loops, there's 1 + 2x cycles.  */
2965   if (c > 2)
2966     {
2967       n = (c - 1) / 2;
2968       c -= (n * 2) + 1;
2969 
2970       emit_insn (gen_delay_cycles_2x_plus1_hi (GEN_INT (n)));
2971     }
2972 
2973   while (c > 0)
2974     {
2975       emit_insn (gen_delay_cycles_1 ());
2976       c -= 1;
2977     }
2978 
2979   emit_insn (gen_delay_cycles_end (arg));
2980 
2981   return NULL_RTX;
2982 }
2983 
2984 
2985 /* Implement TARGET_EXPAND_BUILTIN.  Expand an expression EXP that calls
2986    a built-in function, with result going to TARGET if that's convenient
2987    (and in mode MODE if that's convenient).
2988    SUBTARGET may be used as the target for computing one of EXP's operands.
2989    IGNORE is nonzero if the value is to be ignored.  */
2990 
2991 static rtx
pru_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode,int ignore ATTRIBUTE_UNUSED)2992 pru_expand_builtin (tree exp, rtx target,
2993 		    rtx subtarget ATTRIBUTE_UNUSED,
2994 		    machine_mode mode,
2995 		    int ignore ATTRIBUTE_UNUSED)
2996 {
2997   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2998   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
2999 
3000   switch (fcode)
3001     {
3002     case PRU_BUILTIN_DELAY_CYCLES:
3003 	{
3004 	  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
3005 	  return pru_expand_delay_cycles (arg1);
3006 	}
3007       break;
3008     case PRU_BUILTIN_HALT:
3009 	{
3010 	  emit_insn (gen_pru_halt ());
3011 	  return NULL_RTX;
3012 	}
3013       break;
3014     case PRU_BUILTIN_LMBD:
3015 	{
3016 	  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
3017 	  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
3018 
3019 	  if (target == NULL_RTX || GET_MODE (target) != mode)
3020 	    {
3021 	      target = gen_reg_rtx (mode);
3022 	    }
3023 
3024 	  emit_insn (gen_pru_lmbd (mode, target, arg1, arg2));
3025 	  return target;
3026 	}
3027       break;
3028     default:
3029       internal_error ("bad builtin code");
3030     }
3031 
3032   return NULL_RTX;
3033 }
3034 
3035 /* Remember the last target of pru_set_current_function.  */
3036 static GTY(()) tree pru_previous_fndecl;
3037 
3038 /* Establish appropriate back-end context for processing the function
3039    FNDECL.  The argument might be NULL to indicate processing at top
3040    level, outside of any function scope.  */
3041 static void
pru_set_current_function(tree fndecl)3042 pru_set_current_function (tree fndecl)
3043 {
3044   tree old_tree = (pru_previous_fndecl
3045 		   ? DECL_FUNCTION_SPECIFIC_TARGET (pru_previous_fndecl)
3046 		   : NULL_TREE);
3047 
3048   tree new_tree = (fndecl
3049 		   ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3050 		   : NULL_TREE);
3051 
3052   if (fndecl && fndecl != pru_previous_fndecl)
3053     {
3054       pru_previous_fndecl = fndecl;
3055       if (old_tree == new_tree)
3056 	;
3057 
3058       else if (new_tree)
3059 	{
3060 	  cl_target_option_restore (&global_options, &global_options_set,
3061 				    TREE_TARGET_OPTION (new_tree));
3062 	  target_reinit ();
3063 	}
3064 
3065       else if (old_tree)
3066 	{
3067 	  struct cl_target_option *def
3068 	    = TREE_TARGET_OPTION (target_option_current_node);
3069 
3070 	  cl_target_option_restore (&global_options, &global_options_set, def);
3071 	  target_reinit ();
3072 	}
3073     }
3074 }
3075 
3076 /* Implement TARGET_UNWIND_WORD_MODE.
3077 
3078    Since PRU is really a 32-bit CPU, the default word_mode is not suitable.  */
3079 static scalar_int_mode
pru_unwind_word_mode(void)3080 pru_unwind_word_mode (void)
3081 {
3082   return SImode;
3083 }
3084 
3085 
3086 /* Initialize the GCC target structure.  */
3087 #undef TARGET_ASM_FUNCTION_PROLOGUE
3088 #define TARGET_ASM_FUNCTION_PROLOGUE pru_asm_function_prologue
3089 #undef TARGET_ASM_INTEGER
3090 #define TARGET_ASM_INTEGER pru_assemble_integer
3091 #undef TARGET_SECTION_TYPE_FLAGS
3092 #define TARGET_SECTION_TYPE_FLAGS pru_section_type_flags
3093 
3094 #undef TARGET_ASM_FILE_START
3095 #define TARGET_ASM_FILE_START pru_file_start
3096 
3097 #undef  TARGET_INSERT_ATTRIBUTES
3098 #define TARGET_INSERT_ATTRIBUTES pru_insert_attributes
3099 
3100 #undef TARGET_INIT_BUILTINS
3101 #define TARGET_INIT_BUILTINS pru_init_builtins
3102 #undef TARGET_EXPAND_BUILTIN
3103 #define TARGET_EXPAND_BUILTIN pru_expand_builtin
3104 #undef TARGET_BUILTIN_DECL
3105 #define TARGET_BUILTIN_DECL pru_builtin_decl
3106 
3107 #undef TARGET_COMPUTE_FRAME_LAYOUT
3108 #define TARGET_COMPUTE_FRAME_LAYOUT pru_compute_frame_layout
3109 
3110 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3111 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3112 
3113 #undef TARGET_CAN_ELIMINATE
3114 #define TARGET_CAN_ELIMINATE pru_can_eliminate
3115 
3116 #undef TARGET_HARD_REGNO_MODE_OK
3117 #define TARGET_HARD_REGNO_MODE_OK pru_hard_regno_mode_ok
3118 
3119 #undef  TARGET_HARD_REGNO_SCRATCH_OK
3120 #define TARGET_HARD_REGNO_SCRATCH_OK pru_hard_regno_scratch_ok
3121 
3122 #undef TARGET_FUNCTION_ARG
3123 #define TARGET_FUNCTION_ARG pru_function_arg
3124 
3125 #undef TARGET_FUNCTION_ARG_ADVANCE
3126 #define TARGET_FUNCTION_ARG_ADVANCE pru_function_arg_advance
3127 
3128 #undef TARGET_ARG_PARTIAL_BYTES
3129 #define TARGET_ARG_PARTIAL_BYTES pru_arg_partial_bytes
3130 
3131 #undef TARGET_FUNCTION_VALUE
3132 #define TARGET_FUNCTION_VALUE pru_function_value
3133 
3134 #undef TARGET_LIBCALL_VALUE
3135 #define TARGET_LIBCALL_VALUE pru_libcall_value
3136 
3137 #undef TARGET_FUNCTION_VALUE_REGNO_P
3138 #define TARGET_FUNCTION_VALUE_REGNO_P pru_function_value_regno_p
3139 
3140 #undef TARGET_RETURN_IN_MEMORY
3141 #define TARGET_RETURN_IN_MEMORY pru_return_in_memory
3142 
3143 #undef TARGET_MUST_PASS_IN_STACK
3144 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3145 
3146 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
3147 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
3148   pru_addr_space_legitimate_address_p
3149 
3150 #undef TARGET_INIT_LIBFUNCS
3151 #define TARGET_INIT_LIBFUNCS pru_init_libfuncs
3152 #undef TARGET_LIBFUNC_GNU_PREFIX
3153 #define TARGET_LIBFUNC_GNU_PREFIX true
3154 
3155 #undef TARGET_RTX_COSTS
3156 #define TARGET_RTX_COSTS pru_rtx_costs
3157 
3158 #undef TARGET_PRINT_OPERAND
3159 #define TARGET_PRINT_OPERAND pru_print_operand
3160 
3161 #undef TARGET_PRINT_OPERAND_ADDRESS
3162 #define TARGET_PRINT_OPERAND_ADDRESS pru_print_operand_address
3163 
3164 #undef TARGET_OPTION_OVERRIDE
3165 #define TARGET_OPTION_OVERRIDE pru_option_override
3166 
3167 #undef TARGET_SET_CURRENT_FUNCTION
3168 #define TARGET_SET_CURRENT_FUNCTION pru_set_current_function
3169 
3170 #undef  TARGET_MACHINE_DEPENDENT_REORG
3171 #define TARGET_MACHINE_DEPENDENT_REORG  pru_reorg
3172 
3173 #undef  TARGET_CAN_USE_DOLOOP_P
3174 #define TARGET_CAN_USE_DOLOOP_P		pru_can_use_doloop_p
3175 
3176 #undef TARGET_INVALID_WITHIN_DOLOOP
3177 #define TARGET_INVALID_WITHIN_DOLOOP  pru_invalid_within_doloop
3178 
3179 #undef  TARGET_UNWIND_WORD_MODE
3180 #define TARGET_UNWIND_WORD_MODE pru_unwind_word_mode
3181 
3182 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
3183 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
3184 
3185 struct gcc_target targetm = TARGET_INITIALIZER;
3186 
3187 #include "gt-pru.h"
3188