1;; Machine Descriptions for R8C/M16C/M32C 2;; Copyright (C) 2005 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 2, 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 COPYING. If not, write to the Free 20;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21;; 02110-1301, USA. 22 23;; move, push, extend, etc. 24 25;; Be careful to never create an alternative that has memory as both 26;; src and dest, as that makes gcc think that mem-mem moves in general 27;; are supported. While the chip does support this, it only has two 28;; address registers and sometimes gcc requires more than that. One 29;; example is code like this: a = *b where both a and b are spilled to 30;; the stack. 31 32;; Match push/pop before mov.b for passing char as arg, 33;; e.g. stdlib/efgcvt.c. 34(define_insn "movqi_op" 35 [(set (match_operand:QI 0 "m32c_nonimmediate_operand" 36 "=Rqi*Rmm, <, RqiSd*Rmm, SdSs, Rqi*Rmm, Sd") 37 (match_operand:QI 1 "m32c_any_operand" 38 "iRqi*Rmm, iRqiSd*Rmm, >, Rqi*Rmm, SdSs, i"))] 39 "m32c_mov_ok (operands, QImode)" 40 "@ 41 mov.b\t%1,%0 42 push.b\t%1 43 pop.b\t%0 44 mov.b\t%1,%0 45 mov.b\t%1,%0 46 mov.b\t%1,%0" 47 [(set_attr "flags" "sz,*,*,sz,sz,sz")] 48 ) 49 50(define_expand "movqi" 51 [(set (match_operand:QI 0 "nonimmediate_operand" "=RqiSd*Rmm") 52 (match_operand:QI 1 "general_operand" "iRqiSd*Rmm"))] 53 "" 54 "if (m32c_prepare_move (operands, QImode)) DONE;" 55 ) 56 57 58(define_insn "movhi_op" 59 [(set (match_operand:HI 0 "m32c_nonimmediate_operand" 60 "=Rhi*Rmm, Sd, SdSs, *Rcr, RhiSd*Rmm, <, RhiSd*Rmm, <, *Rcr") 61 (match_operand:HI 1 "m32c_any_operand" 62 "iRhi*RmmSdSs, i, Rhi*Rmm, RhiSd*Rmm, *Rcr, iRhiSd*Rmm, >, *Rcr, >"))] 63 "m32c_mov_ok (operands, HImode)" 64 "@ 65 mov.w\t%1,%0 66 mov.w\t%1,%0 67 mov.w\t%1,%0 68 ldc\t%1,%0 69 stc\t%1,%0 70 push.w\t%1 71 pop.w\t%0 72 pushc\t%1 73 popc\t%0" 74 [(set_attr "flags" "sz,sz,sz,n,n,n,n,n,n")] 75 ) 76 77(define_expand "movhi" 78 [(set (match_operand:HI 0 "m32c_nonimmediate_operand" "=RhiSd*Rmm") 79 (match_operand:HI 1 "m32c_any_operand" "iRhiSd*Rmm"))] 80 "" 81 "if (m32c_prepare_move (operands, HImode)) DONE;" 82 ) 83 84 85(define_insn "movpsi_op" 86 [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" 87 "=Raa, SdRmmRpi, Rcl, RpiSd*Rmm, <, <, Rcl, RpiRaa*Rmm") 88 (match_operand:PSI 1 "m32c_any_operand" 89 "sIU3, iSdRmmRpi, iRpiSd*Rmm, Rcl, Rpi*Rmm, Rcl, >, >"))] 90 "TARGET_A24 && m32c_mov_ok (operands, PSImode)" 91 "@ 92 mov.l:s\t%1,%0 93 mov.l\t%1,%0 94 ldc\t%1,%0 95 stc\t%1,%0 96 push.l\t%1 97 pushc\t%1 98 popc\t%0 99 #" 100 [(set_attr "flags" "sz,sz,n,n,n,n,n,*")] 101 ) 102 103 104;; The intention here is to combine the add with the move to create an 105;; indexed move. GCC doesn't always figure this out itself. 106 107(define_peephole2 108 [(set (match_operand:HPSI 0 "register_operand" "") 109 (plus:HPSI (match_operand:HPSI 1 "register_operand" "") 110 (match_operand:HPSI 2 "immediate_operand" ""))) 111 (set (match_operand:QHSI 3 "nonimmediate_operand" "") 112 (mem:QHSI (match_operand:HPSI 4 "register_operand" "")))] 113 "REGNO (operands[0]) == REGNO (operands[1]) 114 && REGNO (operands[0]) == REGNO (operands[4]) 115 && (rtx_equal_p (operands[0], operands[3]) 116 || (dead_or_set_p (peep2_next_insn (1), operands[4]) 117 && ! reg_mentioned_p (operands[0], operands[3])))" 118 [(set (match_dup 3) 119 (mem:QHSI (plus:HPSI (match_dup 1) 120 (match_dup 2))))] 121 "") 122 123(define_peephole2 124 [(set (match_operand:HPSI 0 "register_operand" "") 125 (plus:HPSI (match_operand:HPSI 1 "register_operand" "") 126 (match_operand:HPSI 2 "immediate_operand" ""))) 127 (set (mem:QHSI (match_operand:HPSI 4 "register_operand" "")) 128 (match_operand:QHSI 3 "m32c_any_operand" ""))] 129 "REGNO (operands[0]) == REGNO (operands[1]) 130 && REGNO (operands[0]) == REGNO (operands[4]) 131 && dead_or_set_p (peep2_next_insn (1), operands[4]) 132 && ! reg_mentioned_p (operands[0], operands[3])" 133 [(set (mem:QHSI (plus:HPSI (match_dup 1) 134 (match_dup 2))) 135 (match_dup 3))] 136 "") 137 138; Peephole to generate SImode mov instructions for storing an 139; immediate double data to a memory location. 140(define_peephole2 141 [(set (match_operand:HI 0 "memory_operand" "") 142 (match_operand 1 "const_int_operand" "")) 143 (set (match_operand:HI 2 "memory_operand" "") 144 (match_operand 3 "const_int_operand" ""))] 145 "TARGET_A24 && m32c_immd_dbl_mov (operands, HImode)" 146 [(set (match_dup 4) (match_dup 5))] 147 "" 148) 149 150; Some PSI moves must be split. 151(define_split 152 [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "") 153 (match_operand:PSI 1 "m32c_any_operand" ""))] 154 "reload_completed && m32c_split_psi_p (operands)" 155 [(set (match_dup 2) 156 (match_dup 3)) 157 (set (match_dup 4) 158 (match_dup 5))] 159 "m32c_split_move (operands, PSImode, 3);" 160 ) 161 162(define_expand "movpsi" 163 [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "") 164 (match_operand:PSI 1 "m32c_any_operand" ""))] 165 "" 166 "if (m32c_prepare_move (operands, PSImode)) DONE;" 167 ) 168 169 170 171(define_expand "movsi" 172 [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=RsiSd*Rmm") 173 (match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm"))] 174 "" 175 "if (m32c_split_move (operands, SImode, 0)) DONE;" 176 ) 177 178; All SI moves are split if TARGET_A16 179(define_insn_and_split "movsi_splittable" 180 [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=Rsi<*Rmm,RsiSd*Rmm,Ss") 181 (match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm,iRsi>*Rmm,Rsi*Rmm"))] 182 "TARGET_A16" 183 "#" 184 "TARGET_A16 && reload_completed" 185 [(pc)] 186 "m32c_split_move (operands, SImode, 1); DONE;" 187 ) 188 189; The movsi pattern doesn't always match because sometimes the modes 190; don't match. 191(define_insn "push_a01_l" 192 [(set (mem:SI (pre_dec:PSI (reg:PSI SP_REGNO))) 193 (match_operand 0 "a_operand" "Raa"))] 194 "" 195 "push.l\t%0" 196 [(set_attr "flags" "n")] 197 ) 198 199(define_insn "movsi_24" 200 [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=Rsi*Rmm, Sd, RsiSd*Rmm, <") 201 (match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm, iRsi*Rmm, >, iRsiRaaSd*Rmm"))] 202 "TARGET_A24" 203 "@ 204 mov.l\t%1,%0 205 mov.l\t%1,%0 206 # 207 push.l\t%1" 208 [(set_attr "flags" "sz,sz,*,n")] 209 ) 210 211(define_expand "movdi" 212 [(set (match_operand:DI 0 "m32c_nonimmediate_operand" "=RdiSd*Rmm") 213 (match_operand:DI 1 "m32c_any_operand" "iRdiSd*Rmm"))] 214 "" 215 "if (m32c_split_move (operands, DImode, 0)) DONE;" 216 ) 217 218(define_insn_and_split "movdi_splittable" 219 [(set (match_operand:DI 0 "m32c_nonimmediate_operand" "=Rdi<*Rmm,RdiSd*Rmm") 220 (match_operand:DI 1 "m32c_any_operand" "iRdiSd*Rmm,iRdi>*Rmm"))] 221 "" 222 "#" 223 "reload_completed" 224 [(pc)] 225 "m32c_split_move (operands, DImode, 1); DONE;" 226 ) 227 228 229 230 231(define_insn "pushqi" 232 [(set (mem:QI (pre_dec:PSI (reg:PSI SP_REGNO))) 233 (match_operand:QI 0 "mrai_operand" "iRqiSd*Rmm"))] 234 "" 235 "push.b\t%0" 236 [(set_attr "flags" "n")] 237 ) 238 239(define_expand "pushhi" 240 [(set (mem:HI (pre_dec:PSI (reg:PSI SP_REGNO))) 241 (match_operand:HI 0 "" ""))] 242 "" 243 "if (TARGET_A16) 244 gen_pushhi_16 (operands[0]); 245 else 246 gen_pushhi_24 (operands[0]); 247 DONE;" 248 ) 249 250(define_insn "pushhi_16" 251 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO))) 252 (match_operand:HI 0 "mrai_operand" "iRhiSd*Rmm,Rcr"))] 253 "TARGET_A16" 254 "@ 255 push.w\t%0 256 pushc\t%0" 257 [(set_attr "flags" "n,n")] 258 ) 259 260(define_insn "pushhi_24" 261 [(set (mem:HI (pre_dec:PSI (reg:PSI SP_REGNO))) 262 (match_operand:HI 0 "mrai_operand" "iRhiSd*Rmm"))] 263 "TARGET_A24" 264 "push.w\t%0" 265 [(set_attr "flags" "n")] 266 ) 267 268;(define_insn "pushpi" 269; [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO))) 270; (match_operand:PI 0 "mrai_operand" "iRaa,Rcr"))] 271; "TARGET_A24" 272; "@ 273; push.l\t%0 274; pushc\t%0" 275; ) 276 277(define_insn "pushsi" 278 [(set (mem:SI (pre_dec:PSI (reg:PSI SP_REGNO))) 279 (match_operand:SI 0 "mrai_operand" "iRsiSd*Rmm"))] 280 "TARGET_A24" 281 "push.l\t%0" 282 [(set_attr "flags" "n")] 283 ) 284 285(define_expand "pophi" 286 [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm,Rcr") 287 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))] 288 "" 289 "if (TARGET_A16) 290 gen_pophi_16 (operands[0]); 291 else 292 gen_pophi_24 (operands[0]); 293 DONE;" 294 ) 295 296(define_insn "pophi_16" 297 [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm,Rcr") 298 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))] 299 "TARGET_A16" 300 "@ 301 pop.w\t%0 302 popc\t%0" 303 [(set_attr "flags" "n,n")] 304 ) 305 306(define_insn "pophi_24" 307 [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm") 308 (mem:HI (post_inc:PSI (reg:PSI SP_REGNO))))] 309 "TARGET_A24" 310 "pop.w\t%0" 311 [(set_attr "flags" "n")] 312 ) 313 314(define_insn "poppsi" 315 [(set (match_operand:PSI 0 "cr_operand" "=Rcl") 316 (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))] 317 "TARGET_A24" 318 "popc\t%0" 319 [(set_attr "flags" "n")] 320 ) 321 322 323;; Rhl used here as an HI-mode Rxl 324(define_insn "extendqihi2" 325[(set (match_operand:HI 0 "m32c_nonimmediate_operand" "=RhlSd*Rmm") 326 (sign_extend:HI (match_operand:QI 1 "mra_operand" "0")))] 327 "" 328 "exts.b\t%1" 329 [(set_attr "flags" "sz")] 330 ) 331 332(define_insn "extendhisi2" 333 [(set (match_operand:SI 0 "register_operand" "=R03") 334 (sign_extend:SI (match_operand:HI 1 "r0123_operand" "0")))] 335 "" 336 "* 337 if (REGNO(operands[0]) == 0) return \"exts.w\t%1\"; 338 else return \"mov.w r1,r3 | sha.w #-8,r3 | sha.w #-7,r3\";" 339 [(set_attr "flags" "x")] 340 ) 341 342(define_insn "extendpsisi2" 343 [(set (match_operand:SI 0 "mr_operand" "=R03Sd*Rmm") 344 (sign_extend:SI (match_operand:PSI 1 "mr_operand" "0")))] 345 "" 346 "; expand psi %1 to si %0" 347 [(set_attr "flags" "n")] 348 ) 349 350(define_insn "zero_extendpsisi2" 351 [(set (match_operand:SI 0 "mr_operand" "=R03Sd*Rmm") 352 (zero_extend:SI (match_operand:PSI 1 "mr_operand" "0")))] 353 "" 354 "; expand psi %1 to si %0" 355 [(set_attr "flags" "n")] 356 ) 357 358(define_insn "zero_extendhipsi2" 359 [(set (match_operand:PSI 0 "register_operand" "=Raa") 360 (truncate:PSI (zero_extend:SI (match_operand:HI 1 "register_operand" "R03"))))] 361 "" 362 "mov.w\t%1,%0" 363 [(set_attr "flags" "sz")] 364 ) 365 366(define_insn "zero_extendhisi2" 367 [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=RsiSd") 368 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))] 369 "" 370 "mov.w\t#0,%H0" 371 [(set_attr "flags" "x")] 372 ) 373 374(define_insn "zero_extendqihi2" 375 [(set (match_operand:HI 0 "m32c_nonimmediate_operand" "=Rhl,RhiSd*Rmm") 376 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,0")))] 377 "" 378 "@ 379 mov.b\t#0,%H0 380 and.w\t#255,%0" 381 [(set_attr "flags" "x,x")] 382 ) 383 384(define_insn "truncsipsi2_16" 385 [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "=RsiRadSd*Rmm,Raa,Rcr,RsiSd*Rmm") 386 (truncate:PSI (match_operand:SI 1 "nonimmediate_operand" "0,RsiSd*Rmm,RsiSd*Rmm,Rcr")))] 387 "TARGET_A16" 388 "@ 389 ; no-op trunc si %1 to psi %0 390 # 391 ldc\t%1,%0 392 stc\t%1,%0" 393 [(set_attr "flags" "n,*,n,n")] 394 ) 395 396(define_insn "trunchiqi2" 397 [(set (match_operand:QI 0 "m32c_nonimmediate_operand" "=RqiRmmSd") 398 (truncate:QI (match_operand:HI 1 "mra_qi_operand" "0")))] 399 "" 400 "; no-op trunc hi %1 to qi %0" 401 [(set_attr "flags" "n")] 402 ) 403 404(define_insn "truncsipsi2_24" 405 [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "=RsiSd*Rmm,Raa,!Rcl,RsiSd*Rmm") 406 (truncate:PSI (match_operand:SI 1 "m32c_nonimmediate_operand" "0,RsiSd*Rmm,RsiSd*Rmm,!Rcl")))] 407 "TARGET_A24" 408 "@ 409 ; no-op trunc si %1 to psi %0 410 mov.l\t%1,%0 411 ldc\t%1,%0 412 stc\t%1,%0" 413 [(set_attr "flags" "n,sz,n,n")] 414 ) 415 416(define_expand "truncsipsi2" 417 [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "=RsiRadSd*Rmm,Raa,Rcr,RsiSd*Rmm") 418 (truncate:PSI (match_operand:SI 1 "m32c_nonimmediate_operand" "0,RsiSd*Rmm,RsiSd*Rmm,Rcr")))] 419 "" 420 "" 421 ) 422 423(define_expand "reload_inqi" 424 [(set (match_operand:QI 2 "" "=&Rqi") 425 (match_operand:QI 1 "" "")) 426 (set (match_operand:QI 0 "" "") 427 (match_dup 2)) 428 ] 429 "" 430 "") 431 432(define_expand "reload_outqi" 433 [(set (match_operand:QI 2 "" "=&Rqi") 434 (match_operand:QI 1 "" "")) 435 (set (match_operand:QI 0 "" "") 436 (match_dup 2)) 437 ] 438 "" 439 "") 440 441(define_expand "reload_inhi" 442 [(set (match_operand:HI 2 "" "=&Rhi") 443 (match_operand:HI 1 "" "")) 444 (set (match_operand:HI 0 "" "") 445 (match_dup 2)) 446 ] 447 "" 448 "") 449 450(define_expand "reload_outhi" 451 [(set (match_operand:HI 2 "" "=&Rhi") 452 (match_operand:HI 1 "" "")) 453 (set (match_operand:HI 0 "" "") 454 (match_dup 2)) 455 ] 456 "" 457 "") 458