1;; Machine Descriptions for R8C/M16C/M32C 2;; Copyright (C) 2006, 2007, 2010 3;; Free Software Foundation, Inc. 4;; Contributed by Red Hat. 5;; 6;; This file is part of GCC. 7;; 8;; GCC is free software; you can redistribute it and/or modify it 9;; under the terms of the GNU General Public License as published 10;; by the Free Software Foundation; either version 3, or (at your 11;; option) any later version. 12;; 13;; GCC is distributed in the hope that it will be useful, but WITHOUT 14;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16;; License for more details. 17;; 18;; You should have received a copy of the GNU General Public License 19;; along with GCC; see the file COPYING3. If not see 20;; <http://www.gnu.org/licenses/>. 21 22;; various block move instructions 23 24;; R8C: 25;; SMOVB - while (r3--) { *a1-- = *r1ha0--; } - memcpy 26;; SMOVF - while (r3--) { *a1++ = *r1ha0++; } - memcpy 27;; SSTR - while (r3--) { *a1++ = [r0l,r0]; } - memset 28 29;; M32CM: 30;; SCMPU - while (*a0 && *a0 != *a1) { a0++; a1++; } - strcmp 31;; SIN - while (r3--) { *a1++ = *a0; } 32;; SMOVB - while (r3--) { *a1-- = *a0--; } - memcpy 33;; SMOVF - while (r3--) { *a1++ = *a0++; } - memcpy 34;; SMOVU - while (*a1++ = *a0++) ; - strcpy 35;; SOUT - while (r3--) { *a1 = *a0++; } 36;; SSTR - while (r3--) { *a1++ = [r0l,r0]; } - memset 37 38 39 40;; 0 = destination (mem:BLK ...) 41;; 1 = source (mem:BLK ...) 42;; 2 = count 43;; 3 = alignment 44(define_expand "movmemhi" 45 [(match_operand 0 "ap_operand" "") 46 (match_operand 1 "ap_operand" "") 47 (match_operand 2 "m32c_r3_operand" "") 48 (match_operand 3 "" "") 49 ] 50 "" 51 "if (m32c_expand_movmemhi(operands)) DONE; FAIL;" 52 ) 53 54;; We can't use mode iterators for these because M16C uses r1h to extend 55;; the source address, for copying data from ROM to RAM. We don't yet 56;; support that, but we need to zero our r1h, so the patterns differ. 57 58;; 0 = dest (out) 59;; 1 = src (out) 60;; 2 = count (out) 61;; 3 = dest (in) 62;; 4 = src (in) 63;; 5 = count (in) 64(define_insn "movmemhi_bhi_op" 65 [(set (mem:QI (match_operand:HI 3 "ap_operand" "0")) 66 (mem:QI (match_operand:HI 4 "ap_operand" "1"))) 67 (set (match_operand:HI 2 "m32c_r3_operand" "=R3w") 68 (const_int 0)) 69 (set (match_operand:HI 0 "ap_operand" "=Ra1") 70 (plus:HI (match_dup 3) 71 (zero_extend:HI (match_operand:HI 5 "m32c_r3_operand" "2")))) 72 (set (match_operand:HI 1 "ap_operand" "=Ra0") 73 (plus:HI (match_dup 4) 74 (zero_extend:HI (match_dup 5)))) 75 (use (reg:HI R1_REGNO))] 76 "TARGET_A16" 77 "mov.b:q\t#0,r1h\n\tsmovf.b\t; %0[0..%2-1]=r1h%1[]" 78 ) 79(define_insn "movmemhi_bpsi_op" 80 [(set (mem:QI (match_operand:PSI 3 "ap_operand" "0")) 81 (mem:QI (match_operand:PSI 4 "ap_operand" "1"))) 82 (set (match_operand:HI 2 "m32c_r3_operand" "=R3w") 83 (const_int 0)) 84 (set (match_operand:PSI 0 "ap_operand" "=Ra1") 85 (plus:PSI (match_dup 3) 86 (zero_extend:PSI (match_operand:HI 5 "m32c_r3_operand" "2")))) 87 (set (match_operand:PSI 1 "ap_operand" "=Ra0") 88 (plus:PSI (match_dup 4) 89 (zero_extend:PSI (match_dup 5))))] 90 "TARGET_A24" 91 "smovf.b\t; %0[0..%2-1]=%1[]" 92 ) 93(define_insn "movmemhi_whi_op" 94 [(set (mem:HI (match_operand:HI 3 "ap_operand" "0")) 95 (mem:HI (match_operand:HI 4 "ap_operand" "1"))) 96 (set (match_operand:HI 2 "m32c_r3_operand" "=R3w") 97 (const_int 0)) 98 (set (match_operand:HI 0 "ap_operand" "=Ra1") 99 (plus:HI (match_dup 3) 100 (zero_extend:HI (match_operand:HI 5 "m32c_r3_operand" "2")))) 101 (set (match_operand:HI 1 "ap_operand" "=Ra0") 102 (plus:HI (match_dup 4) 103 (zero_extend:HI (match_dup 5)))) 104 (use (reg:HI R1_REGNO))] 105 "TARGET_A16" 106 "mov.b:q\t#0,r1h\n\tsmovf.w\t; %0[0..%2-1]=r1h%1[]" 107 ) 108(define_insn "movmemhi_wpsi_op" 109 [(set (mem:HI (match_operand:PSI 3 "ap_operand" "0")) 110 (mem:HI (match_operand:PSI 4 "ap_operand" "1"))) 111 (set (match_operand:HI 2 "m32c_r3_operand" "=R3w") 112 (const_int 0)) 113 (set (match_operand:PSI 0 "ap_operand" "=Ra1") 114 (plus:PSI (match_dup 3) 115 (zero_extend:PSI (match_operand:HI 5 "m32c_r3_operand" "2")))) 116 (set (match_operand:PSI 1 "ap_operand" "=Ra0") 117 (plus:PSI (match_dup 4) 118 (zero_extend:PSI (match_dup 5))))] 119 "TARGET_A24" 120 "smovf.w\t; %0[0..%2-1]=%1[]" 121 ) 122 123 124 125;; 0 = destination (mem:BLK ...) 126;; 1 = number of bytes 127;; 2 = value to store 128;; 3 = alignment 129(define_expand "setmemhi" 130 [(match_operand 0 "ap_operand" "") 131 (match_operand 1 "m32c_r3_operand" "") 132 (match_operand 2 "m32c_r0_operand" "") 133 (match_operand 3 "" "") 134 ] 135 "TARGET_A24" 136 "if (m32c_expand_setmemhi(operands)) DONE; FAIL;" 137 ) 138 139;; 0 = address (out) 140;; 1 = count (out) 141;; 2 = value (in) 142;; 3 = address (in) 143;; 4 = count (in) 144(define_insn "setmemhi_b<mode>_op" 145 [(set (mem:QI (match_operand:HPSI 3 "ap_operand" "0")) 146 (match_operand:QI 2 "m32c_r0_operand" "R0w")) 147 (set (match_operand:HI 1 "m32c_r3_operand" "=R3w") 148 (const_int 0)) 149 (set (match_operand:HPSI 0 "ap_operand" "=Ra1") 150 (plus:HPSI (match_dup 3) 151 (zero_extend:HPSI (match_operand:HI 4 "m32c_r3_operand" "1"))))] 152 "TARGET_A24" 153 "sstr.b\t; %0[0..%1-1]=%2" 154 ) 155 156(define_insn "setmemhi_w<mode>_op" 157 [(set (mem:HI (match_operand:HPSI 3 "ap_operand" "0")) 158 (match_operand:HI 2 "m32c_r0_operand" "R0w")) 159 (set (match_operand:HI 1 "m32c_r3_operand" "=R3w") 160 (const_int 0)) 161 (set (match_operand:HPSI 0 "ap_operand" "=Ra1") 162 (plus:HPSI (match_dup 3) 163 (zero_extend:HPSI (match_operand:HI 4 "m32c_r3_operand" "1"))))] 164 "TARGET_A24" 165 "sstr.w\t; %0[0..%1-1]=%2" 166 ) 167 168 169;; SCMPU sets the flags according to the result of the string 170;; comparison. GCC wants the result to be a signed value reflecting 171;; the result, which it then compares to zero. Hopefully we can 172;; optimize that later (see peephole in cond.md). Meanwhile, the 173;; strcmp builtin is expanded to a SCMPU followed by a flags-to-int 174;; pattern in cond.md. 175 176;; 0 = result:HI 177;; 1 = destination (mem:BLK ...) 178;; 2 = source (mem:BLK ...) 179;; 3 = alignment 180 181(define_expand "cmpstrsi" 182 [(match_operand:HI 0 "" "") 183 (match_operand 1 "ap_operand" "") 184 (match_operand 2 "ap_operand" "") 185 (match_operand 3 "" "") 186 ] 187 "TARGET_A24" 188 "if (m32c_expand_cmpstr(operands)) DONE; FAIL;" 189 ) 190 191;; 0 = string1 192;; 1 = string2 193 194(define_insn "cmpstrhi_op" 195 [(set (reg:CC FLG_REGNO) 196 (compare:CC (mem:BLK (match_operand:PSI 0 "ap_operand" "Ra0")) 197 (mem:BLK (match_operand:PSI 1 "ap_operand" "Ra1")))) 198 (clobber (match_operand:PSI 2 "ap_operand" "=0")) 199 (clobber (match_operand:PSI 3 "ap_operand" "=1"))] 200 "TARGET_A24" 201 "scmpu.b\t; flags := strcmp(*%0,*%1)" 202 [(set_attr "flags" "oszc")] 203 ) 204 205 206 207;; Note that SMOVU leaves the address registers pointing *after* 208;; the NUL at the end of the string. This is not what gcc expects; it 209;; expects the address registers to point *at* the NUL. The expander 210;; must emit a suitable add insn. 211 212;; 0 = target: set to &NUL in dest 213;; 1 = destination (mem:BLK ...) 214;; 2 = source (mem:BLK ...) 215 216(define_expand "movstr" 217 [(match_operand 0 "m32c_nonimmediate_operand" "") 218 (match_operand 1 "ap_operand" "") 219 (match_operand 2 "ap_operand" "") 220 ] 221 "TARGET_A24" 222 "if (m32c_expand_movstr(operands)) DONE; FAIL;" 223 ) 224 225;; 0 = dest (out) 226;; 1 = src (out) (clobbered) 227;; 2 = dest (in) 228;; 3 = src (in) 229(define_insn "movstr_op" 230 [(set (mem:BLK (match_operand:PSI 2 "ap_operand" "0")) 231 (mem:BLK (match_operand:PSI 3 "ap_operand" "1"))) 232 (set (match_operand:PSI 0 "ap_operand" "=Ra1") 233 (plus:PSI (match_dup 2) 234 (unspec:PSI [(const_int 0)] UNS_SMOVU))) 235 (set (match_operand:PSI 1 "ap_operand" "=Ra0") 236 (plus:PSI (match_dup 3) 237 (unspec:PSI [(const_int 0)] UNS_SMOVU)))] 238 "TARGET_A24" 239 "smovu.b\t; while (*%2++ := *%3++) != 0" 240 [(set_attr "flags" "*")] 241 ) 242 243