1;;  Machine Description for Renesas RL78 processors
2;;  Copyright (C) 2011-2021 Free Software Foundation, Inc.
3;;  Contributed by Red Hat.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public 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;;---------- Moving ------------------------
22
23(define_expand "movqi"
24  [(set (match_operand:QI 0 "nonimmediate_operand")
25	(match_operand:QI 1 "general_operand"))]
26  ""
27  {
28    if (MEM_P (operands[0]) && MEM_P (operands[1]))
29      operands[1] = copy_to_mode_reg (QImode, operands[1]);
30    if (rl78_far_p (operands[0]) && rl78_far_p (operands[1]))
31      operands[1] = copy_to_mode_reg (QImode, operands[1]);
32
33    /* GCC can generate (SUBREG (SYMBOL_REF)) when it has to store a symbol
34       into a bitfield, or a packed ordinary field.  We can handle this
35       provided that the destination is a register.  If not, then load the
36       source into a register first.  */
37    if (GET_CODE (operands[1]) == SUBREG
38        && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
39	&& ! REG_P (operands[0]))
40	operands[1] = copy_to_mode_reg (QImode, operands[1]);
41
42    /* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))).
43       cf. g++.dg/abi/packed.C.  */
44    if (GET_CODE (operands[1]) == SUBREG
45	&& GET_CODE (XEXP (operands[1], 0)) == CONST
46        && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == PLUS
47        && GET_CODE (XEXP (XEXP (XEXP (operands[1], 0), 0), 0)) == SYMBOL_REF
48	&& ! REG_P (operands[0]))
49	operands[1] = copy_to_mode_reg (QImode, operands[1]);
50
51    if (CONST_INT_P (operands[1]) && ! IN_RANGE (INTVAL (operands[1]), (HOST_WIDE_INT_M1U << 8) + 1, (1 << 8) - 1))
52      FAIL;
53  }
54)
55
56(define_expand "movhi"
57  [(set (match_operand:HI 0 "nonimmediate_operand")
58	(match_operand:HI 1 "general_operand"))]
59  ""
60  {
61    if (MEM_P (operands[0]) && MEM_P (operands[1]))
62      operands[1] = copy_to_mode_reg (HImode, operands[1]);
63    if (rl78_far_p (operands[0]) && rl78_far_p (operands[1]))
64      operands[1] = copy_to_mode_reg (HImode, operands[1]);
65
66    /* FIXME: Not sure how GCC can generate (SUBREG (SYMBOL_REF)),
67       but it does.  Since this makes no sense, reject it here.  */
68    if (GET_CODE (operands[1]) == SUBREG
69        && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
70      FAIL;
71    /* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))).  */
72    if (GET_CODE (operands[1]) == SUBREG
73	&& GET_CODE (XEXP (operands[1], 0)) == CONST
74        && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == PLUS
75        && GET_CODE (XEXP (XEXP (XEXP (operands[1], 0), 0), 0)) == SYMBOL_REF)
76      FAIL;
77  }
78)
79
80(define_insn_and_split "movsi"
81  [(set (match_operand:SI 0 "nonimmediate_operand" "=vYS,v,Wfr")
82	(match_operand:SI 1 "general_operand" "viYS,Wfr,v"))]
83  ""
84  "#"
85  ""
86  [(set (match_operand:HI 2 "nonimmediate_operand")
87	(match_operand:HI 4 "general_operand"))
88   (set (match_operand:HI 3 "nonimmediate_operand")
89	(match_operand:HI 5 "general_operand"))]
90  "rl78_split_movsi (operands, SImode);"
91  [(set_attr "valloc" "op1")]
92)
93
94(define_insn_and_split "movsf"
95  [(set (match_operand:SF 0 "nonimmediate_operand" "=vYS,v,Wfr")
96	(match_operand:SF 1 "general_operand" "viYS,Wfr,v"))]
97  ""
98  "#"
99  ""
100  [(set (match_operand:HI 2 "nonimmediate_operand")
101	(match_operand:HI 4 "general_operand"))
102   (set (match_operand:HI 3 "nonimmediate_operand")
103	(match_operand:HI 5 "general_operand"))]
104  "rl78_split_movsi (operands, SFmode);"
105  [(set_attr "valloc" "op1")]
106)
107
108(define_expand "bswaphi2"
109  [(set (match_operand:HI           0 "nonimmediate_operand")
110        (bswap:HI (match_operand:HI 1 "general_operand")))]
111  ""
112  "if (rl78_force_nonfar_2 (operands, gen_bswaphi2))
113     DONE;"
114)
115
116;;---------- Conversions ------------------------
117
118(define_expand "zero_extendqihi2"
119  [(set (match_operand:HI                 0 "nonimmediate_operand")
120	(zero_extend:HI (match_operand:QI 1 "general_operand")))]
121  ""
122  "if (rl78_force_nonfar_2 (operands, gen_zero_extendqihi2))
123     DONE;"
124  )
125
126(define_expand "extendqihi2"
127  [(set (match_operand:HI                 0 "nonimmediate_operand")
128	(sign_extend:HI (match_operand:QI 1 "general_operand")))]
129  ""
130  "if (rl78_force_nonfar_2 (operands, gen_extendqihi2))
131     DONE;"
132  )
133
134;;---------- Arithmetic ------------------------
135
136(define_expand "add<mode>3"
137  [(set (match_operand:QHI           0 "nonimmediate_operand")
138	(plus:QHI (match_operand:QHI 1 "general_operand")
139		  (match_operand:QHI 2 "general_operand")))
140   ]
141  ""
142  "if (rl78_force_nonfar_3 (operands, gen_add<mode>3))
143     DONE;"
144)
145
146(define_expand "sub<mode>3"
147  [(set (match_operand:QHI            0 "nonimmediate_operand")
148	(minus:QHI (match_operand:QHI 1 "general_operand")
149		   (match_operand:QHI 2 "general_operand")))
150   ]
151  ""
152  "if (rl78_force_nonfar_3 (operands, gen_sub<mode>3))
153     DONE;"
154)
155
156(define_expand "neg<mode>2"
157  [(set (match_operand:QHI            0 "nonimmediate_operand")
158	(minus:QHI (const_int 0)
159		   (match_operand:QHI 1 "general_operand")))
160   ]
161  ""
162  "if (rl78_force_nonfar_2 (operands, gen_neg<mode>2))
163     DONE;"
164)
165
166(define_expand "umulqihi3"
167  [(set (match_operand:HI 0 "register_operand")
168        (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand"))
169                 (zero_extend:HI (match_operand:QI 2 "register_operand"))))]
170  ""
171  ""
172)
173
174(define_expand "andqi3"
175  [(set (match_operand:QI         0 "rl78_nonimmediate_operand")
176	(and:QI (match_operand:QI 1 "rl78_general_operand")
177		(match_operand:QI 2 "rl78_general_operand")))
178   ]
179  ""
180  "if (rl78_force_nonfar_3 (operands, gen_andqi3))
181     DONE;"
182)
183
184(define_expand "iorqi3"
185  [(set (match_operand:QI         0 "rl78_nonimmediate_operand")
186	(ior:QI (match_operand:QI 1 "rl78_general_operand")
187		(match_operand:QI 2 "rl78_general_operand")))
188   ]
189  ""
190  "if (rl78_force_nonfar_3 (operands, gen_iorqi3))
191     DONE;"
192)
193
194(define_expand "xorqi3"
195  [(set (match_operand:QI         0 "rl78_nonimmediate_operand")
196	(xor:QI (match_operand:QI 1 "rl78_general_operand")
197		(match_operand:QI 2 "rl78_general_operand")))
198   ]
199  ""
200  "if (rl78_force_nonfar_3 (operands, gen_xorqi3))
201     DONE;"
202)
203
204(define_expand "one_cmplqi2"
205  [(set (match_operand:QI         0 "nonimmediate_operand")
206	(xor:QI (match_operand:QI 1 "general_operand")
207		(const_int -1)))
208   ]
209  ""
210  "if (rl78_force_nonfar_2 (operands, gen_one_cmplqi2))
211     DONE;"
212)
213
214;;---------- Shifts ------------------------
215
216(define_expand "ashl<mode>3"
217  [(set (match_operand:QHI             0 "nonimmediate_operand")
218	(ashift:QHI (match_operand:QHI 1 "general_operand")
219		    (match_operand:QI  2 "general_operand")))
220   ]
221  ""
222  "if (rl78_force_nonfar_3 (operands, gen_ashl<mode>3))
223     DONE;"
224)
225
226(define_expand "ashr<mode>3"
227  [(set (match_operand:QHI               0 "nonimmediate_operand")
228	(ashiftrt:QHI (match_operand:QHI 1 "general_operand")
229		      (match_operand:QI  2 "general_operand")))
230   ]
231  ""
232  "if (rl78_force_nonfar_3 (operands, gen_ashr<mode>3))
233     DONE;"
234)
235
236(define_expand "lshr<mode>3"
237  [(set (match_operand:QHI               0 "nonimmediate_operand")
238	(lshiftrt:QHI (match_operand:QHI 1 "general_operand")
239		      (match_operand:QI  2 "general_operand")))
240   ]
241  ""
242  "if (rl78_force_nonfar_3 (operands, gen_lshr<mode>3))
243     DONE;"
244)
245
246(define_expand "ashrsi3"
247  [(parallel [(set (match_operand:SI               0 "nonimmediate_operand")
248		   (ashiftrt:SI (match_operand:SI  1 "nonimmediate_operand")
249				(match_operand:SI  2 "nonmemory_operand")))
250	      (clobber (reg:HI X_REG))])
251   ]
252  ""
253  ""
254)
255
256(define_expand "lshrsi3"
257  [(parallel [(set (match_operand:SI               0 "nonimmediate_operand")
258		   (lshiftrt:SI (match_operand:SI  1 "nonimmediate_operand")
259				(match_operand:SI  2 "nonmemory_operand")))
260	      (clobber (reg:HI X_REG))])
261   ]
262  ""
263  ""
264)
265
266(define_expand "ashlsi3"
267  [(parallel [(set (match_operand:SI            0 "nonimmediate_operand")
268		   (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
269			      (match_operand:SI 2 "nonmemory_operand")))
270	      (clobber (reg:HI X_REG))])
271   ]
272  ""
273  ""
274)
275
276;;---------- Branching ------------------------
277
278(define_expand "indirect_jump"
279  [(set (pc)
280	(match_operand:HI 0 "nonimmediate_operand"))]
281  ""
282  ""
283)
284
285(define_expand "call"
286  [(call (match_operand:HI 0 "memory_operand")
287	 (match_operand 1 ""))]
288  ""
289  ""
290)
291
292(define_expand "call_value"
293  [(set (match_operand          0 "register_operand")
294	(call (match_operand:HI 1 "memory_operand")
295	      (match_operand    2 "")))]
296  ""
297  ""
298)
299
300(define_expand "cbranchqi4"
301  [(set (pc) (if_then_else
302	      (match_operator                    0 "rl78_cmp_operator"
303			      [(match_operand:QI 1 "general_operand")
304			       (match_operand:QI 2 "general_operand")])
305              (label_ref (match_operand 3 "" ""))
306	      (pc)))]
307  ""
308  "rl78_expand_compare (operands);"
309)
310
311(define_expand "cbranchhi4"
312  [(set (pc) (if_then_else
313	      (match_operator                    0 "rl78_cmp_operator"
314			      [(match_operand:HI 1 "general_operand")
315			       (match_operand:HI 2 "general_operand")])
316              (label_ref (match_operand 3 "" ""))
317	      (pc)))]
318  ""
319  "rl78_expand_compare (operands);"
320)
321
322(define_expand "cbranchsi4"
323  [(parallel [(set (pc) (if_then_else
324			 (match_operator 0 "rl78_cmp_operator"
325					 [(match_operand:SI 1 "general_operand")
326					  (match_operand:SI 2 "nonmemory_operand")])
327			 (label_ref (match_operand 3 "" ""))
328			 (pc)))
329	      (clobber (reg:HI AX_REG))
330	      ])]
331  "1"
332  "rl78_expand_compare (operands);"
333)
334