[committed] Fix RISC-V missing stack tie
[official-gcc.git] / gcc / config / riscv / thead.md
blob5c7d4beb1b66cc8494df0f4cf572dfd0987830d7
1 ;; Machine description for T-Head vendor extensions
2 ;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 ;; This file is part of GCC.
6 ;; GCC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version 3, or (at your option)
9 ;; any later version.
11 ;; GCC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;; GNU General Public License for more details.
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING3.  If not see
18 ;; <http://www.gnu.org/licenses/>.
20 ;; XTheadBa
22 (define_insn "*th_addsl<mode>4"
23   [(set (match_operand:X 0 "register_operand" "=r")
24         (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
25                           (match_operand:QI 2 "imm123_operand" "Ds3"))
26                 (match_operand:X 3 "register_operand" "r")))]
27   "TARGET_XTHEADBA"
28   "th.addsl\t%0,%3,%1,%2"
29   [(set_attr "type" "bitmanip")
30    (set_attr "mode" "<X:MODE>")])
32 ;; XTheadBb
34 (define_insn "*th_srri<mode>3"
35   [(set (match_operand:GPR 0 "register_operand" "=r")
36         (rotatert:GPR (match_operand:GPR 1 "register_operand" "r")
37                      (match_operand 2 "const_int_operand" "n")))]
38   "TARGET_XTHEADBB && (TARGET_64BIT || <MODE>mode == SImode)"
39   {
40     bool wform = TARGET_64BIT && (<MODE>mode == SImode);
41     operands[2] = GEN_INT (INTVAL (operands[2])
42                   & (GET_MODE_BITSIZE (<MODE>mode) - 1));
43     return wform ? "th.srriw\t%0,%1,%2" : "th.srri\t%0,%1,%2";
44   }
45   [(set_attr "type" "bitmanip")
46    (set_attr "mode" "<GPR:MODE>")])
48 (define_insn "*th_ext<mode>4"
49   [(set (match_operand:GPR 0 "register_operand" "=r")
50         (sign_extract:GPR (match_operand:GPR 1 "register_operand" "r")
51                         (match_operand 2 "const_int_operand")
52                         (match_operand 3 "const_int_operand")))]
53   "TARGET_XTHEADBB"
55   operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
56   return "th.ext\t%0,%1,%2,%3";
58   [(set_attr "type" "bitmanip")
59    (set_attr "mode" "<GPR:MODE>")])
61 (define_insn "*extendhi<SUPERQI:mode>2_th_ext"
62   [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
63         (sign_extend:SUPERQI
64             (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
65   "TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
66   "@
67    th.ext\t%0,%1,15,0
68    lh\t%0,%1"
69   [(set_attr "type" "bitmanip,load")
70    (set_attr "mode" "<SUPERQI:MODE>")])
72 (define_insn "*extendqi<SUPERQI:mode>2_th_ext"
73   [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
74         (sign_extend:SUPERQI
75             (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
76   "TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
77   "@
78    th.ext\t%0,%1,7,0
79    lb\t%0,%1"
80   [(set_attr "type" "bitmanip,load")
81    (set_attr "mode" "<SUPERQI:MODE>")])
83 (define_insn "*th_extu<mode>4"
84   [(set (match_operand:GPR 0 "register_operand" "=r")
85         (zero_extract:GPR (match_operand:GPR 1 "register_operand" "r")
86                         (match_operand 2 "const_int_operand")
87                         (match_operand 3 "const_int_operand")))]
88   "TARGET_XTHEADBB"
90   operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
91   return "th.extu\t%0,%1,%2,%3";
93   [(set_attr "type" "bitmanip")
94    (set_attr "mode" "<GPR:MODE>")])
96 (define_insn "*zero_extendsidi2_th_extu"
97   [(set (match_operand:DI 0 "register_operand" "=r,r")
98         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
99   "TARGET_64BIT && TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
100   "@
101    th.extu\t%0,%1,31,0
102    lwu\t%0,%1"
103   [(set_attr "type" "bitmanip,load")
104    (set_attr "mode" "DI")])
106 (define_insn "*zero_extendhi<GPR:mode>2_th_extu"
107   [(set (match_operand:GPR 0 "register_operand" "=r,r")
108         (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
109   "TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
110   "@
111    th.extu\t%0,%1,15,0
112    lhu\t%0,%1"
113   [(set_attr "type" "bitmanip,load")
114    (set_attr "mode" "<GPR:MODE>")])
116 (define_insn "*th_clz<mode>2"
117   [(set (match_operand:X 0 "register_operand" "=r")
118         (clz:X (match_operand:X 1 "register_operand" "r")))]
119   "TARGET_XTHEADBB"
120   "th.ff1\t%0,%1"
121   [(set_attr "type" "bitmanip")
122    (set_attr "mode" "<X:MODE>")])
124 (define_insn "th_rev<mode>2"
125   [(set (match_operand:GPR 0 "register_operand" "=r")
126         (bswap:GPR (match_operand:GPR 1 "register_operand" "r")))]
127   "TARGET_XTHEADBB && (TARGET_64BIT || <MODE>mode == SImode)"
128   {
129     bool wform = TARGET_64BIT && (<MODE>mode == SImode);
130     return wform ? "th.revw\t%0,%1" : "th.rev\t%0,%1";
131   }
132   [(set_attr "type" "bitmanip")
133    (set_attr "mode" "<GPR:MODE>")])
135 (define_insn "th_tstnbz<mode>2"
136   [(set (match_operand:X 0 "register_operand" "=r")
137         (unspec:X [(match_operand:X 1 "register_operand" "r")] UNSPEC_ORC_B))]
138   "TARGET_XTHEADBB"
139   "th.tstnbz\t%0,%1"
140   [(set_attr "type" "bitmanip")])
142 ;; XTheadBs
144 (define_insn "*th_tst<mode>3"
145   [(set (match_operand:X 0 "register_operand" "=r")
146         (zero_extract:X (match_operand:X 1 "register_operand" "r")
147                         (const_int 1)
148                         (match_operand 2 "const_int_operand" "n")))]
149   "TARGET_XTHEADBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
150   "th.tst\t%0,%1,%2"
151   [(set_attr "type" "bitmanip")])
153 ;; XTheadCondMov
155 (define_insn "*th_cond_mov<GPR:mode><GPR2:mode>"
156   [(set (match_operand:GPR 0 "register_operand" "=r,r")
157         (if_then_else:GPR
158          (match_operator 4 "equality_operator"
159                 [(match_operand:GPR2 1 "register_operand" "r,r")
160                  (const_int 0)])
161          (match_operand:GPR 2 "reg_or_0_operand" "rJ,0")
162          (match_operand:GPR 3 "reg_or_0_operand" "0,rJ")))]
163   "TARGET_XTHEADCONDMOV"
165   if (which_alternative == 0)
166     return "th.mv%C4z\t%0,%z2,%1";
168   /* Invert the condition and take else-block.  */
169   rtx_code code = GET_CODE (operands[4]);
170   code = (code == EQ) ? NE : EQ;
171   operands[4] = gen_rtx_fmt_ee (code, VOIDmode, operands[1], const0_rtx);
172   return "th.mv%C4z\t%0,%z3,%1";
174   [(set_attr "type" "condmove")
175    (set_attr "mode" "<GPR:MODE>")])
177 ;; XTheadFmv
179 ;; In RV32, we lack fmv.x.d and fmv.d.x, but XTheadFmv has instructions
180 ;; that cover this case.
182 (define_insn "th_fmv_hw_w_x"
183   [(set (match_operand:DF 0 "register_operand" "=f")
184         (unspec:DF [(match_operand:SI 1 "register_operand" "r")
185                 (match_operand:SI 2 "register_operand" "r")]
186      UNSPEC_XTHEADFMV))]
187   "!TARGET_64BIT && TARGET_XTHEADFMV"
188   "fmv.w.x\t%0,%2\n\tth.fmv.hw.x\t%0,%1"
189   [(set_attr "move_type" "move")
190    (set_attr "type" "fmove")
191    (set_attr "mode" "DF")])
193 (define_insn "th_fmv_x_w"
194   [(set (match_operand:SI 0 "register_operand" "=r")
195         (unspec:SI [(match_operand:DF 1 "register_operand" "f")]
196      UNSPEC_XTHEADFMV))]
197   "!TARGET_64BIT && TARGET_XTHEADFMV"
198   "fmv.x.w\t%0,%1"
199   [(set_attr "move_type" "move")
200    (set_attr "type" "fmove")
201    (set_attr "mode" "DF")])
203 (define_insn "th_fmv_x_hw"
204   [(set (match_operand:SI 0 "register_operand" "=r")
205         (unspec:SI [(match_operand:DF 1 "register_operand" "f")]
206      UNSPEC_XTHEADFMV_HW))]
207   "!TARGET_64BIT && TARGET_XTHEADFMV"
208   "th.fmv.x.hw\t%0,%1"
209   [(set_attr "move_type" "move")
210    (set_attr "type" "fmove")
211    (set_attr "mode" "DF")])
213 ;; XTheadInt
215 (define_constants
216   [(T0_REGNUM   5)
217    (T1_REGNUM   6)
218    (T2_REGNUM   7)
219    (A0_REGNUM   10)
220    (A1_REGNUM   11)
221    (A2_REGNUM   12)
222    (A3_REGNUM   13)
223    (A4_REGNUM   14)
224    (A5_REGNUM   15)
225    (A6_REGNUM   16)
226    (A7_REGNUM   17)
227    (T3_REGNUM   28)
228    (T4_REGNUM   29)
229    (T5_REGNUM   30)
230    (T6_REGNUM   31)
233 (define_insn "th_int_push"
234   [(unspec_volatile [(const_int 0)] UNSPECV_XTHEADINT_PUSH)
235    (use (reg:SI RETURN_ADDR_REGNUM))
236    (use (reg:SI T0_REGNUM))
237    (use (reg:SI T1_REGNUM))
238    (use (reg:SI T2_REGNUM))
239    (use (reg:SI A0_REGNUM))
240    (use (reg:SI A1_REGNUM))
241    (use (reg:SI A2_REGNUM))
242    (use (reg:SI A3_REGNUM))
243    (use (reg:SI A4_REGNUM))
244    (use (reg:SI A5_REGNUM))
245    (use (reg:SI A6_REGNUM))
246    (use (reg:SI A7_REGNUM))
247    (use (reg:SI T3_REGNUM))
248    (use (reg:SI T4_REGNUM))
249    (use (reg:SI T5_REGNUM))
250    (use (reg:SI T6_REGNUM))]
251   "TARGET_XTHEADINT && !TARGET_64BIT"
252   "th.ipush"
253   [(set_attr "type"     "store")
254    (set_attr "mode"     "SI")])
256 (define_insn "th_int_pop"
257   [(unspec_volatile [(const_int 0)] UNSPECV_XTHEADINT_POP)
258    (clobber (reg:SI RETURN_ADDR_REGNUM))
259    (clobber (reg:SI T0_REGNUM))
260    (clobber (reg:SI T1_REGNUM))
261    (clobber (reg:SI T2_REGNUM))
262    (clobber (reg:SI A0_REGNUM))
263    (clobber (reg:SI A1_REGNUM))
264    (clobber (reg:SI A2_REGNUM))
265    (clobber (reg:SI A3_REGNUM))
266    (clobber (reg:SI A4_REGNUM))
267    (clobber (reg:SI A5_REGNUM))
268    (clobber (reg:SI A6_REGNUM))
269    (clobber (reg:SI A7_REGNUM))
270    (clobber (reg:SI T3_REGNUM))
271    (clobber (reg:SI T4_REGNUM))
272    (clobber (reg:SI T5_REGNUM))
273    (clobber (reg:SI T6_REGNUM))
274    (return)]
275   "TARGET_XTHEADINT && !TARGET_64BIT"
276   "th.ipop"
277   [(set_attr "type"     "ret")
278    (set_attr "mode"     "SI")])
280 ;; XTheadMac
282 (define_insn "*th_mula<mode>"
283   [(set (match_operand:X 0 "register_operand" "=r")
284               (plus:X (mult:X (match_operand:X 1 "register_operand" "r")
285                               (match_operand:X 2 "register_operand" "r"))
286                       (match_operand:X 3 "register_operand" "0")))]
287   "TARGET_XTHEADMAC"
288   "th.mula\\t%0,%1,%2"
289   [(set_attr "type" "imul")
290    (set_attr "mode" "<MODE>")]
293 (define_insn "*th_mulawsi"
294   [(set (match_operand:DI 0 "register_operand" "=r")
295         (sign_extend:DI
296           (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
297                             (match_operand:SI 2 "register_operand" "r"))
298                    (match_operand:SI 3 "register_operand" "0"))))]
299   "TARGET_XTHEADMAC && TARGET_64BIT"
300   "th.mulaw\\t%0,%1,%2"
301   [(set_attr "type" "imul")
302    (set_attr "mode" "SI")]
305 (define_insn "*th_mulawsi2"
306   [(set (match_operand:SI 0 "register_operand" "=r")
307               (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
308                                 (match_operand:SI 2 "register_operand" "r"))
309                        (match_operand:SI 3 "register_operand" "0")))]
310   "TARGET_XTHEADMAC && TARGET_64BIT"
311   "th.mulaw\\t%0,%1,%2"
312   [(set_attr "type" "imul")
313    (set_attr "mode" "SI")]
316 (define_insn "*th_maddhisi4"
317   [(set (match_operand:SI 0 "register_operand" "=r")
318           (plus:SI
319             (mult:SI
320               (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
321               (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))
322             (match_operand:SI 3 "register_operand" " 0")))]
323   "TARGET_XTHEADMAC"
324   "th.mulah\\t%0,%1,%2"
325   [(set_attr "type" "imul")
326    (set_attr "mode" "SI")]
329 (define_insn "*th_sextw_maddhisi4"
330   [(set (match_operand:DI 0 "register_operand" "=r")
331         (sign_extend:DI
332           (plus:SI
333             (mult:SI
334               (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
335               (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))
336             (match_operand:SI 3 "register_operand" " 0"))))]
337   "TARGET_XTHEADMAC && TARGET_64BIT"
338   "th.mulah\\t%0,%1,%2"
339   [(set_attr "type" "imul")
340    (set_attr "mode" "SI")]
343 (define_insn "*th_muls<mode>"
344   [(set (match_operand:X 0 "register_operand" "=r")
345               (minus:X (match_operand:X 3 "register_operand" "0")
346                        (mult:X (match_operand:X 1 "register_operand" "r")
347                                (match_operand:X 2 "register_operand" "r"))))]
348   "TARGET_XTHEADMAC"
349   "th.muls\\t%0,%1,%2"
350   [(set_attr "type" "imul")
351    (set_attr "mode" "<MODE>")]
354 (define_insn "*th_mulswsi"
355   [(set (match_operand:DI 0 "register_operand" "=r")
356         (sign_extend:DI
357           (minus:SI (match_operand:SI 3 "register_operand" "0")
358                     (mult:SI (match_operand:SI 1 "register_operand" "r")
359                              (match_operand:SI 2 "register_operand" "r")))))]
360   "TARGET_XTHEADMAC && TARGET_64BIT"
361   "th.mulsw\\t%0,%1,%2"
362   [(set_attr "type" "imul")
363    (set_attr "mode" "SI")]
366 (define_insn "*th_mulswsi2"
367   [(set (match_operand:SI 0 "register_operand" "=r")
368         (minus:SI (match_operand:SI 3 "register_operand" "0")
369                   (mult:SI (match_operand:SI 1 "register_operand" "r")
370                            (match_operand:SI 2 "register_operand" "r"))))]
371   "TARGET_XTHEADMAC && TARGET_64BIT"
372   "th.mulsw\\t%0,%1,%2"
373   [(set_attr "type" "imul")
374    (set_attr "mode" "SI")]
377 (define_insn "*th_msubhisi4"
378   [(set (match_operand:SI 0 "register_operand" "=r")
379         (minus:SI (match_operand:SI 3 "register_operand" " 0")
380           (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
381             (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))))]
382   "TARGET_XTHEADMAC"
383   "th.mulsh\\t%0,%1,%2"
384   [(set_attr "type" "imul")
385    (set_attr "mode" "SI")]
388 (define_insn "*th_sextw_msubhisi4"
389   [(set (match_operand:DI 0 "register_operand" "=r")
390         (sign_extend:DI
391           (minus:SI (match_operand:SI 3 "register_operand" " 0")
392             (mult:SI
393               (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
394               (sign_extend:SI (match_operand:HI 2 "register_operand" " r"))))))]
395   "TARGET_XTHEADMAC && TARGET_64BIT"
396   "th.mulsh\\t%0,%1,%2"
397   [(set_attr "type" "imul")
398    (set_attr "mode" "SI")]
401 ;; XTheadMemPair
403 ;; MEMPAIR load 64/32 bit
404 (define_insn "*th_mempair_load_<GPR:mode>2"
405   [(set (match_operand:GPR 0 "register_operand" "=r")
406         (match_operand:GPR 1 "memory_operand" "m"))
407    (set (match_operand:GPR 2 "register_operand" "=r")
408         (match_operand:GPR 3 "memory_operand" "m"))]
409   "TARGET_XTHEADMEMPAIR && reload_completed
410    && th_mempair_operands_p (operands, true, <GPR:MODE>mode)"
411   { return th_mempair_output_move (operands, true, <GPR:MODE>mode, UNKNOWN); }
412   [(set_attr "move_type" "load")
413    (set_attr "type" "load")
414    (set_attr "mode" "<GPR:MODE>")])
416 ;; MEMPAIR store 64/32 bit
417 (define_insn "*th_mempair_store_<GPR:mode>2"
418   [(set (match_operand:GPR 0 "memory_operand" "=m")
419         (match_operand:GPR 1 "register_operand" "r"))
420    (set (match_operand:GPR 2 "memory_operand" "=m")
421         (match_operand:GPR 3 "register_operand" "r"))]
422   "TARGET_XTHEADMEMPAIR && reload_completed
423    && th_mempair_operands_p (operands, false, <GPR:MODE>mode)"
424   { return th_mempair_output_move (operands, false, <GPR:MODE>mode, UNKNOWN); }
425   [(set_attr "move_type" "store")
426    (set_attr "type" "store")
427    (set_attr "mode" "<GPR:MODE>")])
429 ;; MEMPAIR load DI extended signed SI
430 (define_insn "*th_mempair_load_extendsidi2"
431   [(set (match_operand:DI 0 "register_operand" "=r")
432         (sign_extend:DI (match_operand:SI 1 "memory_operand" "m")))
433    (set (match_operand:DI 2 "register_operand" "=r")
434         (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
435   "TARGET_XTHEADMEMPAIR && TARGET_64BIT && reload_completed
436    && th_mempair_operands_p (operands, true, SImode)"
437   { return th_mempair_output_move (operands, true, SImode, SIGN_EXTEND); }
438   [(set_attr "move_type" "load")
439    (set_attr "type" "load")
440    (set_attr "mode" "DI")
441    (set_attr "length" "8")])
443 ;; MEMPAIR load DI extended unsigned SI
444 (define_insn "*th_mempair_load_zero_extendsidi2"
445   [(set (match_operand:DI 0 "register_operand" "=r")
446         (zero_extend:DI (match_operand:SI 1 "memory_operand" "m")))
447    (set (match_operand:DI 2 "register_operand" "=r")
448         (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
449   "TARGET_XTHEADMEMPAIR && TARGET_64BIT && reload_completed
450    && th_mempair_operands_p (operands, true, SImode)"
451   { return th_mempair_output_move (operands, true, SImode, ZERO_EXTEND); }
452   [(set_attr "move_type" "load")
453    (set_attr "type" "load")
454    (set_attr "mode" "DI")
455    (set_attr "length" "8")])
457 ;; XTheadMemIdx
459 ;; Help reload to add a displacement for the base register.
460 ;; In the case `zext(*(uN*)(base+(zext(rN)<<1)))` LRA splits
461 ;; off two new instructions: a) `new_base = base + disp`, and
462 ;; b) `index = zext(rN)<<1`.  The index calculation has no
463 ;; corresponding instruction pattern and needs this insn_and_split
464 ;; to recover.
466 (define_insn_and_split "*th_memidx_operand"
467   [(set (match_operand:DI 0 "register_operand" "=r")
468      (ashift:DI
469        (zero_extend:DI (subreg:SI (match_operand:DI 1 "register_operand" "r") 0))
470        (match_operand 2 "const_int_operand" "n")))]
471   "TARGET_64BIT && TARGET_XTHEADMEMIDX && lra_in_progress"
472   "#"
473   ""
474   [(set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 1) 0)))
475    (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))]
476   ""
477   [(set_attr "type" "bitmanip")])
479 (define_insn "*th_memidx_zero_extendqi<SUPERQI:mode>2"
480   [(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
481         (zero_extend:SUPERQI
482             (match_operand:QI 1 "nonimmediate_operand"
483          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
484   "TARGET_XTHEADMEMIDX"
485   "@
486    andi\t%0,%1,0xff
487    th.lbuia\t%0,%1
488    th.lbuib\t%0,%1
489    th.lrbu\t%0,%1
490    th.lurbu\t%0,%1
491    lbu\t%0,%1"
492   [(set_attr "move_type" "andi,load,load,load,load,load")
493    (set_attr "mode" "<SUPERQI:MODE>")])
495 (define_insn "*th_memidx_extendsidi2"
496   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
497         (sign_extend:DI
498             (match_operand:SI 1 "nonimmediate_operand"
499          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
500   "TARGET_64BIT && TARGET_XTHEADMEMIDX"
501   "@
502    sext.w\t%0,%1
503    th.lwia\t%0,%1
504    th.lwib\t%0,%1
505    th.lrw\t%0,%1
506    th.lurw\t%0,%1
507    lw\t%0,%1"
508   [(set_attr "move_type" "move,load,load,load,load,load")
509    (set_attr "mode" "DI")])
511 ;; XTheadMemIdx (without XTheadBb)
513 (define_insn_and_split "*th_memidx_zero_extendsidi2"
514   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
515         (zero_extend:DI
516             (match_operand:SI 1 "nonimmediate_operand"
517          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
518   "TARGET_64BIT && TARGET_XTHEADMEMIDX && !TARGET_XTHEADBB"
519   "@
520    #
521    th.lwuia\t%0,%1
522    th.lwuib\t%0,%1
523    th.lrwu\t%0,%1
524    th.lurwu\t%0,%1
525    lwu\t%0,%1"
526   "&& reload_completed
527    && REG_P (operands[1])
528    && !paradoxical_subreg_p (operands[0])"
529   [(set (match_dup 0)
530         (ashift:DI (match_dup 1) (const_int 32)))
531    (set (match_dup 0)
532         (lshiftrt:DI (match_dup 0) (const_int 32)))]
533   { operands[1] = gen_lowpart (DImode, operands[1]); }
534   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
535    (set_attr "mode" "DI")])
537 (define_insn_and_split "*th_memidx_zero_extendhi<GPR:mode>2"
538   [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r")
539         (zero_extend:GPR
540             (match_operand:HI 1 "nonimmediate_operand"
541          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
542   "TARGET_XTHEADMEMIDX && !TARGET_XTHEADBB"
543   "@
544    #
545    th.lhuia\t%0,%1
546    th.lhuib\t%0,%1
547    th.lrhu\t%0,%1
548    th.lurhu\t%0,%1
549    lhu\t%0,%1"
550   "&& reload_completed
551    && REG_P (operands[1])
552    && !paradoxical_subreg_p (operands[0])"
553   [(set (match_dup 0)
554         (ashift:GPR (match_dup 1) (match_dup 2)))
555    (set (match_dup 0)
556         (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
557   {
558     operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
559     operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
560   }
561   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
562    (set_attr "mode" "<GPR:MODE>")])
564 (define_insn_and_split "*th_memidx_extend<SHORT:mode><SUPERQI:mode>2"
565   [(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
566         (sign_extend:SUPERQI
567             (match_operand:SHORT 1 "nonimmediate_operand"
568          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
569   "TARGET_XTHEADMEMIDX && !TARGET_XTHEADBB"
570   "@
571    #
572    th.l<SHORT:size>ia\t%0,%1
573    th.l<SHORT:size>ib\t%0,%1
574    th.lr<SHORT:size>\t%0,%1
575    th.lur<SHORT:size>\t%0,%1
576    l<SHORT:size>\t%0,%1"
577   "&& reload_completed
578    && REG_P (operands[1])
579    && !paradoxical_subreg_p (operands[0])"
580   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
581    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
583   operands[0] = gen_lowpart (SImode, operands[0]);
584   operands[1] = gen_lowpart (SImode, operands[1]);
585   operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
586                          - GET_MODE_BITSIZE (<SHORT:MODE>mode));
588   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
589    (set_attr "mode" "SI")])
591 ;; XTheadMemIdx (with XTheadBb)
593 (define_insn "*th_memidx_bb_zero_extendsidi2"
594   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
595         (zero_extend:DI
596             (match_operand:SI 1 "nonimmediate_operand"
597          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
598   "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
599   "@
600    th.extu\t%0,%1,31,0
601    th.lwuia\t%0,%1
602    th.lwuib\t%0,%1
603    th.lrwu\t%0,%1
604    th.lurwu\t%0,%1
605    lwu\t%0,%1"
606   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
607    (set_attr "mode" "DI")])
609 (define_insn "*th_memidx_bb_zero_extendhi<GPR:mode>2"
610   [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r")
611         (zero_extend:GPR
612             (match_operand:HI 1 "nonimmediate_operand"
613          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
614   "TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
615   "@
616    th.extu\t%0,%1,15,0
617    th.lhuia\t%0,%1
618    th.lhuib\t%0,%1
619    th.lrhu\t%0,%1
620    th.lurhu\t%0,%1
621    lhu\t%0,%1"
622   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
623    (set_attr "mode" "<GPR:MODE>")])
625 (define_insn "*th_memidx_bb_extendhi<GPR:mode>2"
626   [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r")
627         (sign_extend:GPR
628             (match_operand:HI 1 "nonimmediate_operand"
629          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
630   "TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
631   "@
632    th.ext\t%0,%1,15,0
633    th.lhia\t%0,%1
634    th.lhib\t%0,%1
635    th.lrh\t%0,%1
636    th.lurh\t%0,%1
637    lh\t%0,%1"
638   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
639    (set_attr "mode" "<GPR:MODE>")])
641 (define_insn "*th_memidx_bb_extendqi<SUPERQI:mode>2"
642   [(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
643         (sign_extend:SUPERQI
644             (match_operand:QI 1 "nonimmediate_operand"
645          " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
646   "TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
647   "@
648    th.ext\t%0,%1,7,0
649    th.lbia\t%0,%1
650    th.lbib\t%0,%1
651    th.lrb\t%0,%1
652    th.lurb\t%0,%1
653    lb\t%0,%1"
654   [(set_attr "move_type" "shift_shift,load,load,load,load,load")
655    (set_attr "mode" "<SUPERQI:MODE>")])
657 ;; All modes that are supported by XTheadMemIdx
658 (define_mode_iterator TH_M_ANYI [(QI "TARGET_XTHEADMEMIDX")
659                                  (HI "TARGET_XTHEADMEMIDX")
660                                  (SI "TARGET_XTHEADMEMIDX")
661                                  (DI "TARGET_64BIT && TARGET_XTHEADMEMIDX")])
663 ;; All modes that are supported by XTheadFMemIdx
664 (define_mode_iterator TH_M_ANYF [(SF "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX")
665                                  (DF "TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX")])
667 ;; All non-extension modes that are supported by XTheadMemIdx
668 (define_mode_iterator TH_M_NOEXTI [(SI "!TARGET_64BIT && TARGET_XTHEADMEMIDX")
669                                    (DI "TARGET_64BIT && TARGET_XTHEADMEMIDX")])
671 ;; All non-extension modes that are supported by XTheadFMemIdx
672 (define_mode_iterator TH_M_NOEXTF [(SF "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX")
673                                    (DF "TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX")])
675 ;; XTheadMemIdx optimizations
676 ;; All optimizations attempt to improve the operand utilization of
677 ;; XTheadMemIdx instructions, where one sign or zero extended
678 ;; register-index-operand can be shifted left by a 2-bit immediate.
680 ;; The basic idea is the following optimization:
681 ;; (set (reg 0) (op (reg 1) (imm 2)))
682 ;; (set (reg 3) (mem (plus (reg 0) (reg 4)))
683 ;; ==>
684 ;; (set (reg 3) (mem (plus (reg 4) (op2 (reg 1) (imm 2))))
685 ;; This optimization only valid if (reg 0) has no further uses.
687 ;; The three-instruction case is as follows:
688 ;; (set (reg 0) (op1 (reg 1) (imm 2)))
689 ;; (set (reg 3) (op2 (reg 0) (imm 4)))
690 ;; (set (reg 5) (mem (plus (reg 3) (reg 6)))
691 ;; ==>
692 ;; (set (reg 5) (mem (plus (reg 6) (op2 (reg 1) (imm 2/4)))))
693 ;; This optimization is only valid if (reg 0) and (reg 3) have no further uses.
695 ;; The optimization cases are:
696 ;; I) fold 2-bit ashift of register offset into mem-plus RTX
697 ;; US) fold 32-bit zero-extended (shift) offset into mem-plus
698 ;; UZ) fold 32-bit zero-extended (zext) offset into mem-plus
700 ;; The first optimization case is targeting the th.lr<MODE> instructions.
701 ;; The other optimization cases are targeting the th.lur<MODE> instructions
702 ;; and have to consider two forms of zero-extensions:
703 ;; - ashift-32 + lshiftrt-{29..32} if there are no zero-extension instructions.
704 ;;   Left-shift amounts of 29..31 indicate a left-shifted zero-extended value.
705 ;; - zero-extend32 if there are zero-extension instructions (XTheadBb or Zbb).
707 ;; We always have three peephole passes per optimization case:
708 ;; a) no-extended (X) word-load
709 ;; b) any-extend (SUBX) word-load
710 ;; c) store
712 ;; Note, that SHIFTs will be converted to MULTs during combine.
714 (define_insn_and_split "*th_memidx_I_a"
715   [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
716         (mem:TH_M_NOEXTI (plus:X
717           (mult:X (match_operand:X 1 "register_operand" "r")
718                   (match_operand:QI 2 "immediate_operand" "i"))
719           (match_operand:X 3 "register_operand" "r"))))]
720   "TARGET_XTHEADMEMIDX
721    && CONST_INT_P (operands[2])
722    && pow2p_hwi (INTVAL (operands[2]))
723    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
724   "#"
725   "&& 1"
726   [(set (match_dup 0)
727         (mem:TH_M_NOEXTI (plus:X
728           (match_dup 3)
729           (ashift:X (match_dup 1) (match_dup 2)))))]
730   { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
731   }
734 (define_insn_and_split "*th_memidx_I_b"
735   [(set (match_operand:X 0 "register_operand" "=r")
736         (any_extend:X (mem:SUBX (plus:X
737           (mult:X (match_operand:X 1 "register_operand" "r")
738                   (match_operand:QI 2 "immediate_operand" "i"))
739           (match_operand:X 3 "register_operand" "r")))))]
740   "TARGET_XTHEADMEMIDX
741    && CONST_INT_P (operands[2])
742    && pow2p_hwi (INTVAL (operands[2]))
743    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
744   "#"
745   "&& 1"
746   [(set (match_dup 0)
747         (any_extend:X (mem:SUBX (plus:X
748           (match_dup 3)
749           (ashift:X (match_dup 1) (match_dup 2))))))]
750   { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
751   }
754 (define_insn_and_split "*th_memidx_I_c"
755   [(set (mem:TH_M_ANYI (plus:X
756           (mult:X (match_operand:X 1 "register_operand" "r")
757                   (match_operand:QI 2 "immediate_operand" "i"))
758           (match_operand:X 3 "register_operand" "r")))
759         (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
760   "TARGET_XTHEADMEMIDX
761    && CONST_INT_P (operands[2])
762    && pow2p_hwi (INTVAL (operands[2]))
763    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
764   "#"
765   "&& 1"
766   [(set (mem:TH_M_ANYI (plus:X
767           (match_dup 3)
768           (ashift:X (match_dup 1) (match_dup 2))))
769         (match_dup 0))]
770   { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
771   }
774 (define_insn_and_split "*th_memidx_US_a"
775   [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
776         (mem:TH_M_NOEXTI (plus:DI
777           (and:DI
778             (mult:DI (match_operand:DI 1 "register_operand" "r")
779                      (match_operand:QI 2 "immediate_operand" "i"))
780             (match_operand:DI 3 "immediate_operand" "i"))
781           (match_operand:DI 4 "register_operand" "r"))))]
782   "TARGET_64BIT && TARGET_XTHEADMEMIDX
783    && CONST_INT_P (operands[2])
784    && pow2p_hwi (INTVAL (operands[2]))
785    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
786    && CONST_INT_P (operands[3])
787    && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
788   "#"
789   "&& 1"
790   [(set (match_dup 0)
791         (mem:TH_M_NOEXTI (plus:DI
792           (match_dup 4)
793           (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))))]
794   { operands[1] = gen_lowpart (SImode, operands[1]);
795     operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
796   }
799 (define_insn_and_split "*th_memidx_US_b"
800   [(set (match_operand:X 0 "register_operand" "=r")
801         (any_extend:X (mem:SUBX (plus:DI
802           (and:DI
803             (mult:DI (match_operand:DI 1 "register_operand" "r")
804                      (match_operand:QI 2 "immediate_operand" "i"))
805             (match_operand:DI 3 "immediate_operand" "i"))
806           (match_operand:DI 4 "register_operand" "r")))))]
807   "TARGET_64BIT && TARGET_XTHEADMEMIDX
808    && CONST_INT_P (operands[2])
809    && pow2p_hwi (INTVAL (operands[2]))
810    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
811    && CONST_INT_P (operands[3])
812    && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
813   "#"
814   "&& 1"
815   [(set (match_dup 0)
816         (any_extend:X (mem:SUBX (plus:DI
817           (match_dup 4)
818           (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))))]
819   { operands[1] = gen_lowpart (SImode, operands[1]);
820     operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
821   }
824 (define_insn_and_split "*th_memidx_US_c"
825   [(set (mem:TH_M_ANYI (plus:DI
826           (and:DI
827             (mult:DI (match_operand:DI 1 "register_operand" "r")
828                      (match_operand:QI 2 "immediate_operand" "i"))
829             (match_operand:DI 3 "immediate_operand" "i"))
830           (match_operand:DI 4 "register_operand" "r")))
831         (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
832   "TARGET_64BIT && TARGET_XTHEADMEMIDX
833    && CONST_INT_P (operands[2])
834    && pow2p_hwi (INTVAL (operands[2]))
835    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
836    && CONST_INT_P (operands[3])
837    && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
838   "#"
839   "&& 1"
840   [(set (mem:TH_M_ANYI (plus:DI
841           (match_dup 4)
842           (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))
843         (match_dup 0))]
844   { operands[1] = gen_lowpart (SImode, operands[1]);
845     operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
846   }
849 (define_insn_and_split "*th_memidx_UZ_a"
850   [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
851         (mem:TH_M_NOEXTI (plus:DI
852           (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
853           (match_operand:DI 2 "register_operand" "r"))))]
854   "TARGET_64BIT && TARGET_XTHEADMEMIDX"
855   "#"
856   "&& 1"
857   [(set (match_dup 0)
858         (mem:TH_M_NOEXTI (plus:DI
859           (match_dup 2)
860           (zero_extend:DI (match_dup 1)))))]
863 (define_insn_and_split "*th_memidx_UZ_b"
864   [(set (match_operand:X 0 "register_operand" "=r")
865         (any_extend:X (mem:SUBX (plus:DI
866           (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
867           (match_operand:DI 2 "register_operand" "r")))))]
868   "TARGET_64BIT && TARGET_XTHEADMEMIDX"
869   "#"
870   "&& 1"
871   [(set (match_dup 0)
872         (any_extend:X (mem:SUBX (plus:DI
873           (match_dup 2)
874           (zero_extend:DI (match_dup 1))))))]
877 (define_insn_and_split "*th_memidx_UZ_c"
878   [(set (mem:TH_M_ANYI (plus:DI
879           (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
880           (match_operand:DI 2 "register_operand" "r")))
881         (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
882   "TARGET_64BIT && TARGET_XTHEADMEMIDX"
883   "#"
884   "&& 1"
885   [(set (mem:TH_M_ANYI (plus:DI
886           (match_dup 2)
887           (zero_extend:DI (match_dup 1))))
888         (match_dup 0))]
891 ;; XTheadFMemIdx
892 ;; Note, that we might get GP registers in FP-mode (reg:DF a2)
893 ;; which cannot be handled by the XTheadFMemIdx instructions.
894 ;; This might even happend after register allocation.
895 ;; We could implement splitters that undo the combiner results
896 ;; if "after_reload && !HARDFP_REG_P (operands[0])", but this
897 ;; raises even more questions (e.g. split into what?).
898 ;; So let's solve this by simply requiring XTheadMemIdx
899 ;; which provides the necessary instructions to cover this case.
901 (define_insn "*th_fmemidx_movsf_hardfloat"
902   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,th_m_mir,f,th_m_miu")
903         (match_operand:SF 1 "move_operand"         " th_m_mir,f,th_m_miu,f"))]
904   "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX && TARGET_XTHEADMEMIDX
905    && (register_operand (operands[0], SFmode)
906        || reg_or_0_operand (operands[1], SFmode))"
907   { return riscv_output_move (operands[0], operands[1]); }
908   [(set_attr "move_type" "fpload,fpstore,fpload,fpstore")
909    (set_attr "mode" "SF")])
911 (define_insn "*th_fmemidx_movdf_hardfloat_rv64"
912   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,th_m_mir,f,th_m_miu")
913         (match_operand:DF 1 "move_operand"         " th_m_mir,f,th_m_miu,f"))]
914   "TARGET_64BIT && TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX
915    && TARGET_XTHEADMEMIDX
916    && (register_operand (operands[0], DFmode)
917        || reg_or_0_operand (operands[1], DFmode))"
918   { return riscv_output_move (operands[0], operands[1]); }
919   [(set_attr "move_type" "fpload,fpstore,fpload,fpstore")
920    (set_attr "mode" "DF")])
922 ;; XTheadFMemIdx optimizations
923 ;; Similar like XTheadMemIdx optimizations, but less cases.
925 (define_insn_and_split "*th_fmemidx_I_a"
926   [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
927         (mem:TH_M_NOEXTF (plus:X
928           (mult:X (match_operand:X 1 "register_operand" "r")
929                   (match_operand:QI 2 "immediate_operand" "i"))
930           (match_operand:X 3 "register_operand" "r"))))]
931   "TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
932    && CONST_INT_P (operands[2])
933    && pow2p_hwi (INTVAL (operands[2]))
934    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
935   "#"
936   "&& reload_completed"
937   [(set (match_dup 0)
938         (mem:TH_M_NOEXTF (plus:X
939           (match_dup 3)
940           (ashift:X (match_dup 1) (match_dup 2)))))]
941   { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
942   }
943   [(set_attr "move_type" "fpload")
944    (set_attr "mode" "<UNITMODE>")
945    (set_attr "type" "fmove")
946    (set (attr "length") (const_int 16))])
948 (define_insn_and_split "*th_fmemidx_I_c"
949   [(set (mem:TH_M_ANYF (plus:X
950           (mult:X (match_operand:X 1 "register_operand" "r")
951                   (match_operand:QI 2 "immediate_operand" "i"))
952           (match_operand:X 3 "register_operand" "r")))
953         (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
954   "TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
955    && CONST_INT_P (operands[2])
956    && pow2p_hwi (INTVAL (operands[2]))
957    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
958   "#"
959   "&& 1"
960   [(set (mem:TH_M_ANYF (plus:X
961           (match_dup 3)
962           (ashift:X (match_dup 1) (match_dup 2))))
963         (match_dup 0))]
964   { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
965   }
968 (define_insn_and_split "*th_fmemidx_US_a"
969   [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
970         (mem:TH_M_NOEXTF (plus:DI
971           (and:DI
972             (mult:DI (match_operand:DI 1 "register_operand" "r")
973                      (match_operand:QI 2 "immediate_operand" "i"))
974             (match_operand:DI 3 "immediate_operand" "i"))
975           (match_operand:DI 4 "register_operand" "r"))))]
976   "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
977    && CONST_INT_P (operands[2])
978    && pow2p_hwi (INTVAL (operands[2]))
979    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
980    && CONST_INT_P (operands[3])
981    && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
982   "#"
983   "&& reload_completed"
984   [(set (match_dup 0)
985         (mem:TH_M_NOEXTF (plus:DI
986           (match_dup 4)
987           (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))))]
988   { operands[1] = gen_lowpart (SImode, operands[1]);
989     operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
990   }
991   [(set_attr "move_type" "fpload")
992    (set_attr "mode" "<UNITMODE>")
993    (set_attr "type" "fmove")
994    (set (attr "length") (const_int 16))])
996 (define_insn_and_split "*th_fmemidx_US_c"
997   [(set (mem:TH_M_ANYF (plus:DI
998           (and:DI
999             (mult:DI (match_operand:DI 1 "register_operand" "r")
1000                      (match_operand:QI 2 "immediate_operand" "i"))
1001             (match_operand:DI 3 "immediate_operand" "i"))
1002           (match_operand:DI 4 "register_operand" "r")))
1003         (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
1004   "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
1005    && CONST_INT_P (operands[2])
1006    && pow2p_hwi (INTVAL (operands[2]))
1007    && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
1008    && CONST_INT_P (operands[3])
1009    && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
1010   "#"
1011   "&& 1"
1012   [(set (mem:TH_M_ANYF (plus:DI
1013           (match_dup 4)
1014           (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))
1015         (match_dup 0))]
1016   { operands[1] = gen_lowpart (SImode, operands[1]);
1017     operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
1018   }
1021 (define_insn_and_split "*th_fmemidx_UZ_a"
1022   [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
1023         (mem:TH_M_NOEXTF (plus:DI
1024           (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1025           (match_operand:DI 2 "register_operand" "r"))))]
1026   "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
1027    && (!HARD_REGISTER_NUM_P (REGNO (operands[0])) || HARDFP_REG_P (REGNO (operands[0])))"
1028   "#"
1029   "&& reload_completed"
1030   [(set (match_dup 0)
1031         (mem:TH_M_NOEXTF (plus:DI
1032           (match_dup 2)
1033           (zero_extend:DI (match_dup 1)))))]
1034   ""
1035   [(set_attr "move_type" "fpload")
1036    (set_attr "mode" "<UNITMODE>")
1037    (set_attr "type" "fmove")
1038    (set (attr "length") (const_int 16))])
1040 (define_insn_and_split "*th_fmemidx_UZ_c"
1041   [(set (mem:TH_M_ANYF (plus:DI
1042           (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1043           (match_operand:DI 2 "register_operand" "r")))
1044         (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
1045   "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX"
1046   "#"
1047   "&& 1"
1048   [(set (mem:TH_M_ANYF (plus:DI
1049           (match_dup 2)
1050           (zero_extend:DI (match_dup 1))))
1051         (match_dup 0))]
1054 (include "thead-peephole.md")