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