163d1a8abSmrg;; Machine Descriptions for R8C/M16C/M32C
2*ec02198aSmrg;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
363d1a8abSmrg;; Contributed by Red Hat.
463d1a8abSmrg;;
563d1a8abSmrg;; This file is part of GCC.
663d1a8abSmrg;;
763d1a8abSmrg;; GCC is free software; you can redistribute it and/or modify it
863d1a8abSmrg;; under the terms of the GNU General Public License as published
963d1a8abSmrg;; by the Free Software Foundation; either version 3, or (at your
1063d1a8abSmrg;; option) any later version.
1163d1a8abSmrg;;
1263d1a8abSmrg;; GCC is distributed in the hope that it will be useful, but WITHOUT
1363d1a8abSmrg;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1463d1a8abSmrg;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1563d1a8abSmrg;; License for more details.
1663d1a8abSmrg;;
1763d1a8abSmrg;; You should have received a copy of the GNU General Public License
1863d1a8abSmrg;; along with GCC; see the file COPYING3.  If not see
1963d1a8abSmrg;; <http://www.gnu.org/licenses/>.
2063d1a8abSmrg
2163d1a8abSmrg;; various block move instructions
2263d1a8abSmrg
2363d1a8abSmrg;; R8C:
2463d1a8abSmrg;;  SMOVB - while (r3--) { *a1-- = *r1ha0--; } - memcpy
2563d1a8abSmrg;;  SMOVF - while (r3--) { *a1++ = *r1ha0++; } - memcpy
2663d1a8abSmrg;;  SSTR  - while (r3--) { *a1++ = [r0l,r0]; } - memset
2763d1a8abSmrg
2863d1a8abSmrg;; M32CM:
2963d1a8abSmrg;;  SCMPU - while (*a0 && *a0 != *a1) { a0++; a1++; } - strcmp
3063d1a8abSmrg;;  SIN   - while (r3--) { *a1++ = *a0; }
3163d1a8abSmrg;;  SMOVB - while (r3--) { *a1-- = *a0--; } - memcpy
3263d1a8abSmrg;;  SMOVF - while (r3--) { *a1++ = *a0++; } - memcpy
3363d1a8abSmrg;;  SMOVU - while (*a1++ = *a0++) ; - strcpy
3463d1a8abSmrg;;  SOUT  - while (r3--) { *a1 = *a0++; }
3563d1a8abSmrg;;  SSTR  - while (r3--) { *a1++ = [r0l,r0]; } - memset
3663d1a8abSmrg
3763d1a8abSmrg
3863d1a8abSmrg
3963d1a8abSmrg;; 0 = destination (mem:BLK ...)
4063d1a8abSmrg;; 1 = source (mem:BLK ...)
4163d1a8abSmrg;; 2 = count
4263d1a8abSmrg;; 3 = alignment
43*ec02198aSmrg(define_expand "cpymemhi"
4463d1a8abSmrg  [(match_operand 0 "ap_operand" "")
4563d1a8abSmrg   (match_operand 1 "ap_operand" "")
4663d1a8abSmrg   (match_operand 2 "m32c_r3_operand" "")
4763d1a8abSmrg   (match_operand 3 "" "")
4863d1a8abSmrg   ]
4963d1a8abSmrg  ""
50*ec02198aSmrg  "if (m32c_expand_cpymemhi(operands)) DONE; FAIL;"
5163d1a8abSmrg  )
5263d1a8abSmrg
5363d1a8abSmrg;; We can't use mode iterators for these because M16C uses r1h to extend
5463d1a8abSmrg;; the source address, for copying data from ROM to RAM.  We don't yet
5563d1a8abSmrg;; support that, but we need to zero our r1h, so the patterns differ.
5663d1a8abSmrg
5763d1a8abSmrg;; 0 = dest (out)
5863d1a8abSmrg;; 1 = src (out)
5963d1a8abSmrg;; 2 = count (out)
6063d1a8abSmrg;; 3 = dest (in)
6163d1a8abSmrg;; 4 = src (in)
6263d1a8abSmrg;; 5 = count (in)
63*ec02198aSmrg(define_insn "cpymemhi_bhi_op"
6463d1a8abSmrg  [(set (mem:QI (match_operand:HI 3 "ap_operand" "0"))
6563d1a8abSmrg	(mem:QI (match_operand:HI 4 "ap_operand" "1")))
6663d1a8abSmrg   (set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
6763d1a8abSmrg	(const_int 0))
6863d1a8abSmrg   (set (match_operand:HI 0 "ap_operand" "=Ra1")
6963d1a8abSmrg	(plus:HI (match_dup 3)
7063d1a8abSmrg		  (zero_extend:HI (match_operand:HI 5 "m32c_r3_operand" "2"))))
7163d1a8abSmrg   (set (match_operand:HI 1 "ap_operand" "=Ra0")
7263d1a8abSmrg	(plus:HI (match_dup 4)
7363d1a8abSmrg		  (zero_extend:HI (match_dup 5))))
7463d1a8abSmrg   (use (reg:HI R1_REGNO))]
7563d1a8abSmrg  "TARGET_A16"
7663d1a8abSmrg  "mov.b:q\t#0,r1h\n\tsmovf.b\t; %0[0..%2-1]=r1h%1[]"
7763d1a8abSmrg  )
78*ec02198aSmrg(define_insn "cpymemhi_bpsi_op"
7963d1a8abSmrg  [(set (mem:QI (match_operand:PSI 3 "ap_operand" "0"))
8063d1a8abSmrg	(mem:QI (match_operand:PSI 4 "ap_operand" "1")))
8163d1a8abSmrg   (set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
8263d1a8abSmrg	(const_int 0))
8363d1a8abSmrg   (set (match_operand:PSI 0 "ap_operand" "=Ra1")
8463d1a8abSmrg	(plus:PSI (match_dup 3)
8563d1a8abSmrg		  (zero_extend:PSI (match_operand:HI 5 "m32c_r3_operand" "2"))))
8663d1a8abSmrg   (set (match_operand:PSI 1 "ap_operand" "=Ra0")
8763d1a8abSmrg	(plus:PSI (match_dup 4)
8863d1a8abSmrg		  (zero_extend:PSI (match_dup 5))))]
8963d1a8abSmrg  "TARGET_A24"
9063d1a8abSmrg  "smovf.b\t; %0[0..%2-1]=%1[]"
9163d1a8abSmrg  )
92*ec02198aSmrg(define_insn "cpymemhi_whi_op"
9363d1a8abSmrg  [(set (mem:HI (match_operand:HI 3 "ap_operand" "0"))
9463d1a8abSmrg	(mem:HI (match_operand:HI 4 "ap_operand" "1")))
9563d1a8abSmrg   (set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
9663d1a8abSmrg	(const_int 0))
9763d1a8abSmrg   (set (match_operand:HI 0 "ap_operand" "=Ra1")
9863d1a8abSmrg	(plus:HI (match_dup 3)
9963d1a8abSmrg		  (zero_extend:HI (match_operand:HI 5 "m32c_r3_operand" "2"))))
10063d1a8abSmrg   (set (match_operand:HI 1 "ap_operand" "=Ra0")
10163d1a8abSmrg	(plus:HI (match_dup 4)
10263d1a8abSmrg		  (zero_extend:HI (match_dup 5))))
10363d1a8abSmrg   (use (reg:HI R1_REGNO))]
10463d1a8abSmrg  "TARGET_A16"
10563d1a8abSmrg  "mov.b:q\t#0,r1h\n\tsmovf.w\t; %0[0..%2-1]=r1h%1[]"
10663d1a8abSmrg  )
107*ec02198aSmrg(define_insn "cpymemhi_wpsi_op"
10863d1a8abSmrg  [(set (mem:HI (match_operand:PSI 3 "ap_operand" "0"))
10963d1a8abSmrg	(mem:HI (match_operand:PSI 4 "ap_operand" "1")))
11063d1a8abSmrg   (set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
11163d1a8abSmrg	(const_int 0))
11263d1a8abSmrg   (set (match_operand:PSI 0 "ap_operand" "=Ra1")
11363d1a8abSmrg	(plus:PSI (match_dup 3)
11463d1a8abSmrg		  (zero_extend:PSI (match_operand:HI 5 "m32c_r3_operand" "2"))))
11563d1a8abSmrg   (set (match_operand:PSI 1 "ap_operand" "=Ra0")
11663d1a8abSmrg	(plus:PSI (match_dup 4)
11763d1a8abSmrg		  (zero_extend:PSI (match_dup 5))))]
11863d1a8abSmrg  "TARGET_A24"
11963d1a8abSmrg  "smovf.w\t; %0[0..%2-1]=%1[]"
12063d1a8abSmrg  )
12163d1a8abSmrg
12263d1a8abSmrg
12363d1a8abSmrg
12463d1a8abSmrg;; 0 = destination (mem:BLK ...)
12563d1a8abSmrg;; 1 = number of bytes
12663d1a8abSmrg;; 2 = value to store
12763d1a8abSmrg;; 3 = alignment
12863d1a8abSmrg(define_expand "setmemhi"
12963d1a8abSmrg  [(match_operand 0 "ap_operand" "")
13063d1a8abSmrg   (match_operand 1 "m32c_r3_operand" "")
13163d1a8abSmrg   (match_operand 2 "m32c_r0_operand" "")
13263d1a8abSmrg   (match_operand 3 "" "")
13363d1a8abSmrg   ]
13463d1a8abSmrg  "TARGET_A24"
13563d1a8abSmrg  "if (m32c_expand_setmemhi(operands)) DONE; FAIL;"
13663d1a8abSmrg  )
13763d1a8abSmrg
13863d1a8abSmrg;; 0 = address (out)
13963d1a8abSmrg;; 1 = count (out)
14063d1a8abSmrg;; 2 = value (in)
14163d1a8abSmrg;; 3 = address (in)
14263d1a8abSmrg;; 4 = count (in)
14363d1a8abSmrg(define_insn "setmemhi_b<mode>_op"
14463d1a8abSmrg  [(set (mem:QI (match_operand:HPSI 3 "ap_operand" "0"))
14563d1a8abSmrg	(match_operand:QI 2 "m32c_r0_operand" "R0w"))
14663d1a8abSmrg   (set (match_operand:HI 1 "m32c_r3_operand" "=R3w")
14763d1a8abSmrg	(const_int 0))
14863d1a8abSmrg   (set (match_operand:HPSI 0 "ap_operand" "=Ra1")
14963d1a8abSmrg	(plus:HPSI (match_dup 3)
15063d1a8abSmrg		  (zero_extend:HPSI (match_operand:HI 4 "m32c_r3_operand" "1"))))]
15163d1a8abSmrg  "TARGET_A24"
15263d1a8abSmrg  "sstr.b\t; %0[0..%1-1]=%2"
15363d1a8abSmrg  )
15463d1a8abSmrg
15563d1a8abSmrg(define_insn "setmemhi_w<mode>_op"
15663d1a8abSmrg  [(set (mem:HI (match_operand:HPSI 3 "ap_operand" "0"))
15763d1a8abSmrg	(match_operand:HI 2 "m32c_r0_operand" "R0w"))
15863d1a8abSmrg   (set (match_operand:HI 1 "m32c_r3_operand" "=R3w")
15963d1a8abSmrg	(const_int 0))
16063d1a8abSmrg   (set (match_operand:HPSI 0 "ap_operand" "=Ra1")
16163d1a8abSmrg	(plus:HPSI (match_dup 3)
16263d1a8abSmrg		  (zero_extend:HPSI (match_operand:HI 4 "m32c_r3_operand" "1"))))]
16363d1a8abSmrg  "TARGET_A24"
16463d1a8abSmrg  "sstr.w\t; %0[0..%1-1]=%2"
16563d1a8abSmrg  )
16663d1a8abSmrg
16763d1a8abSmrg
16863d1a8abSmrg;; SCMPU sets the flags according to the result of the string
16963d1a8abSmrg;; comparison.  GCC wants the result to be a signed value reflecting
17063d1a8abSmrg;; the result, which it then compares to zero.  Hopefully we can
17163d1a8abSmrg;; optimize that later (see peephole in cond.md).  Meanwhile, the
17263d1a8abSmrg;; strcmp builtin is expanded to a SCMPU followed by a flags-to-int
17363d1a8abSmrg;; pattern in cond.md.
17463d1a8abSmrg
17563d1a8abSmrg;; 0 = result:HI
17663d1a8abSmrg;; 1 = destination (mem:BLK ...)
17763d1a8abSmrg;; 2 = source (mem:BLK ...)
17863d1a8abSmrg;; 3 = alignment
17963d1a8abSmrg
18063d1a8abSmrg(define_expand "cmpstrsi"
18163d1a8abSmrg  [(match_operand:HI 0 "register_operand" "")
18263d1a8abSmrg   (match_operand 1 "memory_operand" "")
18363d1a8abSmrg   (match_operand 2 "memory_operand" "")
18463d1a8abSmrg   (match_operand 3 "const_int_operand" "")
18563d1a8abSmrg   ]
18663d1a8abSmrg  "TARGET_A24"
18763d1a8abSmrg  "if (m32c_expand_cmpstr(operands)) DONE; FAIL;"
18863d1a8abSmrg  )
18963d1a8abSmrg
19063d1a8abSmrg;; 0 = string1
19163d1a8abSmrg;; 1 = string2
19263d1a8abSmrg
19363d1a8abSmrg(define_insn "cmpstrhi_op"
19463d1a8abSmrg  [(set (reg:CC FLG_REGNO)
19563d1a8abSmrg	(compare:CC (mem:BLK (match_operand:PSI 0 "ap_operand" "Ra0"))
19663d1a8abSmrg		    (mem:BLK (match_operand:PSI 1 "ap_operand" "Ra1"))))
19763d1a8abSmrg   (clobber (match_operand:PSI 2 "ap_operand" "=0"))
19863d1a8abSmrg   (clobber (match_operand:PSI 3 "ap_operand" "=1"))]
19963d1a8abSmrg  "TARGET_A24"
20063d1a8abSmrg  "scmpu.b\t; flags := strcmp(*%0,*%1)"
20163d1a8abSmrg  [(set_attr "flags" "oszc")]
20263d1a8abSmrg  )
20363d1a8abSmrg
20463d1a8abSmrg
20563d1a8abSmrg
20663d1a8abSmrg;; Note that SMOVU leaves the address registers pointing *after*
20763d1a8abSmrg;; the NUL at the end of the string.  This is not what gcc expects; it
20863d1a8abSmrg;; expects the address registers to point *at* the NUL.  The expander
20963d1a8abSmrg;; must emit a suitable add insn.
21063d1a8abSmrg
21163d1a8abSmrg;; 0 = target: set to &NUL in dest
21263d1a8abSmrg;; 1 = destination (mem:BLK ...)
21363d1a8abSmrg;; 2 = source (mem:BLK ...)
21463d1a8abSmrg
21563d1a8abSmrg(define_expand "movstr"
21663d1a8abSmrg  [(match_operand 0 "m32c_nonimmediate_operand" "")
21763d1a8abSmrg   (match_operand 1 "" "")
21863d1a8abSmrg   (match_operand 2 "" "")
21963d1a8abSmrg   ]
22063d1a8abSmrg  "TARGET_A24"
22163d1a8abSmrg  "if (m32c_expand_movstr(operands)) DONE; FAIL;"
22263d1a8abSmrg  )
22363d1a8abSmrg
22463d1a8abSmrg;; 0 = dest (out)
22563d1a8abSmrg;; 1 = src (out) (clobbered)
22663d1a8abSmrg;; 2 = dest (in)
22763d1a8abSmrg;; 3 = src (in)
22863d1a8abSmrg(define_insn "movstr_op"
22963d1a8abSmrg  [(set (mem:BLK (match_operand:PSI 2 "ap_operand" "0"))
23063d1a8abSmrg	(mem:BLK (match_operand:PSI 3 "ap_operand" "1")))
23163d1a8abSmrg   (set (match_operand:PSI 0 "ap_operand" "=Ra1")
23263d1a8abSmrg	(plus:PSI (match_dup 2)
23363d1a8abSmrg		  (unspec:PSI [(const_int 0)] UNS_SMOVU)))
23463d1a8abSmrg   (set (match_operand:PSI 1 "ap_operand" "=Ra0")
23563d1a8abSmrg	(plus:PSI (match_dup 3)
23663d1a8abSmrg		  (unspec:PSI [(const_int 0)] UNS_SMOVU)))]
23763d1a8abSmrg  "TARGET_A24"
23863d1a8abSmrg  "smovu.b\t; while (*%2++ := *%3++) != 0"
23963d1a8abSmrg  [(set_attr "flags" "*")]
24063d1a8abSmrg  )
24163d1a8abSmrg
242