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