xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/nds32/nds32-utils.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1cef8759bSmrg /* Auxiliary functions for pipeline descriptions pattern of Andes
2cef8759bSmrg    NDS32 cpu for GNU compiler
3*4c3eb207Smrg    Copyright (C) 2012-2020 Free Software Foundation, Inc.
4cef8759bSmrg    Contributed by Andes Technology Corporation.
5cef8759bSmrg 
6cef8759bSmrg    This file is part of GCC.
7cef8759bSmrg 
8cef8759bSmrg    GCC is free software; you can redistribute it and/or modify it
9cef8759bSmrg    under the terms of the GNU General Public License as published
10cef8759bSmrg    by the Free Software Foundation; either version 3, or (at your
11cef8759bSmrg    option) any later version.
12cef8759bSmrg 
13cef8759bSmrg    GCC is distributed in the hope that it will be useful, but WITHOUT
14cef8759bSmrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15cef8759bSmrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16cef8759bSmrg    License for more details.
17cef8759bSmrg 
18cef8759bSmrg    You should have received a copy of the GNU General Public License
19cef8759bSmrg    along with GCC; see the file COPYING3.  If not see
20cef8759bSmrg    <http://www.gnu.org/licenses/>.  */
21cef8759bSmrg 
22cef8759bSmrg /* ------------------------------------------------------------------------ */
23cef8759bSmrg 
24cef8759bSmrg #define IN_TARGET_CODE 1
25cef8759bSmrg 
26cef8759bSmrg #include "config.h"
27cef8759bSmrg #include "system.h"
28cef8759bSmrg #include "coretypes.h"
29cef8759bSmrg #include "backend.h"
30cef8759bSmrg #include "target.h"
31cef8759bSmrg #include "rtl.h"
32cef8759bSmrg #include "tree.h"
33cef8759bSmrg #include "memmodel.h"
34cef8759bSmrg #include "tm_p.h"
35cef8759bSmrg #include "optabs.h"		/* For GEN_FCN.  */
36cef8759bSmrg #include "recog.h"
37cef8759bSmrg #include "tm-constrs.h"
38cef8759bSmrg #include "insn-attr.h"
39cef8759bSmrg 
40cef8759bSmrg 
41cef8759bSmrg namespace nds32 {
42cef8759bSmrg 
43cef8759bSmrg /* Get the rtx in the PATTERN field of an insn.  If INSN is not an insn,
44cef8759bSmrg    the funciton doesn't change anything and returns it directly.  */
45cef8759bSmrg rtx
extract_pattern_from_insn(rtx insn)46cef8759bSmrg extract_pattern_from_insn (rtx insn)
47cef8759bSmrg {
48cef8759bSmrg   if (INSN_P (insn))
49cef8759bSmrg     return PATTERN (insn);
50cef8759bSmrg 
51cef8759bSmrg   return insn;
52cef8759bSmrg }
53cef8759bSmrg 
54cef8759bSmrg /* Get the number of elements in a parallel rtx.  */
55cef8759bSmrg size_t
parallel_elements(rtx parallel_rtx)56cef8759bSmrg parallel_elements (rtx parallel_rtx)
57cef8759bSmrg {
58cef8759bSmrg   parallel_rtx = extract_pattern_from_insn (parallel_rtx);
59cef8759bSmrg   gcc_assert (GET_CODE (parallel_rtx) == PARALLEL);
60cef8759bSmrg 
61cef8759bSmrg   return XVECLEN (parallel_rtx, 0);
62cef8759bSmrg }
63cef8759bSmrg 
64cef8759bSmrg /* Extract an rtx from a parallel rtx with index NTH.  If NTH is a negative
65cef8759bSmrg    value, the function returns the last NTH rtx.  */
66cef8759bSmrg rtx
parallel_element(rtx parallel_rtx,int nth)67cef8759bSmrg parallel_element (rtx parallel_rtx, int nth)
68cef8759bSmrg {
69cef8759bSmrg   parallel_rtx = extract_pattern_from_insn (parallel_rtx);
70cef8759bSmrg   gcc_assert (GET_CODE (parallel_rtx) == PARALLEL);
71cef8759bSmrg 
72cef8759bSmrg   int len = parallel_elements (parallel_rtx);
73cef8759bSmrg 
74cef8759bSmrg   if (nth >= 0)
75cef8759bSmrg     {
76cef8759bSmrg       if (nth >= len)
77cef8759bSmrg 	return NULL_RTX;
78cef8759bSmrg 
79cef8759bSmrg       return XVECEXP (parallel_rtx, 0, nth);
80cef8759bSmrg     }
81cef8759bSmrg   else
82cef8759bSmrg     {
83cef8759bSmrg       if (len + nth < 0)
84cef8759bSmrg 	return NULL_RTX;
85cef8759bSmrg 
86cef8759bSmrg       return XVECEXP (parallel_rtx, 0, len + nth);
87cef8759bSmrg     }
88cef8759bSmrg }
89cef8759bSmrg 
90cef8759bSmrg /* Functions to determine whether INSN is single-word, double-word
91cef8759bSmrg    or partial-word load/store insn.  */
92cef8759bSmrg 
93cef8759bSmrg bool
load_single_p(rtx_insn * insn)94cef8759bSmrg load_single_p (rtx_insn *insn)
95cef8759bSmrg {
96cef8759bSmrg   if (get_attr_type (insn) != TYPE_LOAD)
97cef8759bSmrg     return false;
98cef8759bSmrg 
99cef8759bSmrg   if (INSN_CODE (insn) == CODE_FOR_move_di ||
100cef8759bSmrg       INSN_CODE (insn) == CODE_FOR_move_df)
101cef8759bSmrg     return false;
102cef8759bSmrg 
103cef8759bSmrg   return true;
104cef8759bSmrg }
105cef8759bSmrg 
106cef8759bSmrg bool
store_single_p(rtx_insn * insn)107cef8759bSmrg store_single_p (rtx_insn *insn)
108cef8759bSmrg {
109cef8759bSmrg   if (get_attr_type (insn) != TYPE_STORE)
110cef8759bSmrg     return false;
111cef8759bSmrg 
112cef8759bSmrg   if (INSN_CODE (insn) == CODE_FOR_move_di ||
113cef8759bSmrg       INSN_CODE (insn) == CODE_FOR_move_df)
114cef8759bSmrg     return false;
115cef8759bSmrg 
116cef8759bSmrg   return true;
117cef8759bSmrg }
118cef8759bSmrg 
119cef8759bSmrg bool
load_double_p(rtx_insn * insn)120cef8759bSmrg load_double_p (rtx_insn *insn)
121cef8759bSmrg {
122cef8759bSmrg   if (get_attr_type (insn) != TYPE_LOAD)
123cef8759bSmrg     return false;
124cef8759bSmrg 
125cef8759bSmrg   if (INSN_CODE (insn) != CODE_FOR_move_di &&
126cef8759bSmrg       INSN_CODE (insn) != CODE_FOR_move_df)
127cef8759bSmrg     return false;
128cef8759bSmrg 
129cef8759bSmrg   return true;
130cef8759bSmrg }
131cef8759bSmrg 
132cef8759bSmrg bool
store_double_p(rtx_insn * insn)133cef8759bSmrg store_double_p (rtx_insn *insn)
134cef8759bSmrg {
135cef8759bSmrg   if (get_attr_type (insn) != TYPE_STORE)
136cef8759bSmrg     return false;
137cef8759bSmrg 
138cef8759bSmrg   if (INSN_CODE (insn) != CODE_FOR_move_di &&
139cef8759bSmrg       INSN_CODE (insn) != CODE_FOR_move_df)
140cef8759bSmrg     return false;
141cef8759bSmrg 
142cef8759bSmrg   return true;
143cef8759bSmrg }
144cef8759bSmrg 
145627f7eb2Smrg bool
store_offset_reg_p(rtx_insn * insn)146627f7eb2Smrg store_offset_reg_p (rtx_insn *insn)
147627f7eb2Smrg {
148627f7eb2Smrg   if (get_attr_type (insn) != TYPE_STORE)
149627f7eb2Smrg     return false;
150627f7eb2Smrg 
151627f7eb2Smrg   rtx offset_rtx = extract_offset_rtx (insn);
152627f7eb2Smrg 
153627f7eb2Smrg   if (offset_rtx == NULL_RTX)
154627f7eb2Smrg     return false;
155627f7eb2Smrg 
156627f7eb2Smrg   if (REG_P (offset_rtx))
157627f7eb2Smrg     return true;
158627f7eb2Smrg 
159627f7eb2Smrg   return false;
160627f7eb2Smrg }
161627f7eb2Smrg 
162cef8759bSmrg /* Determine if INSN is a post update insn.  */
163cef8759bSmrg bool
post_update_insn_p(rtx_insn * insn)164cef8759bSmrg post_update_insn_p (rtx_insn *insn)
165cef8759bSmrg {
166cef8759bSmrg   if (find_post_update_rtx (insn) == -1)
167cef8759bSmrg     return false;
168cef8759bSmrg   else
169cef8759bSmrg     return true;
170cef8759bSmrg }
171cef8759bSmrg 
172cef8759bSmrg /* Check if the address of MEM_RTX consists of a base register and an
173cef8759bSmrg    immediate offset.  */
174cef8759bSmrg bool
immed_offset_p(rtx mem_rtx)175cef8759bSmrg immed_offset_p (rtx mem_rtx)
176cef8759bSmrg {
177cef8759bSmrg   gcc_assert (MEM_P (mem_rtx));
178cef8759bSmrg 
179cef8759bSmrg   rtx addr_rtx = XEXP (mem_rtx, 0);
180cef8759bSmrg 
181cef8759bSmrg   /* (mem (reg)) is equivalent to (mem (plus (reg) (const_int 0))) */
182cef8759bSmrg   if (REG_P (addr_rtx))
183cef8759bSmrg     return true;
184cef8759bSmrg 
185cef8759bSmrg   /* (mem (plus (reg) (const_int))) */
186cef8759bSmrg   if (GET_CODE (addr_rtx) == PLUS
187cef8759bSmrg       && GET_CODE (XEXP (addr_rtx, 1)) == CONST_INT)
188cef8759bSmrg     return true;
189cef8759bSmrg 
190cef8759bSmrg   return false;
191cef8759bSmrg }
192cef8759bSmrg 
193cef8759bSmrg /* Find the post update rtx in INSN.  If INSN is a load/store multiple insn,
194cef8759bSmrg    the function returns the vector index of its parallel part.  If INSN is a
195cef8759bSmrg    single load/store insn, the function returns 0.  If INSN is not a post-
196cef8759bSmrg    update insn, the function returns -1.  */
197cef8759bSmrg int
find_post_update_rtx(rtx_insn * insn)198cef8759bSmrg find_post_update_rtx (rtx_insn *insn)
199cef8759bSmrg {
200cef8759bSmrg   rtx mem_rtx;
201cef8759bSmrg   int i, len;
202cef8759bSmrg 
203cef8759bSmrg   switch (get_attr_type (insn))
204cef8759bSmrg     {
205cef8759bSmrg     case TYPE_LOAD_MULTIPLE:
206cef8759bSmrg     case TYPE_STORE_MULTIPLE:
207cef8759bSmrg       /* Find a pattern in a parallel rtx:
208cef8759bSmrg 	 (set (reg) (plus (reg) (const_int)))  */
209cef8759bSmrg       len = parallel_elements (insn);
210cef8759bSmrg       for (i = 0; i < len; ++i)
211cef8759bSmrg 	{
212cef8759bSmrg 	  rtx curr_insn = parallel_element (insn, i);
213cef8759bSmrg 
214cef8759bSmrg 	  if (GET_CODE (curr_insn) == SET
215cef8759bSmrg 	      && REG_P (SET_DEST (curr_insn))
216cef8759bSmrg 	      && GET_CODE (SET_SRC (curr_insn)) == PLUS)
217cef8759bSmrg 		return i;
218cef8759bSmrg 	}
219cef8759bSmrg       return -1;
220cef8759bSmrg 
221cef8759bSmrg     case TYPE_LOAD:
222cef8759bSmrg     case TYPE_FLOAD:
223cef8759bSmrg     case TYPE_STORE:
224cef8759bSmrg     case TYPE_FSTORE:
225cef8759bSmrg       mem_rtx = extract_mem_rtx (insn);
226cef8759bSmrg       /* (mem (post_inc (reg)))  */
227cef8759bSmrg       switch (GET_CODE (XEXP (mem_rtx, 0)))
228cef8759bSmrg 	{
229cef8759bSmrg 	case POST_INC:
230cef8759bSmrg 	case POST_DEC:
231cef8759bSmrg 	case POST_MODIFY:
232cef8759bSmrg 	  return 0;
233cef8759bSmrg 
234cef8759bSmrg 	default:
235cef8759bSmrg 	  return -1;
236cef8759bSmrg 	}
237cef8759bSmrg 
238cef8759bSmrg     default:
239cef8759bSmrg       gcc_unreachable ();
240cef8759bSmrg     }
241cef8759bSmrg }
242cef8759bSmrg 
243cef8759bSmrg /* Extract the MEM rtx from a load/store insn.  */
244cef8759bSmrg rtx
extract_mem_rtx(rtx_insn * insn)245cef8759bSmrg extract_mem_rtx (rtx_insn *insn)
246cef8759bSmrg {
247cef8759bSmrg   rtx body = PATTERN (insn);
248cef8759bSmrg 
249cef8759bSmrg   switch (get_attr_type (insn))
250cef8759bSmrg     {
251cef8759bSmrg     case TYPE_LOAD:
252cef8759bSmrg     case TYPE_FLOAD:
253cef8759bSmrg       if (MEM_P (SET_SRC (body)))
254cef8759bSmrg 	return SET_SRC (body);
255cef8759bSmrg 
256cef8759bSmrg       /* unaligned address: (unspec [(mem)])  */
257cef8759bSmrg       if (GET_CODE (SET_SRC (body)) == UNSPEC)
258cef8759bSmrg 	{
259cef8759bSmrg 	  gcc_assert (MEM_P (XVECEXP (SET_SRC (body), 0, 0)));
260cef8759bSmrg 	  return XVECEXP (SET_SRC (body), 0, 0);
261cef8759bSmrg 	}
262cef8759bSmrg 
263cef8759bSmrg       /* (sign_extend (mem)) */
264cef8759bSmrg       gcc_assert (MEM_P (XEXP (SET_SRC (body), 0)));
265cef8759bSmrg       return XEXP (SET_SRC (body), 0);
266cef8759bSmrg 
267cef8759bSmrg     case TYPE_STORE:
268cef8759bSmrg     case TYPE_FSTORE:
269cef8759bSmrg       if (MEM_P (SET_DEST (body)))
270cef8759bSmrg 	return SET_DEST (body);
271cef8759bSmrg 
272cef8759bSmrg       /* unaligned address: (unspec [(mem)])  */
273cef8759bSmrg       if (GET_CODE (SET_DEST (body)) == UNSPEC)
274cef8759bSmrg 	{
275cef8759bSmrg 	  gcc_assert (MEM_P (XVECEXP (SET_DEST (body), 0, 0)));
276cef8759bSmrg 	  return XVECEXP (SET_DEST (body), 0, 0);
277cef8759bSmrg 	}
278cef8759bSmrg 
279cef8759bSmrg       /* (sign_extend (mem)) */
280cef8759bSmrg       gcc_assert (MEM_P (XEXP (SET_DEST (body), 0)));
281cef8759bSmrg       return XEXP (SET_DEST (body), 0);
282cef8759bSmrg 
283cef8759bSmrg     default:
284cef8759bSmrg       gcc_unreachable ();
285cef8759bSmrg     }
286cef8759bSmrg }
287cef8759bSmrg 
288cef8759bSmrg /* Extract the base register from load/store insns.  The function returns
289cef8759bSmrg    NULL_RTX if the address is not consist of any registers.  */
290cef8759bSmrg rtx
extract_base_reg(rtx_insn * insn)291cef8759bSmrg extract_base_reg (rtx_insn *insn)
292cef8759bSmrg {
293cef8759bSmrg   int post_update_rtx_index;
294cef8759bSmrg   rtx mem_rtx;
295cef8759bSmrg   rtx plus_rtx;
296cef8759bSmrg 
297cef8759bSmrg   /* Find the MEM rtx.  If we can find an insn updating the base register,
298cef8759bSmrg      the base register will be returned directly.  */
299cef8759bSmrg   switch (get_attr_type (insn))
300cef8759bSmrg     {
301cef8759bSmrg     case TYPE_LOAD_MULTIPLE:
302cef8759bSmrg       post_update_rtx_index = find_post_update_rtx (insn);
303cef8759bSmrg 
304cef8759bSmrg       if (post_update_rtx_index != -1)
305cef8759bSmrg         return SET_DEST (parallel_element (insn, post_update_rtx_index));
306cef8759bSmrg 
307cef8759bSmrg       mem_rtx = SET_SRC (parallel_element (insn, 0));
308cef8759bSmrg       break;
309cef8759bSmrg 
310cef8759bSmrg     case TYPE_STORE_MULTIPLE:
311cef8759bSmrg       post_update_rtx_index = find_post_update_rtx (insn);
312cef8759bSmrg 
313cef8759bSmrg       if (post_update_rtx_index != -1)
314cef8759bSmrg         return SET_DEST (parallel_element (insn, post_update_rtx_index));
315cef8759bSmrg 
316cef8759bSmrg       mem_rtx = SET_DEST (parallel_element (insn, 0));
317cef8759bSmrg       break;
318cef8759bSmrg 
319cef8759bSmrg     case TYPE_LOAD:
320cef8759bSmrg     case TYPE_FLOAD:
321cef8759bSmrg     case TYPE_STORE:
322cef8759bSmrg     case TYPE_FSTORE:
323cef8759bSmrg       mem_rtx = extract_mem_rtx (insn);
324cef8759bSmrg       break;
325cef8759bSmrg 
326cef8759bSmrg     default:
327cef8759bSmrg       gcc_unreachable ();
328cef8759bSmrg     }
329cef8759bSmrg 
330cef8759bSmrg   gcc_assert (MEM_P (mem_rtx));
331cef8759bSmrg 
332cef8759bSmrg   /* (mem (reg))  */
333cef8759bSmrg   if (REG_P (XEXP (mem_rtx, 0)))
334cef8759bSmrg     return XEXP (mem_rtx, 0);
335cef8759bSmrg 
336627f7eb2Smrg   /* (mem (lo_sum (reg) (symbol_ref)) */
337627f7eb2Smrg   if (GET_CODE (XEXP (mem_rtx, 0)) == LO_SUM)
338627f7eb2Smrg     return XEXP (XEXP (mem_rtx, 0), 0);
339627f7eb2Smrg 
340cef8759bSmrg   plus_rtx = XEXP (mem_rtx, 0);
341cef8759bSmrg 
342cef8759bSmrg   if (GET_CODE (plus_rtx) == SYMBOL_REF
343cef8759bSmrg       || GET_CODE (plus_rtx) == CONST)
344cef8759bSmrg     return NULL_RTX;
345cef8759bSmrg 
346627f7eb2Smrg   /* (mem (plus (reg) (const_int))) or
347627f7eb2Smrg      (mem (plus (mult (reg) (const_int 4)) (reg))) or
348627f7eb2Smrg      (mem (post_inc (reg))) or
349627f7eb2Smrg      (mem (post_dec (reg))) or
350627f7eb2Smrg      (mem (post_modify (reg) (plus (reg) (reg))))  */
351cef8759bSmrg   gcc_assert (GET_CODE (plus_rtx) == PLUS
352cef8759bSmrg 	      || GET_CODE (plus_rtx) == POST_INC
353cef8759bSmrg 	      || GET_CODE (plus_rtx) == POST_DEC
354cef8759bSmrg 	      || GET_CODE (plus_rtx) == POST_MODIFY);
355627f7eb2Smrg 
356627f7eb2Smrg   if (REG_P (XEXP (plus_rtx, 0)))
357cef8759bSmrg     return XEXP (plus_rtx, 0);
358627f7eb2Smrg 
359627f7eb2Smrg   gcc_assert (REG_P (XEXP (plus_rtx, 1)));
360627f7eb2Smrg   return XEXP (plus_rtx, 1);
361627f7eb2Smrg }
362627f7eb2Smrg 
363627f7eb2Smrg /* Extract the offset rtx from load/store insns.  The function returns
364627f7eb2Smrg    NULL_RTX if offset is absent.  */
365627f7eb2Smrg rtx
extract_offset_rtx(rtx_insn * insn)366627f7eb2Smrg extract_offset_rtx (rtx_insn *insn)
367627f7eb2Smrg {
368627f7eb2Smrg   rtx mem_rtx;
369627f7eb2Smrg   rtx plus_rtx;
370627f7eb2Smrg   rtx offset_rtx;
371627f7eb2Smrg 
372627f7eb2Smrg   /* Find the MEM rtx.  The multiple load/store insns doens't have
373627f7eb2Smrg      the offset field so we can return NULL_RTX here.  */
374627f7eb2Smrg   switch (get_attr_type (insn))
375627f7eb2Smrg     {
376627f7eb2Smrg     case TYPE_LOAD_MULTIPLE:
377627f7eb2Smrg     case TYPE_STORE_MULTIPLE:
378627f7eb2Smrg       return NULL_RTX;
379627f7eb2Smrg 
380627f7eb2Smrg     case TYPE_LOAD:
381627f7eb2Smrg     case TYPE_FLOAD:
382627f7eb2Smrg     case TYPE_STORE:
383627f7eb2Smrg     case TYPE_FSTORE:
384627f7eb2Smrg       mem_rtx = extract_mem_rtx (insn);
385627f7eb2Smrg       break;
386627f7eb2Smrg 
387627f7eb2Smrg     default:
388627f7eb2Smrg       gcc_unreachable ();
389627f7eb2Smrg     }
390627f7eb2Smrg 
391627f7eb2Smrg   gcc_assert (MEM_P (mem_rtx));
392627f7eb2Smrg 
393627f7eb2Smrg   /* (mem (reg))  */
394627f7eb2Smrg   if (REG_P (XEXP (mem_rtx, 0)))
395627f7eb2Smrg     return NULL_RTX;
396627f7eb2Smrg 
397627f7eb2Smrg   plus_rtx = XEXP (mem_rtx, 0);
398627f7eb2Smrg 
399627f7eb2Smrg   switch (GET_CODE (plus_rtx))
400627f7eb2Smrg     {
401627f7eb2Smrg     case SYMBOL_REF:
402627f7eb2Smrg     case CONST:
403627f7eb2Smrg     case POST_INC:
404627f7eb2Smrg     case POST_DEC:
405627f7eb2Smrg       return NULL_RTX;
406627f7eb2Smrg 
407627f7eb2Smrg     case PLUS:
408627f7eb2Smrg       /* (mem (plus (reg) (const_int))) or
409627f7eb2Smrg          (mem (plus (mult (reg) (const_int 4)) (reg))) */
410627f7eb2Smrg       if (REG_P (XEXP (plus_rtx, 0)))
411627f7eb2Smrg         offset_rtx = XEXP (plus_rtx, 1);
412627f7eb2Smrg       else
413627f7eb2Smrg 	{
414627f7eb2Smrg 	  gcc_assert (REG_P (XEXP (plus_rtx, 1)));
415627f7eb2Smrg 	  offset_rtx = XEXP (plus_rtx, 0);
416627f7eb2Smrg 	}
417627f7eb2Smrg 
418627f7eb2Smrg       if (ARITHMETIC_P (offset_rtx))
419627f7eb2Smrg 	{
420627f7eb2Smrg 	  gcc_assert (GET_CODE (offset_rtx) == MULT);
421627f7eb2Smrg 	  gcc_assert (REG_P (XEXP (offset_rtx, 0)));
422627f7eb2Smrg 	  offset_rtx = XEXP (offset_rtx, 0);
423627f7eb2Smrg 	}
424627f7eb2Smrg       break;
425627f7eb2Smrg 
426627f7eb2Smrg     case LO_SUM:
427627f7eb2Smrg       /* (mem (lo_sum (reg) (symbol_ref)) */
428627f7eb2Smrg       offset_rtx = XEXP (plus_rtx, 1);
429627f7eb2Smrg       break;
430627f7eb2Smrg 
431627f7eb2Smrg     case POST_MODIFY:
432627f7eb2Smrg       /* (mem (post_modify (reg) (plus (reg) (reg / const_int)))) */
433627f7eb2Smrg       gcc_assert (REG_P (XEXP (plus_rtx, 0)));
434627f7eb2Smrg       plus_rtx = XEXP (plus_rtx, 1);
435627f7eb2Smrg       gcc_assert (GET_CODE (plus_rtx) == PLUS);
436627f7eb2Smrg       offset_rtx = XEXP (plus_rtx, 0);
437627f7eb2Smrg       break;
438627f7eb2Smrg 
439627f7eb2Smrg     default:
440627f7eb2Smrg       gcc_unreachable ();
441627f7eb2Smrg     }
442627f7eb2Smrg 
443627f7eb2Smrg   return offset_rtx;
444cef8759bSmrg }
445cef8759bSmrg 
446cef8759bSmrg /* Extract the register of the shift operand from an ALU_SHIFT rtx.  */
447cef8759bSmrg rtx
extract_shift_reg(rtx alu_shift_rtx)448cef8759bSmrg extract_shift_reg (rtx alu_shift_rtx)
449cef8759bSmrg {
450cef8759bSmrg   alu_shift_rtx = extract_pattern_from_insn (alu_shift_rtx);
451cef8759bSmrg 
452cef8759bSmrg   rtx alu_rtx = SET_SRC (alu_shift_rtx);
453cef8759bSmrg   rtx shift_rtx;
454cef8759bSmrg 
455cef8759bSmrg   /* Various forms of ALU_SHIFT can be made by the combiner.
456cef8759bSmrg      See the difference between add_slli and sub_slli in nds32.md.  */
457cef8759bSmrg   if (REG_P (XEXP (alu_rtx, 0)))
458cef8759bSmrg     shift_rtx = XEXP (alu_rtx, 1);
459cef8759bSmrg   else
460cef8759bSmrg     shift_rtx = XEXP (alu_rtx, 0);
461cef8759bSmrg 
462cef8759bSmrg   return XEXP (shift_rtx, 0);
463cef8759bSmrg }
464cef8759bSmrg 
465cef8759bSmrg /* Check if INSN is a movd44 insn.  */
466cef8759bSmrg bool
movd44_insn_p(rtx_insn * insn)467cef8759bSmrg movd44_insn_p (rtx_insn *insn)
468cef8759bSmrg {
469cef8759bSmrg   if (get_attr_type (insn) == TYPE_ALU
470cef8759bSmrg       && (INSN_CODE (insn) == CODE_FOR_move_di
471cef8759bSmrg 	  || INSN_CODE (insn) == CODE_FOR_move_df))
472cef8759bSmrg     {
473cef8759bSmrg       rtx body = PATTERN (insn);
474cef8759bSmrg       gcc_assert (GET_CODE (body) == SET);
475cef8759bSmrg 
476cef8759bSmrg       rtx src = SET_SRC (body);
477cef8759bSmrg       rtx dest = SET_DEST (body);
478cef8759bSmrg 
479cef8759bSmrg       if ((REG_P (src) || GET_CODE (src) == SUBREG)
480cef8759bSmrg 	  && (REG_P (dest) || GET_CODE (dest) == SUBREG))
481cef8759bSmrg 	return true;
482cef8759bSmrg 
483cef8759bSmrg       return false;
484cef8759bSmrg     }
485cef8759bSmrg 
486cef8759bSmrg   return false;
487cef8759bSmrg }
488cef8759bSmrg 
489cef8759bSmrg /* Extract the second result (odd reg) of a movd44 insn.  */
490cef8759bSmrg rtx
extract_movd44_odd_reg(rtx_insn * insn)491cef8759bSmrg extract_movd44_odd_reg (rtx_insn *insn)
492cef8759bSmrg {
493cef8759bSmrg   gcc_assert (movd44_insn_p (insn));
494cef8759bSmrg 
495cef8759bSmrg   rtx def_reg = SET_DEST (PATTERN (insn));
496cef8759bSmrg   machine_mode mode;
497cef8759bSmrg 
498cef8759bSmrg   gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG);
499cef8759bSmrg   switch (GET_MODE (def_reg))
500cef8759bSmrg     {
501cef8759bSmrg     case E_DImode:
502cef8759bSmrg       mode = SImode;
503cef8759bSmrg       break;
504cef8759bSmrg 
505cef8759bSmrg     case E_DFmode:
506cef8759bSmrg       mode = SFmode;
507cef8759bSmrg       break;
508cef8759bSmrg 
509cef8759bSmrg     default:
510cef8759bSmrg       gcc_unreachable ();
511cef8759bSmrg     }
512cef8759bSmrg 
513cef8759bSmrg   return gen_highpart (mode, def_reg);
514cef8759bSmrg }
515cef8759bSmrg 
516cef8759bSmrg /* Extract the rtx representing non-accumulation operands of a MAC insn.  */
517cef8759bSmrg rtx
extract_mac_non_acc_rtx(rtx_insn * insn)518cef8759bSmrg extract_mac_non_acc_rtx (rtx_insn *insn)
519cef8759bSmrg {
520cef8759bSmrg   rtx exp = SET_SRC (PATTERN (insn));
521cef8759bSmrg 
522cef8759bSmrg   switch (get_attr_type (insn))
523cef8759bSmrg     {
524cef8759bSmrg     case TYPE_MAC:
525627f7eb2Smrg     case TYPE_DMAC:
526cef8759bSmrg       if (REG_P (XEXP (exp, 0)))
527cef8759bSmrg 	return XEXP (exp, 1);
528cef8759bSmrg       else
529cef8759bSmrg 	return XEXP (exp, 0);
530cef8759bSmrg 
531cef8759bSmrg     default:
532cef8759bSmrg       gcc_unreachable ();
533cef8759bSmrg     }
534cef8759bSmrg }
535cef8759bSmrg 
536627f7eb2Smrg /* Check if the DIV insn needs two write ports.  */
537627f7eb2Smrg bool
divmod_p(rtx_insn * insn)538627f7eb2Smrg divmod_p (rtx_insn *insn)
539627f7eb2Smrg {
540627f7eb2Smrg   gcc_assert (get_attr_type (insn) == TYPE_DIV);
541627f7eb2Smrg 
542627f7eb2Smrg   if (INSN_CODE (insn) == CODE_FOR_divmodsi4
543627f7eb2Smrg       || INSN_CODE (insn) == CODE_FOR_udivmodsi4)
544627f7eb2Smrg     return true;
545627f7eb2Smrg 
546627f7eb2Smrg   return false;
547627f7eb2Smrg }
548627f7eb2Smrg 
549cef8759bSmrg /* Extract the rtx representing the branch target to help recognize
550cef8759bSmrg    data hazards.  */
551cef8759bSmrg rtx
extract_branch_target_rtx(rtx_insn * insn)552cef8759bSmrg extract_branch_target_rtx (rtx_insn *insn)
553cef8759bSmrg {
554cef8759bSmrg   gcc_assert (CALL_P (insn) || JUMP_P (insn));
555cef8759bSmrg 
556cef8759bSmrg   rtx body = PATTERN (insn);
557cef8759bSmrg 
558cef8759bSmrg   if (GET_CODE (body) == SET)
559cef8759bSmrg     {
560cef8759bSmrg       /* RTXs in IF_THEN_ELSE are branch conditions.  */
561cef8759bSmrg       if (GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)
562cef8759bSmrg         return NULL_RTX;
563cef8759bSmrg 
564cef8759bSmrg       return SET_SRC (body);
565cef8759bSmrg     }
566cef8759bSmrg 
567cef8759bSmrg   if (GET_CODE (body) == CALL)
568cef8759bSmrg     return XEXP (body, 0);
569cef8759bSmrg 
570cef8759bSmrg   if (GET_CODE (body) == PARALLEL)
571cef8759bSmrg     {
572cef8759bSmrg       rtx first_rtx = parallel_element (body, 0);
573cef8759bSmrg 
574cef8759bSmrg       if (GET_CODE (first_rtx) == SET)
575cef8759bSmrg 	return SET_SRC (first_rtx);
576cef8759bSmrg 
577cef8759bSmrg       if (GET_CODE (first_rtx) == CALL)
578cef8759bSmrg 	return XEXP (first_rtx, 0);
579cef8759bSmrg     }
580cef8759bSmrg 
581cef8759bSmrg   /* Handle special cases of bltzal, bgezal and jralnez.  */
582cef8759bSmrg   if (GET_CODE (body) == COND_EXEC)
583cef8759bSmrg     {
584cef8759bSmrg       rtx addr_rtx = XEXP (body, 1);
585cef8759bSmrg 
586cef8759bSmrg       if (GET_CODE (addr_rtx) == SET)
587cef8759bSmrg 	return SET_SRC (addr_rtx);
588cef8759bSmrg 
589cef8759bSmrg       if (GET_CODE (addr_rtx) == PARALLEL)
590cef8759bSmrg 	{
591cef8759bSmrg 	  rtx first_rtx = parallel_element (addr_rtx, 0);
592cef8759bSmrg 
593cef8759bSmrg 	  if (GET_CODE (first_rtx) == SET)
594cef8759bSmrg 	    {
595cef8759bSmrg 	      rtx call_rtx = SET_SRC (first_rtx);
596cef8759bSmrg 	      gcc_assert (GET_CODE (call_rtx) == CALL);
597cef8759bSmrg 
598cef8759bSmrg 	      return XEXP (call_rtx, 0);
599cef8759bSmrg 	    }
600cef8759bSmrg 
601cef8759bSmrg 	  if (GET_CODE (first_rtx) == CALL)
602cef8759bSmrg 	    return XEXP (first_rtx, 0);
603cef8759bSmrg 	}
604cef8759bSmrg     }
605cef8759bSmrg 
606cef8759bSmrg   gcc_unreachable ();
607cef8759bSmrg }
608cef8759bSmrg 
609cef8759bSmrg /* Extract the rtx representing the branch condition to help recognize
610cef8759bSmrg    data hazards.  */
611cef8759bSmrg rtx
extract_branch_condition_rtx(rtx_insn * insn)612cef8759bSmrg extract_branch_condition_rtx (rtx_insn *insn)
613cef8759bSmrg {
614cef8759bSmrg   gcc_assert (CALL_P (insn) || JUMP_P (insn));
615cef8759bSmrg 
616cef8759bSmrg   rtx body = PATTERN (insn);
617cef8759bSmrg 
618cef8759bSmrg   if (GET_CODE (body) == SET)
619cef8759bSmrg     {
620cef8759bSmrg       rtx if_then_else_rtx = SET_SRC (body);
621cef8759bSmrg 
622cef8759bSmrg       if (GET_CODE (if_then_else_rtx) == IF_THEN_ELSE)
623cef8759bSmrg         return XEXP (if_then_else_rtx, 0);
624cef8759bSmrg 
625cef8759bSmrg       return NULL_RTX;
626cef8759bSmrg     }
627cef8759bSmrg 
628cef8759bSmrg   if (GET_CODE (body) == COND_EXEC)
629cef8759bSmrg     return XEXP (body, 0);
630cef8759bSmrg 
631cef8759bSmrg   return NULL_RTX;
632cef8759bSmrg }
633cef8759bSmrg 
634cef8759bSmrg } // namespace nds32
635