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;; The insns in this file correspond to the actual opcodes the RL78
22;; can issue with real registers.  All insns in here should be
23;; conditional on rl78_real_insns_ok() returning true, and should
24;; allow virtual registers in their predicates - the reorg pass that
25;; allocates physical registers uses the constraints to select
26;; registers, but insns with virtual registers MUST match one of these
27;; patterns - other than the constraints - so that the operand info is
28;; properly set up for the alloc pass.
29
30;; This attribute reflects how the insn alters the Z flag,
31;; based upon the value of the it's output.  The default is NO
32;; for no change, but other possibilities are UPDATE_Z if it changes
33;; the Z flag and CLOBBER if the state of the flag is indeterminate.
34;; The CY and AC flags are not set in the same way as the Z flag, so
35;; their values are not tracked.
36(define_attr "update_Z" "no,update_Z,clobber" (const_string "no"))
37
38;;---------- Moving ------------------------
39
40(define_insn "movqi_to_es"
41  [(set (reg:QI ES_REG)
42	(match_operand:QI 0 "register_operand" "a"))]
43  ""
44  "mov\tes, %0"
45)
46
47(define_insn "movqi_from_es"
48  [(set (match_operand:QI 0 "register_operand" "=a")
49	(reg:QI ES_REG))]
50  ""
51  "mov\t%0, es"
52)
53
54(define_insn "movqi_cs"
55  [(set (reg:QI CS_REG)
56	(match_operand:QI 0 "register_operand" "a"))]
57  ""
58  "mov\tcs, %0"
59)
60
61(define_insn "*movqi_real"
62  [(set (match_operand:QI 0 "rl78_nonimmediate_operand" "=Rv,RaxbcWab,RaxbcWab,a,                               bcx,R,     WabWd2WhlWh1WhbWbcWs1v, bcx,WsaWsf")
63	(match_operand    1 "rl78_general_operand"      "0,K,        M,       RInt8sJvWabWdeWd2WhlWh1WhbWbcWs1,Wab,aInt8J,a,                      R,  i"))]
64  "rl78_real_insns_ok ()"
65  "@
66   ; mov\t%0, %1
67   oneb\t%0
68   clrb\t%0
69   mov\t%0, %1
70   mov\t%0, %1
71   mov\t%0, %1
72   mov\t%0, %1
73   mov\t%0, %S1
74   mov\t%0, %1"
75)
76
77(define_insn "*movhi_real"
78  [(set (match_operand:HI 0 "rl78_nonimmediate_operand" "=Rv,AB,AB,RSv,A,BDTvSWabWd2WdeWhlWh1WbcWs1, BDT,ABDT,v")
79	(match_operand:HI 1 "rl78_general_operand"      " 0,K, M, i,  BDTvSWabWd2WdeWh1WhlWbcWs1,A, BDT,vS,  ABDT"))]
80  "rl78_real_insns_ok ()"
81  "@
82   ; movw\t%0, %1
83   onew\t%0
84   clrw\t%0
85   movw\t%0, %1
86   movw\t%0, %1
87   movw\t%0, %1
88   movw\t%0, %S1
89   movw\t%0, %1
90   movw\t%0, %1"
91)
92
93(define_insn "*bswaphi2_real"
94  [(set (match_operand:HI           0 "rl78_nonfar_nonimm_operand" "=A,A")
95        (bswap:HI (match_operand:HI 1 "general_operand"  "0,viU")))]
96  "rl78_real_insns_ok ()"
97  "@
98   xch\ta, x
99   movw\tax, %1\n\txch\ta, x"
100)
101
102;;---------- Conversions ------------------------
103
104(define_insn "*zero_extendqihi2_real"
105  [(set (match_operand:HI                 0 "nonimmediate_operand" "=Rv,A")
106	(zero_extend:HI (match_operand:QI 1 "general_operand" "0,a")))]
107  "rl78_real_insns_ok ()"
108  "@
109   mov\t%Q0, #0
110   mov\tx, a \;mov\ta, #0"
111  )
112
113(define_insn "*extendqihi2_real"
114  [(set (match_operand:HI                 0 "nonimmediate_operand" "=A,A")
115	(sign_extend:HI (match_operand:QI 1 "general_operand" "x,a")))]
116  "rl78_real_insns_ok ()"
117  "@
118   shlw\t%0, 8 \;sarw\t%0, 8
119   sarw\t%0, 8"
120  )
121
122;;---------- Arithmetic ------------------------
123
124(define_insn "*addqi3_real"
125  [(set (match_operand:QI          0 "rl78_nonimmediate_operand"  "=RvWabWhlWh1Wsa,RvWabWhlWh1Wsa,a,*bcdehl,Wsa")
126	(plus:QI (match_operand:QI 1 "rl78_general_operand"  "%0,0,0,0,0")
127		 (match_operand:QI 2 "rl78_general_operand" "K,L,RWhlWh1Wabi,a,i")))
128   ]
129  "rl78_real_insns_ok ()"
130  "@
131    inc\t%p0
132    dec\t%p0
133    add\t%0, %2
134    add\t%0, %2
135    add\t%0, %2"
136  [(set (attr "update_Z") (const_string "update_Z"))]
137)
138
139(define_insn "*addhi3_real"
140  [(set (match_operand:HI          0 "rl78_nonimmediate_operand"  "=vABDTWhlWh1WabWsa,vABDTWhlWh1WabWsa,v,v,A,S,S,A")
141	(plus:HI (match_operand:HI 1 "rl78_general_operand"  "%0,0,0,0,0,0,0,S")
142		 (match_operand:HI 2 "" "K,L,N,O,RWh1WhlWabiv,Int8Qs8,J,Ri")))
143   ]
144  "rl78_real_insns_ok ()"
145  "@
146   incw\t%p0
147   decw\t%p0
148   incw\t%0 \;incw\t%0
149   decw\t%0 \;decw\t%0
150   addw\t%0, %p2
151   addw\t%0, %2
152   subw\t%0, %m2
153   movw\t%0, %1 \;addw\t%0, %2"
154  [(set_attr "update_Z" "*,*,*,*,update_Z,update_Z,update_Z,update_Z")]
155)
156
157(define_insn "*addqihi3a_real"
158  [(set (match_operand:HI                          0 "register_operand" "=R")
159	(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand"  "R"))
160		 (match_operand:HI                 2 "register_operand"  "0")))
161   ]
162  "rl78_real_insns_ok ()"
163  "add\t%q0, %q1 \;addc\t%Q0, #0"
164  [(set (attr "update_Z") (const_string "update_Z"))]
165)
166
167(define_insn "*subqi3_real"
168  [(set (match_operand:QI           0 "nonimmediate_operand"  "=a,R,v")
169	(minus:QI (match_operand:QI 1 "general_operand"  "0,0,0")
170		  (match_operand:QI 2 "rl78_general_operand" "RiWabWhbWh1Whl,a,i")))
171   ]
172  "rl78_real_insns_ok ()"
173  "sub\t%0, %2"
174  [(set (attr "update_Z") (const_string "update_Z"))]
175)
176
177(define_insn "*subhi3_real"
178  [(set (match_operand:HI           0 "nonimmediate_operand"  "=A,S")
179	(minus:HI (match_operand:HI 1 "general_operand"  "0,0")
180		  (match_operand:HI 2 "rl78_general_operand" "iBDTWabWh1v,i")))
181   ]
182  "rl78_real_insns_ok ()"
183  "subw\t%0, %2"
184  [(set (attr "update_Z") (const_string "update_Z"))]
185)
186
187(define_insn "*umulhi3_shift_real"
188  [(set (match_operand:HI 0 "register_operand" "=A,A")
189        (mult:HI (match_operand:HI 1 "rl78_nonfar_operand" "0,0")
190                 (match_operand:HI 2 "rl78_24_operand" "N,i")))]
191  "rl78_real_insns_ok ()"
192  "@
193   shlw\t%0, 1
194   shlw\t%0, 2"
195)
196
197(define_insn "*umulqihi3_real"
198  [(set (match_operand:HI 0 "nonimmediate_operand" "=A")
199        (mult:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "%a"))
200                 (zero_extend:HI (match_operand:QI 2 "general_operand" "x"))))]
201  "rl78_real_insns_ok ()"
202  "mulu\t%2"
203)
204
205(define_insn "*andqi3_real"
206  [(set (match_operand:QI         0 "rl78_nonimmediate_operand"  "=WsfWsaWhlWab,A,R,vWsa")
207	(and:QI (match_operand:QI 1 "rl78_general_operand"       "%0,0,0,0")
208		(match_operand:QI 2 "rl78_general_operand"       "IBqi,iRvWabWhbWh1Whl,A,i")))
209   ]
210  "rl78_real_insns_ok ()"
211  "@
212   clr1\t%0.%B2
213   and\t%0, %2
214   and\t%0, %2
215   and\t%0, %2"
216  [(set_attr "update_Z" "*,update_Z,update_Z,update_Z")]
217)
218
219(define_insn "*iorqi3_real"
220  [(set (match_operand:QI         0 "rl78_nonimmediate_operand"  "=WsfWsaWhlWab,A,R,vWsa")
221	(ior:QI (match_operand:QI 1 "rl78_general_operand"       "%0,0,0,0")
222		(match_operand:QI 2 "rl78_general_operand"       "Ibqi,iRvWabWhbWh1Whl,A,i")))
223   ]
224  "rl78_real_insns_ok ()"
225  "@
226   set1\t%0.%B2
227   or\t%0, %2
228   or\t%0, %2
229   or\t%0, %2"
230  [(set_attr "update_Z" "*,update_Z,update_Z,update_Z")]
231)
232
233(define_insn "*xorqi3_real"
234  [(set (match_operand:QI         0 "rl78_nonimmediate_operand"  "=A,R,vWsa")
235	(xor:QI (match_operand:QI 1 "rl78_general_operand"       "%0,0,0")
236		(match_operand    2 "rl78_general_operand"       "iRvWabWhbWh1Whl,A,i")))
237   ]
238  "rl78_real_insns_ok ()"
239  "xor\t%0, %2"
240  [(set (attr "update_Z") (const_string "update_Z"))]
241)
242
243;;---------- Shifts ------------------------
244
245(define_insn "*ashlqi3_real"
246  [(set (match_operand:QI            0 "nonimmediate_operand"  "=abc,a,a")
247	(ashift:QI (match_operand:QI 1 "general_operand"  "0,0,0")
248		   (match_operand:QI 2 "general_operand" "Int3,bc,dehl")))
249   ]
250  "rl78_real_insns_ok ()"
251  "@
252   shl\t%0, %u2
253   cmp0 %2\; bz $2f\; 1: shl\t%0, 1 \;dec %2 \;bnz $1b\;2:
254   inc %2\;dec %2\;bz $2f\;1: shl\t%0, 1 \;dec %2 \;bnz $1b\;2:"
255  [(set_attr "update_Z" "*,clobber,clobber")]
256)
257
258(define_insn "*ashlhi3_real"
259  [(set (match_operand:HI            0 "nonimmediate_operand"  "=AB,A,A")
260	(ashift:HI (match_operand:HI 1 "general_operand"  "0,0,0")
261		   (match_operand:QI 2 "general_operand" "P,bc,dehl")))
262   ]
263  "rl78_real_insns_ok ()"
264  "@
265   shlw\t%0, %u2
266   cmp0 %2\; bz $2f\; 1: shlw\t%0, 1 \;dec %2 \;bnz $1b\;2:
267   inc %2\;dec %2\;bz $2f\;1: shlw\t%0, 1 \;dec %2 \;bnz $1b\;2:"
268  [(set_attr "update_Z" "*,clobber,clobber")]
269)
270
271;;----------
272
273(define_insn "*ashrqi3_real"
274  [(set (match_operand:QI              0 "nonimmediate_operand"  "=abc,a,a")
275	(ashiftrt:QI (match_operand:QI 1 "general_operand"  "0,0,0")
276		     (match_operand:QI 2 "general_operand" "Int3,bc,dehl")))
277   ]
278  "rl78_real_insns_ok ()"
279  "@
280   sar\t%0, %u2
281   cmp0 %2\; bz $2f\; 1: sar\t%0, 1 \;dec %2 \;bnz $1b\;2:
282   inc %2\;dec %2\;bz $2f\;1: sar\t%0, 1\;dec %2 \;bnz $1b\;2:"
283  [(set_attr "update_Z" "*,clobber,clobber")]
284)
285
286(define_insn "*ashrhi3_real"
287  [(set (match_operand:HI              0 "nonimmediate_operand"  "=AB,A,A")
288	(ashiftrt:HI (match_operand:HI 1 "general_operand"  "0,0,0")
289		     (match_operand:QI 2 "general_operand" "P,bc,dehl")))
290   ]
291  "rl78_real_insns_ok ()"
292  "@
293   sarw\t%0, %u2
294   cmp0 %2\; bz $2f\; 1: sarw\t%0, 1 \;dec %2 \;bnz $1b\;2:
295   inc %2\;dec %2\;bz $2f\;1: sarw\t%0, 1\;dec %2\;bnz $1b\;2:"
296  [(set_attr "update_Z" "*,clobber,clobber")]
297)
298
299;;----------
300
301(define_insn "*lshrqi3_real"
302  [(set (match_operand:QI              0 "nonimmediate_operand"  "=abc,a,a")
303	(lshiftrt:QI (match_operand:QI 1 "general_operand"  "0,0,0")
304		     (match_operand:QI 2 "general_operand" "Int3,bc,dehl")))
305   ]
306  "rl78_real_insns_ok ()"
307  "@
308   shr\t%0, %u2
309   cmp0 %2\; bz $2f\; 1: shr\t%0, 1 \;dec %2 \;bnz $1b\;2:
310   inc %2\;dec %2\;bz $2f\;1: shr\t%0, 1\;dec %2\;bnz $1b\;2:"
311  [(set_attr "update_Z" "*,clobber,clobber")]
312)
313
314(define_insn "*lshrhi3_real"
315  [(set (match_operand:HI              0 "nonimmediate_operand"  "=AB,A,A")
316	(lshiftrt:HI (match_operand:HI 1 "general_operand"  "0,0,0")
317		     (match_operand:QI 2 "general_operand" "P,bc,dehl")))
318   ]
319  "rl78_real_insns_ok ()"
320  "@
321   shrw\t%0, %u2
322   cmp0 %2\; bz $2f\; 1: shrw\t%0, 1 \;dec %2 \;bnz $1b\;2:
323   inc %2\;dec %2\;bz $2f\;1: shrw\t%0, 1\;dec %2\;bnz $1b\;2:"
324  [(set_attr "update_Z" "*,clobber,clobber")]
325)
326
327;;---------- Branching ------------------------
328
329(define_insn "*indirect_jump_real"
330  [(set (pc)
331	(match_operand:HI 0 "nonimmediate_operand" "A"))]
332  "rl78_real_insns_ok ()"
333  "br\t%0"
334)
335
336(define_insn "jump"
337  [(set (pc)
338	(label_ref (match_operand 0 "" "")))]
339  ""
340  ;; $rel8, $!rel16, !abs16, !!abs20
341  "br\t!!%0"
342)
343
344(define_insn "*call_real"
345  [(call (match_operand:HI 0 "memory_operand" "Wab,Wca")
346	 (match_operand 1 "" ""))]
347  "rl78_real_insns_ok ()"
348  "@
349   call\t!!%A0
350   call\t%A0"
351  [(set (attr "update_Z") (const_string "clobber"))]
352  )
353
354;; Peephole to match:
355;;
356;;	(set (reg1) (reg2))
357;;	(call (mem (reg1)))
358;;
359;;  and replace it with:
360;;
361;;	(call (mem (reg2)))
362
363(define_peephole2
364  [(set (match_operand:HI 0 "register_operand") (match_operand:HI 1 "register_operand"))
365   (call (mem:HI (match_dup 0))(const_int 0))
366  ]
367  "peep2_regno_dead_p (2, REGNO (operands[0]))
368   && REGNO (operands[1]) < 8"
369  [(call (mem:HI (match_dup 1))(const_int 0))
370  ]
371)
372
373(define_insn "*call_value_real"
374  [(set (match_operand 0 "register_operand" "=v,v")
375	(call (match_operand:HI 1 "memory_operand" "Wab,Wca")
376	      (match_operand 2 "" "")))]
377  "rl78_real_insns_ok ()"
378  "@
379   call\t!!%A1
380   call\t%A1"
381  [(set (attr "update_Z") (const_string "clobber"))]
382  )
383
384;; Peephole to match:
385;;
386;;	(set (reg1) (reg2))
387;;	(set (reg3) (call (mem (reg1))))
388;;
389;;  and replace it with:
390;;
391;;	(set (reg3) (call (mem (reg2))))
392
393(define_peephole2
394  [(set (match_operand:HI 0 "register_operand") (match_operand:HI 1 "register_operand"))
395   (set (match_operand:HI 2 "register_operand") (call (mem:HI (match_dup 0))(const_int 0)))
396  ]
397  "peep2_regno_dead_p (2, REGNO (operands[0]))
398   && REGNO (operands[1]) < 8"
399  [(set (match_dup 2) (call (mem:HI (match_dup 1))(const_int 0)))
400  ]
401)
402
403(define_insn "*cbranchqi4_real_signed"
404  [(set (pc) (if_then_else
405	      (match_operator 0 "rl78_cmp_operator_signed"
406			      [(match_operand:QI 1 "general_operand" "A,A,A,A,Wsa")
407			       (match_operand:QI 2 "general_operand" "M,ISqi,i,v,i")])
408              (label_ref (match_operand 3 "" ""))
409	      (pc)))]
410  "rl78_real_insns_ok ()"
411  {
412    gcc_assert (GET_CODE (operands[0]) != EQ && GET_CODE (operands[0]) != NE);
413
414    switch (which_alternative)
415    {
416    case 0: return "cmp0\t%1\; xor1\tCY, %1.7\; sk%C0\; br\t!!%3";
417    case 1: return "cmp\t%1, %2\; xor1\tCY, %1.7\; not1\tCY\; sk%C0\; br\t!!%3";
418    case 4:
419    case 2: return "cmp\t%1, %2\; xor1\tCY, %1.7\; sk%C0\; br\t!!%3";
420    case 3: return "cmp\t%1, %2\; xor1\tCY, %1.7\; xor1\tCY, %2.7\; sk%C0\; br\t!!%3";
421    default: gcc_unreachable ();
422    }
423  }
424  [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: flags are set based on %1 vs %2
425  )
426
427(define_insn "*cbranchqi4_real"
428  [(set (pc) (if_then_else
429	      (match_operator 0 "rl78_cmp_operator_real"
430			      [(match_operand:QI 1 "rl78_general_operand" "Wabvaxbc,a,              vWsaWab,bcdehl")
431			       (match_operand:QI 2 "rl78_general_operand" "M,       iRvWabWhlWh1Whb,i,a")])
432              (label_ref (match_operand 3 "" ""))
433	      (pc)))]
434  "rl78_real_insns_ok ()"
435  {
436    if (which_alternative == 0)
437      {
438        if (rl78_flags_already_set (operands[0], operands[1]))
439          return "sk%C0\; br\t!!%3\; # zero-comparison eliminated";
440	else
441	  return "cmp0\t%1\; sk%C0\; br\t!!%3";
442      }
443    return "cmp\t%1, %2\; sk%C0\; br\t!!%3";
444  }
445  [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: alt 0: flags are set based on %1 vs %2
446  )
447
448(define_insn "*cbranchhi4_real_signed"
449  [(set (pc) (if_then_else
450	      (match_operator 0 "rl78_cmp_operator_signed"
451			      [(match_operand:HI 1 "general_operand" "A,A,A,vR")
452			       (match_operand:HI 2 "general_operand" "IShi,i,v,1")])
453              (label_ref (match_operand 3))
454	      (pc)))]
455  "rl78_real_insns_ok ()"
456  "@
457   cmpw\t%1, %2\; xor1\tCY, %Q1.7\; not1\tCY\; sk%C0\; br\t!!%3
458   cmpw\t%1, %2\; xor1\tCY, %Q1.7\; sk%C0\; br\t!!%3
459   cmpw\t%1, %2\; xor1\tCY, %Q1.7\; xor1\tCY, %Q2.7\; sk%C0\; br\t!!%3
460   %z0\t!!%3"
461  [(set_attr "update_Z" "clobber,clobber,clobber,*")]
462  )
463
464(define_insn "cbranchhi4_real"
465  [(set (pc) (if_then_else
466	      (match_operator                    0 "rl78_cmp_operator_real"
467			      [(match_operand:HI 1 "general_operand" "A,A,vR")
468			       (match_operand:HI 2 "rl78_general_operand" "M,iBDTvWabWhlWh1,1")])
469              (label_ref (match_operand          3 "" ""))
470	      (pc)))]
471  "rl78_real_insns_ok ()"
472  {
473    switch (which_alternative)
474      {
475      case 0:
476        if (rl78_flags_already_set (operands[0], operands[1]))
477	  return "sk%C0\; br\t!!%3\; # cmpw eliminated";
478	/* else fall through.  */
479      case 1:
480	return "cmpw\t%1, %2\; sk%C0\; br\t!!%3";
481      case 2:
482        return "%z0\t!!%3";
483      default:
484        gcc_unreachable ();
485      }
486  }
487  [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: Z might be set based on %1 vs %2
488  )
489
490(define_insn "cbranchhi4_real_inverted"
491  [(set (pc) (if_then_else
492	      (match_operator                    0 "rl78_cmp_operator_real"
493			      [(match_operand:HI 1 "general_operand" "A,A")
494			       (match_operand:HI 2 "rl78_general_operand" "M,iBDTvWabWhlWh1")])
495	      (pc)
496              (label_ref (match_operand          3 "" ""))))]
497  "rl78_real_insns_ok ()"
498  {
499    if (which_alternative == 0 && rl78_flags_already_set (operands[0], operands[1]))
500      return "sk%C0\; br\t!!%3\; # inverted cmpw eliminated";
501    else
502      return "cmpw\t%1, %2\; sk%C0\; br\t!!%3";
503  }
504  [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: flags are set based on %1 vs %2
505  )
506
507(define_insn "*cbranchsi4_real_lt"
508  [(set (pc) (if_then_else
509	      (lt (match_operand:SI 0 "rl78_general_operand" "U,vWabWhlWh1")
510		  (const_int 0))
511              (label_ref (match_operand 1 "" ""))
512	      (pc)))
513   (clobber (reg:HI AX_REG))
514   ]
515  "rl78_real_insns_ok ()"
516  "@
517   mov\ta, %E0\; mov1\tCY, a.7\; sknc\; br\t!!%1
518   mov1\tCY, %E0.7\; sknc\; br\t!!%1"
519  )
520
521(define_insn "*cbranchsi4_real_ge"
522  [(set (pc) (if_then_else
523	      (ge (match_operand:SI 0 "rl78_general_operand" "U,vWabWhlWh1")
524		  (const_int 0))
525              (label_ref (match_operand 1 "" ""))
526	      (pc)))
527   (clobber (reg:HI AX_REG))
528   ]
529  "rl78_real_insns_ok ()"
530  "@
531   mov\ta, %E0\; mov1\tCY, a.7\; skc\; br\t!!%1
532   mov1\tCY, %E0.7\; skc\; br\t!!%1"
533  )
534
535(define_insn "*cbranchsi4_real_signed"
536  [(set (pc) (if_then_else
537	      (match_operator 0 "rl78_cmp_operator_signed"
538			      [(match_operand:SI 1 "general_operand"   "vU,vU,vU,i,i")
539			       (match_operand:SI 2 "nonmemory_operand" "ISsi,i,v,S,v")])
540              (label_ref (match_operand 3 "" ""))
541	      (pc)))
542   (clobber (reg:HI AX_REG))
543   ]
544  "rl78_real_insns_ok ()"
545  "@
546   movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; not1\tCY\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3
547   movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3
548   movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; xor1\tCY, %E2.7\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3
549   movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; not1\tCY\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%0\; br\t!!%3
550   movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%0\; br\t!!%3"
551  [(set (attr "update_Z") (const_string "clobber"))]
552  )
553
554(define_insn "*cbranchsi4_real"
555  [(set (pc) (if_then_else
556	      (match_operator 0 "rl78_cmp_operator_real"
557			      [(match_operand:SI 1 "general_operand" "vUi")
558			       (match_operand:SI 2 "general_operand" "iWhlWh1v")])
559              (label_ref (match_operand 3 "" ""))
560	      (pc)))
561   (clobber (reg:HI AX_REG))
562   ]
563  "rl78_real_insns_ok ()"
564  "movw\tax, %H1\; cmpw\tax, %H2\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3"
565  [(set (attr "update_Z") (const_string "clobber"))]
566  )
567
568;; Peephole to match:
569;;
570;;     (set (mem (sp)) (ax))
571;;     (set (ax) (mem (sp)))
572;; or:
573;;     (set (mem (plus (sp) (const)) (ax))
574;;     (set (ax) (mem (plus (sp) (const))))
575;;
576;; which can be generated as the last instruction of the conversion
577;; of one virtual insn into a real insn and the first instruction of
578;; the conversion of the following virtual insn.
579
580(define_peephole2
581  [(set (match_operand:HI 0 "rl78_stack_based_mem")
582	(reg:HI AX_REG))
583   (set (reg:HI AX_REG)
584	(match_dup 0))]
585  ""
586  [(set (match_dup 0) (reg:HI AX_REG))]
587  )
588
589;; Bit test and branch insns.
590
591;; NOTE: These patterns will work for bits in other places, not just A.
592
593(define_insn "bf"
594  [(set (pc)
595	(if_then_else (eq (and (reg:QI A_REG)
596			       (match_operand 0 "immediate_operand" "n"))
597			  (const_int 0))
598		      (label_ref (match_operand 1 "" ""))
599		      (pc)))]
600  ""
601  "bt\tA.%B0, $1f\n\tbr !!%1\n\t1:"
602  [(set (attr "update_Z") (const_string "clobber"))]
603)
604
605(define_insn "bt"
606  [(set (pc)
607	(if_then_else (ne (and (reg:QI A_REG)
608			       (match_operand 0 "immediate_operand" "n"))
609			  (const_int 0))
610		      (label_ref (match_operand 1 "" ""))
611		      (pc)))]
612  ""
613  "bf\tA.%B0, $1f\n\tbr !!%1\n\t1:"
614  [(set (attr "update_Z") (const_string "clobber"))]
615)
616
617;; NOTE: These peepholes are fragile.  They rely upon GCC generating
618;; a specific sequence on insns, based upon examination of test code.
619;; Improvements to GCC or using code other than the test code can result
620;; in the peephole not matching and the optimization being missed.
621
622(define_peephole2
623  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
624   (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
625   (set (pc) (if_then_else (eq (match_dup 0) (const_int 0))
626			   (label_ref (match_operand 2 ""))
627			   (pc)))]
628  "peep2_regno_dead_p (3, REGNO (operands[0]))
629   && exact_log2 (INTVAL (operands[1])) >= 0"
630  [(set (pc) (if_then_else (eq (and (reg:QI A_REG) (match_dup 1)) (const_int 0))
631			   (label_ref (match_dup 2))
632			   (pc)))]
633  )
634
635(define_peephole2
636  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
637   (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
638   (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
639			   (label_ref (match_operand 2 ""))
640			   (pc)))]
641  "peep2_regno_dead_p (3, REGNO (operands[0]))
642   && exact_log2 (INTVAL (operands[1])) >= 0"
643  [(set (pc) (if_then_else (ne (and (reg:QI A_REG) (match_dup 1)) (const_int 0))
644			   (label_ref (match_dup 2))
645			   (pc)))]
646  )
647
648;; Eliminate needless register copies.
649(define_peephole2
650  [(set (match_operand:HI 0 "register_operand") (match_operand:HI 1 "register_operand"))
651   (set (match_operand:HI 2 "register_operand") (match_dup 0))]
652  "peep2_regno_dead_p (2, REGNO (operands[0]))
653   && (REGNO (operands[1]) < 8 || REGNO (operands[2]) < 8)"
654  [(set (match_dup 2) (match_dup 1))]
655  )
656
657;; Eliminate needless register copying when performing bit manipulations.
658(define_peephole2
659  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
660   (set (match_dup 0) (ior:QI (match_dup 0) (match_operand 1 "immediate_operand")))
661   (set (reg:QI A_REG) (match_dup 0))]
662  "peep2_regno_dead_p (3, REGNO (operands[0]))"
663  [(set (reg:QI A_REG) (ior:QI (reg:QI A_REG) (match_dup 1)))]
664  )
665
666(define_peephole2
667  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
668   (set (match_dup 0) (xor:QI (match_dup 0) (match_operand 1 "immediate_operand")))
669   (set (reg:QI A_REG) (match_dup 0))]
670  "peep2_regno_dead_p (3, REGNO (operands[0]))"
671  [(set (reg:QI A_REG) (xor:QI (reg:QI A_REG) (match_dup 1)))]
672  )
673
674(define_peephole2
675  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
676   (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
677   (set (reg:QI A_REG) (match_dup 0))]
678  "peep2_regno_dead_p (3, REGNO (operands[0]))"
679  [(set (reg:QI A_REG) (and:QI (reg:QI A_REG) (match_dup 1)))]
680  )
681
682(define_insn "*negandhi3_real"
683  [(set (match_operand:HI                 0 "register_operand"  "=A")
684	(and:HI (neg:HI (match_operand:HI 1 "register_operand"  "0"))
685		(match_operand:HI         2 "immediate_operand" "n")))
686   ]
687  "rl78_real_insns_ok ()"
688  "xor a, #0xff @ xch a, x @ xor a, #0xff @ xch a, x @ addw ax, #1 @ and a, %Q2 @ xch a, x @ and a, %q2 @ xch a, x"
689  [(set (attr "update_Z") (const_string "clobber"))]
690)
691