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