1;;- Machine description file for Motorola 68HC11 and 68HC12. 2;;- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 3;;- Contributed by Stephane Carrez (stcarrez@nerim.fr) 4 5;; This file is part of GNU CC. 6 7;; GNU CC is free software; you can redistribute it and/or modify 8;; it under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 2, or (at your option) 10;; any later version. 11 12;; GNU CC is distributed in the hope that it will be useful, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public License for more details. 16 17;; You should have received a copy of the GNU General Public License 18;; along with GNU CC; see the file COPYING. If not, write to 19;; the Free Software Foundation, 59 Temple Place - Suite 330, 20;; Boston, MA 02111-1307, USA. 21 22;; Note: 23;; A first 68HC11 port was made by Otto Lind (otto@coactive.com) 24;; on gcc 2.6.3. I have used it as a starting point for this port. 25;; However, this new port is a complete re-write. Its internal 26;; design is completely different. The generated code is not 27;; compatible with the gcc 2.6.3 port. 28;; 29;; The gcc 2.6.3 port is available at: 30;; 31;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz 32;; 33 34;;- Instruction patterns. When multiple patterns apply, 35;;- the first one in the file is chosen. 36;;- 37;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 38;;- 39;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code 40;;- updates for most instructions. 41 42;; 43;; The following constraints are used: 44;; 45;; Single pair registers: 46;; a register 'a' 8-bit 47;; b register 'b' 8-bit 48;; d register 'd' 16-bit 49;; t pseudo soft register 'TMP' 16-bit 50;; v register 'd' for 68hc11, 16-bit 51;; NO_REG for 68hc12 52;; (used for scratch register) 53;; w register 'sp' 16-bit 54;; x register 'x' 16-bit 55;; y register 'y' 16-bit 56;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12) 57;; D register 'd+x' 32-bit 58;; 59;; Group of registers: 60;; q register 'a' or 'b' or 'd' 8-bit 61;; u pseudo soft register 16-bit 62;; A register 'x', 'y', 'z' 16-bit 63;; B register 'x', 'y' 16-bit 64;; h register 'd', 'x', 'y', 'z' 16-bit 65;; 66;; Other constraints: 67;; 68;; Q an operand which is in memory but whose address is constant 69;; (ie, a (MEM (SYMBOL_REF x))). This constraint is used by 70;; bset/bclr instructions together with linker relaxation. The 71;; operand can be translated to a page0 addressing mode if the 72;; symbol address is in page0 (0..255). 73;; 74;; R an operand which is in memory and whose address is expressed 75;; with 68HC11/68HC12 indexed addressing mode. In general this 76;; is any valid (MEM) except a (MEM (SYMBOL_REF x)). 77;; 78;; U an operand which is in memory and if it uses the 68HC12 indexed 79;; addressing mode, the offset is in the range -16..+15. This is 80;; used by 68HC12 movb/movw instructions since they do not accept 81;; the full 16-bit offset range (as other insn do). 82;; 83;; 84;; Immediate integer operand constraints: 85;; `L' is for range -65536 to 65536 86;; `M' is for values whose 16-bit low part is 0 87;; 'N' is for +1 or -1. 88;; 'O' is for 16 (for rotate using swap). 89;; 'P' is for range -8 to 2 (used by addhi_sp) 90;; 91;; In many cases, it's not possible to use the 'g' or 'r' constraints. 92;; 93;; Operands modifiers: 94;; 95;; %b Get the low part of the operand (to obtain a QImode) 96;; This modified must always be used for QImode operations 97;; because a correction must be applied when the operand 98;; is a soft register (ex: *ZD1). Otherwise, we generate 99;; *ZD1 and this is the high part of the register. For other 100;; kinds of operands, if the operand is already QImode, no 101;; additional correction is made. 102;; %h Get the high part of the operand (to obtain a QImode) 103;; %t Represents the temporary/scratch register *_.tmp 104;; The scratch register is used in some cases when GCC puts 105;; some values in bad registers. 106;; 107;; 32/64-bit Patterns: 108;; The 68HC11 does not support 32/64-bit operations. Most of the 109;; 32/64-bit patterns are defined to split the instruction in 110;; 16-bits patterns. Providing split patterns generates better code 111;; than letting GCC implement the 32/64-bit operation itself. 112;; 113;; 114;; Notes: 115;; 116;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint 117;; otherwise some insn are not satisfied. 118;; 119;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must 120;; be valid only when z_replacement_completed == 2 because once these 121;; swap instructions are generated, a flow/cse pass fails to handle 122;; them correctly (it would treat the X, Y or D register as dead sometimes). 123;; 124;; o Some split pattern generate instructions that operate on 'a' or 'b' 125;; register directly (high part and low part of D respectively). 126;; Such split pattern must also be valid when z_replacement_completed == 2 127;; because flow/cse is not aware that D is composed of {a, b}. 128;; 129;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access 130;; the high part of a soft register must be expanded after z_replacement 131;; pass. 132;; 133;;--------------------------------------------------------------------------- 134;; Constants 135 136(define_constants [ 137 ;; Register numbers 138 (X_REGNUM 0) ; Index X register 139 (D_REGNUM 1) ; Data register 140 (Y_REGNUM 2) ; Index Y register 141 (SP_REGNUM 3) ; Stack pointer 142 (PC_REGNUM 4) ; Program counter 143 (A_REGNUM 5) ; A (high part of D) 144 (B_REGNUM 6) ; B (low part of D) 145 (CC_REGNUM 7) ; Condition code register 146 (SOFT_Z_REGNUM 11) ; Z soft register 147]) 148 149;;-------------------------------------------------------------------- 150;;- Test 151;;-------------------------------------------------------------------- 152;; 153;; The test and compare insn must not accept a memory operand with 154;; an auto-inc mode. If we do this, the reload can emit move insns 155;; after the test or compare. Such move will set the flags and therefore 156;; break the comparison. This can happen if the auto-inc register 157;; does not happen to be a hard register (ie, reloading occurs). 158;; An offsetable memory operand should be ok. The 'tst_operand' and 159;; 'cmp_operand' predicates take care of this rule. 160;; 161(define_expand "tstsi" 162 [(set (cc0) 163 (match_operand:SI 0 "tst_operand" ""))] 164 "" 165 " 166{ 167 m68hc11_compare_op0 = operands[0]; 168 m68hc11_compare_op1 = const0_rtx; 169 DONE; 170}") 171 172(define_expand "tsthi" 173 [(set (cc0) 174 (match_operand:HI 0 "tst_operand" ""))] 175 "" 176 " 177{ 178 m68hc11_compare_op0 = operands[0]; 179 m68hc11_compare_op1 = const0_rtx; 180 DONE; 181}") 182 183(define_insn "tsthi_1" 184 [(set (cc0) 185 (match_operand:HI 0 "tst_operand" "dx,*y"))] 186 "" 187 "* 188{ 189 if (D_REG_P (operands[0]) && !TARGET_M6812) 190 return \"std\\t%t0\"; 191 else 192 return \"cp%0\\t#0\"; 193}") 194 195(define_expand "tstqi" 196 [(set (cc0) 197 (match_operand:QI 0 "tst_operand" ""))] 198 "" 199 " 200{ 201 m68hc11_compare_op0 = operands[0]; 202 m68hc11_compare_op1 = const0_rtx; 203 DONE; 204}") 205 206;; 207;; Split pattern for (tst:QI) on an address register. 208;; 209(define_split 210 [(set (cc0) 211 (match_operand:QI 0 "hard_addr_reg_operand" ""))] 212 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" 213 [(parallel [(set (reg:HI D_REGNUM) (match_dup 1)) 214 (set (match_dup 1) (reg:HI D_REGNUM))]) 215 (set (cc0) (reg:QI D_REGNUM)) 216 (parallel [(set (reg:HI D_REGNUM) (match_dup 1)) 217 (set (match_dup 1) (reg:HI D_REGNUM))])] 218 "operands[1] = gen_rtx (REG, HImode, REGNO (operands[0]));") 219 220(define_insn "tstqi_1" 221 [(set (cc0) 222 (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))] 223 "" 224 "* 225{ 226 if (A_REG_P (operands[0])) 227 return \"#\"; 228 229 else if (D_REG_P (operands[0])) 230 return \"tstb\"; 231 232 else if (dead_register_here (insn, d_reg)) 233 return \"ldab\\t%b0\"; 234 235 else 236 return \"tst\\t%b0\"; 237}") 238 239;; 240;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated 241;; during the Z register replacement. They are used when an operand 242;; uses the Z register as an index register (ie, (MEM:QI (REG:HI Z))). 243;; In that case, we have to preserve the values of the replacement 244;; register (as well as the CC0 since the insns are compare insns). 245;; To do this, the replacement register is pushed on the stack and 246;; restored after the real compare. A pattern+split is defined to 247;; avoid problems with the flow+cse register pass which are made 248;; after Z register replacement. 249;; 250(define_insn "tstqi_z_used" 251 [(set (cc0) 252 (match_operand:QI 0 "tst_operand" "m")) 253 (use (match_operand:HI 1 "hard_reg_operand" "dxy")) 254 (use (reg:HI 11))] 255 "" 256 "#") 257 258(define_split /* "tstqi_z_used" */ 259 [(set (cc0) 260 (match_operand:QI 0 "tst_operand" "")) 261 (use (match_operand:HI 1 "hard_reg_operand" "")) 262 (use (reg:HI SOFT_Z_REGNUM))] 263 "z_replacement_completed == 2" 264 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1)) 265 (set (match_dup 1) (match_dup 2)) 266 (set (cc0) (match_dup 0)) 267 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] 268 "operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") 269 270 271;;-------------------------------------------------------------------- 272;;- Compare 273;;-------------------------------------------------------------------- 274 275(define_expand "cmpsi" 276 [(set (cc0) 277 (compare (match_operand:SI 0 "tst_operand" "") 278 (match_operand:SI 1 "cmp_operand" "")))] 279 "" 280 " 281{ 282 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 283 operands[0] = force_reg (SImode, operands[0]); 284 285 m68hc11_compare_op0 = operands[0]; 286 m68hc11_compare_op1 = operands[1]; 287 DONE; 288}") 289 290;; 291;; Comparison of a hard register with another one is provided because 292;; it helps GCC to avoid to spill a pseudo hard register. 293;; We use a temporary in page 0, this is equivalent to a pseudo hard reg. 294;; (except that we loose the information that the value is saved in it). 295;; 296;; The split pattern transforms the comparison into a save of one hard 297;; register and a comparison with the temporary. 298;; 299(define_split 300 [(set (cc0) 301 (compare (match_operand:HI 0 "hard_reg_operand" "") 302 (match_operand:HI 1 "hard_reg_operand" "")))] 303 "reload_completed" 304 [(set (match_dup 2) (match_dup 1)) 305 (set (cc0) 306 (compare (match_dup 0) (match_dup 2)))] 307 "operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);") 308 309(define_expand "cmphi" 310 [(set (cc0) 311 (compare (match_operand:HI 0 "tst_operand" "") 312 (match_operand:HI 1 "cmp_operand" "")))] 313 "" 314 " 315{ 316 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 317 operands[0] = force_reg (HImode, operands[0]); 318 319 m68hc11_compare_op0 = operands[0]; 320 m68hc11_compare_op1 = operands[1]; 321 DONE; 322}") 323 324(define_insn "cmphi_1_hc12" 325 [(set (cc0) 326 (compare (match_operand:HI 0 "tst_operand" 327 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy") 328 (match_operand:HI 1 "cmp_operand" 329 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))] 330 "TARGET_M6812" 331 "* 332{ 333 if (H_REG_P (operands[1]) && !H_REG_P (operands[0])) 334 { 335 cc_status.flags |= CC_REVERSED; 336 return \"cp%1\\t%0\"; 337 } 338 else if (H_REG_P (operands[1])) 339 return \"#\"; 340 else 341 return \"cp%0\\t%1\"; 342}") 343 344(define_insn "cmphi_1_hc11" 345 [(set (cc0) 346 (compare (match_operand:HI 0 "tst_operand" 347 "dx,y,xyd,?xy,d,m,!u,dxy,dxy") 348 (match_operand:HI 1 "cmp_operand" 349 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))] 350 "TARGET_M6811" 351 "* 352{ 353 if (H_REG_P (operands[1]) && !H_REG_P (operands[0])) 354 { 355 cc_status.flags |= CC_REVERSED; 356 return \"cp%1\\t%0\"; 357 } 358 else if (H_REG_P (operands[1])) 359 return \"#\"; 360 else 361 return \"cp%0\\t%1\"; 362}") 363 364(define_insn "cmphi_z_used" 365 [(set (cc0) 366 (compare (match_operand:HI 0 "tst_operand" "dxy,m") 367 (match_operand:HI 1 "cmp_operand" "m,dxy"))) 368 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy")) 369 (use (reg:HI SOFT_Z_REGNUM))] 370 "" 371 "#") 372 373(define_split /* "cmphi_z_used" */ 374 [(set (cc0) 375 (compare (match_operand:HI 0 "tst_operand" "") 376 (match_operand:HI 1 "cmp_operand" ""))) 377 (use (match_operand:HI 2 "hard_reg_operand" "")) 378 (use (reg:HI SOFT_Z_REGNUM))] 379 "z_replacement_completed == 2" 380 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) 381 (set (match_dup 2) (match_dup 3)) 382 (set (cc0) (compare (match_dup 0) (match_dup 1))) 383 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] 384 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") 385 386;; 387;; 8-bit comparison with address register. 388;; There is no such comparison instruction, we have to temporarily switch 389;; the address register and the D register and do the comparison with D. 390;; The xgdx and xgdy instructions preserve the flags. 391;; 392(define_split 393 [(set (cc0) 394 (compare (match_operand:QI 0 "hard_addr_reg_operand" "") 395 (match_operand:QI 1 "cmp_operand" "")))] 396 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" 397 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3)) 398 (set (match_dup 3) (reg:HI D_REGNUM))]) 399 (set (cc0) 400 (compare (reg:QI D_REGNUM) (match_dup 1))) 401 (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) 402 (set (match_dup 3) (reg:HI D_REGNUM))])] 403 "operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));") 404 405(define_split 406 [(set (cc0) 407 (compare (match_operand:QI 0 "hard_reg_operand" "") 408 (match_operand:QI 1 "hard_reg_operand" "")))] 409 "reload_completed" 410 [(set (match_dup 3) (match_dup 4)) 411 (set (cc0) 412 (compare (match_dup 0) (match_dup 2)))] 413 "operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 414 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 415 operands[4] = gen_rtx (REG, HImode, REGNO (operands[1]));") 416 417(define_expand "cmpqi" 418 [(set (cc0) 419 (compare (match_operand:QI 0 "tst_operand" "") 420 (match_operand:QI 1 "cmp_operand" "")))] 421 "" 422 " 423{ 424 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 425 operands[0] = force_reg (QImode, operands[0]); 426 427 m68hc11_compare_op0 = operands[0]; 428 m68hc11_compare_op1 = operands[1]; 429 DONE; 430}") 431 432(define_insn "bitcmpqi" 433 [(set (cc0) 434 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u") 435 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))] 436 "" 437 "@ 438 bitb\\t%b1 439 # 440 bitb\\t%b1 441 bitb\\t%b0 442 bitb\\t%b0") 443 444(define_split /* "bitcmpqi" */ 445 [(set (cc0) 446 (and:QI (match_operand:QI 0 "tst_operand" "") 447 (match_operand:QI 1 "hard_addr_reg_operand" "")))] 448 "z_replacement_completed == 2" 449 [(set (match_dup 3) (match_dup 2)) 450 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))] 451 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1])); 452 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 453 operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);") 454 455(define_insn "bitcmpqi_z_used" 456 [(set (cc0) 457 (and:QI (match_operand:QI 0 "tst_operand" "d,m") 458 (match_operand:QI 1 "cmp_operand" "m,d"))) 459 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy")) 460 (use (reg:HI SOFT_Z_REGNUM))] 461 "" 462 "#") 463 464(define_split /* "bitcmpqi_z_used" */ 465 [(set (cc0) 466 (and:QI (match_operand:QI 0 "tst_operand" "") 467 (match_operand:QI 1 "cmp_operand" ""))) 468 (use (match_operand:HI 2 "hard_reg_operand" "")) 469 (use (reg:HI SOFT_Z_REGNUM))] 470 "z_replacement_completed == 2" 471 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) 472 (set (match_dup 2) (match_dup 3)) 473 (set (cc0) (and:QI (match_dup 0) (match_dup 1))) 474 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] 475 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") 476 477(define_insn "bitcmphi" 478 [(set (cc0) 479 (and:HI (match_operand:HI 0 "tst_operand" "d") 480 (match_operand:HI 1 "const_int_operand" "i")))] 481 "(INTVAL (operands[1]) & 0x0ff) == 0 482 || (INTVAL (operands[1]) & 0x0ff00) == 0" 483 "* 484{ 485 if ((INTVAL (operands[1]) & 0x0ff) == 0) 486 return \"bita\\t%h1\"; 487 else 488 return \"bitb\\t%1\"; 489}") 490 491(define_insn "bitcmpqi_12" 492 [(set (cc0) 493 (zero_extract (match_operand:HI 0 "tst_operand" "d") 494 (match_operand:HI 1 "const_int_operand" "i") 495 (match_operand:HI 2 "const_int_operand" "i")))] 496 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8 497 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16) 498 && (unsigned) INTVAL (operands[2]) >= 8)" 499 "* 500{ 501 rtx ops[1]; 502 int mask; 503 int startpos = INTVAL (operands[2]); 504 int bitsize = INTVAL (operands[1]); 505 506 if (startpos >= 8) 507 { 508 startpos -= 8; 509 mask = (1 << (startpos + bitsize)) - 1; 510 mask &= ~((1 << startpos) - 1); 511 512 ops[0] = GEN_INT (mask); 513 output_asm_insn (\"bita\\t%0\", ops); 514 } 515 else 516 { 517 mask = (1 << (startpos + bitsize)) - 1; 518 mask &= ~((1 << startpos) - 1); 519 520 ops[0] = GEN_INT (mask); 521 output_asm_insn (\"bitb\\t%0\", ops); 522 } 523 return \"\"; 524}") 525 526(define_insn "cmpqi_1" 527 [(set (cc0) 528 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B") 529 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))] 530 "" 531 "* 532{ 533 if (A_REG_P (operands[0]) || A_REG_P (operands[1])) 534 { 535 return \"#\"; 536 } 537 else if (D_REG_P (operands[0])) 538 { 539 return \"cmpb\\t%b1\"; 540 } 541 cc_status.flags |= CC_REVERSED; 542 return \"cmpb\\t%b0\"; 543}") 544 545(define_insn "cmpqi_z_used" 546 [(set (cc0) 547 (compare (match_operand:QI 0 "tst_operand" "dxy,m") 548 (match_operand:QI 1 "cmp_operand" "m,dxy"))) 549 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy")) 550 (use (reg:HI SOFT_Z_REGNUM))] 551 "" 552 "#") 553 554(define_split /* cmpqi_z_used */ 555 [(set (cc0) 556 (compare (match_operand:QI 0 "tst_operand" "") 557 (match_operand:QI 1 "cmp_operand" ""))) 558 (use (match_operand:HI 2 "hard_reg_operand" "")) 559 (use (reg:HI SOFT_Z_REGNUM))] 560 "z_replacement_completed == 2" 561 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) 562 (set (match_dup 2) (match_dup 3)) 563 (set (cc0) (compare (match_dup 0) (match_dup 1))) 564 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] 565 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") 566 567;;-------------------------------------------------------------------- 568;;- Move strict_low_part 569;;-------------------------------------------------------------------- 570;; 571;; The (strict_low_part ...) patterns are replaced by normal (set) patterns. 572;; The replacement must be made at the very end because we loose the 573;; (strict_low_part ...) information. This is correct for our machine 574;; description but not for GCC optimization passes. 575;; 576(define_insn "movstrictsi" 577 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D")) 578 (match_operand:SI 1 "general_operand" "D,Dim,uD"))] 579 "" 580 "#") 581 582(define_split 583 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "")) 584 (match_operand:SI 1 "general_operand" ""))] 585 "z_replacement_completed == 2" 586 [(set (match_dup 0) (match_dup 1))] 587 "") 588 589(define_insn "movstricthi" 590 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA")) 591 (match_operand:HI 1 "general_operand" "dA,dAim,u"))] 592 "" 593 "#") 594 595(define_split 596 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "")) 597 (match_operand:HI 1 "general_operand" ""))] 598 "z_replacement_completed == 2" 599 [(set (match_dup 0) (match_dup 1))] 600 "") 601 602(define_insn "movstrictqi" 603 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA")) 604 (match_operand:QI 1 "general_operand" "d,imudA"))] 605 "" 606 "#") 607 608(define_split 609 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "")) 610 (match_operand:QI 1 "general_operand" ""))] 611 "z_replacement_completed == 2" 612 [(set (match_dup 0) (match_dup 1))] 613 "") 614 615;;-------------------------------------------------------------------- 616;;- 64-bit Move Operations. 617;; The movdi and movdf patterns are identical except for the mode. 618;; They are also very similar to those for movsi and movsf. 619;; 620;; For 68HC11, we need a scratch register (either D, X, Y) 621;; because there is no memory->memory moves. It must be defined with 622;; earlyclobber (&) so that it does not appear in the source or destination 623;; address. Providing patterns for movdi/movdf allows GCC to generate 624;; better code. [Until now, the scratch register is limited to D because 625;; otherwise we can run out of registers in the A_REGS class for reload]. 626;; 627;; For 68HC12, the scratch register is not necessary. To use the same 628;; pattern and same split, we use the 'v' constraint. This tells the 629;; reload to use the _.tmp register (which is not used at all). 630;; The insn will be split in one or several memory moves (movw). 631;; [SCz: this does not work ?? So, I switched temporary to 'd' reg] 632;;-------------------------------------------------------------------- 633(define_expand "movdi" 634 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") 635 (match_operand:DI 1 "general_operand" "")) 636 (clobber (match_scratch:HI 2 ""))])] 637 "" 638 " 639 /* For push/pop, emit a REG_INC note to make sure the reload 640 inheritance and reload CSE pass notice the change of the stack 641 pointer. */ 642 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1])) 643 { 644 rtx insn; 645 646 insn = emit_insn (gen_movdi_internal (operands[0], operands[1])); 647 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, 648 stack_pointer_rtx, 649 REG_NOTES (insn)); 650 DONE; 651 } 652") 653 654(define_insn "movdi_internal" 655 [(set (match_operand:DI 0 "nonimmediate_operand" "=ou,U,!u,U,m,m,!u") 656 (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu")) 657 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))] 658 "" 659 "#") 660 661(define_split 662 [(set (match_operand:DI 0 "nonimmediate_operand" "") 663 (match_operand:DI 1 "general_operand" "")) 664 (clobber (match_scratch:HI 2 ""))] 665 "reload_completed" 666 [(const_int 0)] 667 "m68hc11_split_move (operands[0], operands[1], operands[2]); 668 DONE;") 669 670(define_expand "movdf" 671 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") 672 (match_operand:DF 1 "general_operand" "")) 673 (clobber (match_scratch:HI 2 ""))])] 674 "" 675 "/* For push/pop, emit a REG_INC note to make sure the reload 676 inheritance and reload CSE pass notice the change of the stack 677 pointer. */ 678 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1])) 679 { 680 rtx insn; 681 682 insn = emit_insn (gen_movdf_internal (operands[0], operands[1])); 683 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, 684 stack_pointer_rtx, 685 REG_NOTES (insn)); 686 DONE; 687 } 688") 689 690(define_insn "movdf_internal" 691 [(set (match_operand:DF 0 "nonimmediate_operand" "=ou,U,!u,U,m,m,!u") 692 (match_operand:DF 1 "general_operand" "G,iU,iU,!u,mi,!u,!mu")) 693 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))] 694 "" 695 "#") 696 697(define_split 698 [(set (match_operand:DF 0 "nonimmediate_operand" "") 699 (match_operand:DF 1 "general_operand" "")) 700 (clobber (match_scratch:HI 2 ""))] 701 "reload_completed" 702 [(const_int 0)] 703 "m68hc11_split_move (operands[0], operands[1], operands[2]); 704 DONE;") 705 706;;-------------------------------------------------------------------- 707;;- 32-bit Move Operations. 708;; The movsi and movsf patterns are identical except for the mode. 709;; When we move to/from a hard register (d+x), we don't need a scratch. 710;; Otherwise, a scratch register is used as intermediate register for 711;; the move. The '&' constraint is necessary to make sure the reload 712;; pass does not give us a register that dies in the insn and is used 713;; for input/output operands. 714;;-------------------------------------------------------------------- 715(define_expand "movsi" 716 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") 717 (match_operand:SI 1 "general_operand" "")) 718 (clobber (match_scratch:HI 2 ""))])] 719 "" 720 "/* For push/pop, emit a REG_INC note to make sure the reload 721 inheritance and reload CSE pass notice the change of the stack 722 pointer. */ 723 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1])) 724 { 725 rtx insn; 726 727 insn = emit_insn (gen_movsi_internal (operands[0], operands[1])); 728 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, 729 stack_pointer_rtx, 730 REG_NOTES (insn)); 731 DONE; 732 } 733") 734 735(define_insn "movsi_internal" 736 [(set (match_operand:SI 0 "nonimmediate_operand" "=ou,mu,?D,m,?D,?u,?u,!u,D") 737 (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D")) 738 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))] 739 "" 740 "#") 741 742(define_split 743 [(set (match_operand:SI 0 "nonimmediate_operand" "") 744 (match_operand:SI 1 "general_operand" "")) 745 (clobber (match_scratch:HI 2 ""))] 746 "reload_completed" 747 [(const_int 0)] 748 "m68hc11_split_move (operands[0], operands[1], operands[2]); 749 DONE;") 750 751(define_expand "movsf" 752 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") 753 (match_operand:SF 1 "general_operand" "")) 754 (clobber (match_scratch:HI 2 ""))])] 755 "" 756 "/* For push/pop, emit a REG_INC note to make sure the reload 757 inheritance and reload CSE pass notice the change of the stack 758 pointer. */ 759 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1])) 760 { 761 rtx insn; 762 763 insn = emit_insn (gen_movsf_internal (operands[0], operands[1])); 764 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, 765 stack_pointer_rtx, 766 REG_NOTES (insn)); 767 DONE; 768 } 769") 770 771(define_insn "movsf_internal" 772 [(set (match_operand:SF 0 "nonimmediate_operand" "=o!u,m,D,m,D,!u,!u,!u,D") 773 (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D")) 774 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))] 775 "" 776 "#") 777 778(define_split 779 [(set (match_operand:SF 0 "nonimmediate_operand" "") 780 (match_operand:SF 1 "general_operand" "")) 781 (clobber (match_scratch:HI 2 ""))] 782 "reload_completed" 783 [(const_int 0)] 784 "m68hc11_split_move (operands[0], operands[1], operands[2]); 785 DONE;") 786 787 788;;-------------------------------------------------------------------- 789;;- 16-bit Move Operations. 790;; We don't need a scratch register. 791;;-------------------------------------------------------------------- 792 793(define_insn "*movhi2_push" 794 [(set (match_operand:HI 0 "push_operand" "=<,<,<") 795 (match_operand:HI 1 "general_operand" "xy,?d,!z"))] 796 "TARGET_M6811 && !TARGET_M6812" 797 "* 798{ 799 cc_status = cc_prev_status; 800 if (D_REG_P (operands[1])) 801 { 802 output_asm_insn (\"pshb\", operands); 803 return \"psha\"; 804 } 805 else if (X_REG_P (operands[1])) 806 { 807 return \"pshx\"; 808 } 809 else if (Y_REG_P (operands[1])) 810 { 811 return \"pshy\"; 812 } 813 fatal_insn (\"Invalid register in the instruction\", insn); 814}") 815 816(define_insn "*movhi2_pop" 817 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d") 818 (match_operand:HI 1 "pop_operand" ">,>"))] 819 "TARGET_M6811" 820 "* 821{ 822 cc_status = cc_prev_status; 823 if (D_REG_P (operands[0])) 824 { 825 output_asm_insn (\"pula\", operands); 826 return \"pulb\"; 827 } 828 else if (X_REG_P (operands[0])) 829 { 830 return \"pulx\"; 831 } 832 else if (Y_REG_P (operands[0])) 833 { 834 return \"puly\"; 835 } 836 fatal_insn (\"Invalid register in the instruction\", insn); 837}") 838 839(define_expand "movhi" 840 [(set (match_operand:HI 0 "nonimmediate_operand" "") 841 (match_operand:HI 1 "general_operand" ""))] 842 "" 843 " 844{ 845 if (reload_in_progress) 846 { 847 if (m68hc11_reload_operands (operands)) 848 { 849 DONE; 850 } 851 } 852 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0) 853 { 854 if (GET_CODE (operands[0]) == MEM && 855 (GET_CODE (operands[1]) == MEM 856 || GET_CODE (operands[1]) == CONST_INT)) 857 { 858 operands[1] = force_reg (HImode, operands[1]); 859 } 860 else if (IS_STACK_PUSH (operands[0]) 861 && GET_CODE (operands[1]) != REG) 862 { 863 operands[1] = force_reg (HImode, operands[1]); 864 } 865 } 866 /* For push/pop, emit a REG_INC note to make sure the reload 867 inheritance and reload CSE pass notice the change of the stack 868 pointer. */ 869 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1])) 870 { 871 rtx insn; 872 873 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); 874 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, 875 stack_pointer_rtx, 876 REG_NOTES (insn)); 877 DONE; 878 } 879}") 880 881(define_insn "movhi_const0" 882 [(set (match_operand:HI 0 "non_push_operand" "=d,A,um") 883 (const_int 0))] 884 "" 885 "@ 886 clra\\n\\tclrb 887 ld%0\\t#0 888 clr\\t%b0\\n\\tclr\\t%h0") 889 890(define_insn "*movhi_68hc12" 891 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,U,U,m,!u") 892 (match_operand:HI 1 "general_operand" "U,rim,dAwi,!u,dAw,riU"))] 893 "TARGET_M6812" 894 "* 895{ 896 m68hc11_gen_movhi (insn, operands); 897 return \"\"; 898}") 899 900(define_insn "*movhi_m68hc11" 901 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u") 902 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))] 903 "TARGET_M6811" 904 "* 905{ 906 m68hc11_gen_movhi (insn, operands); 907 return \"\"; 908}") 909 910;;-------------------------------------------------------------------- 911;;- 8-bit Move Operations. 912;; We don't need a scratch register. 913;;-------------------------------------------------------------------- 914;; 915;; The *a alternative also clears the high part of the register. 916;; This should be ok since this is not the (strict_low_part) set. 917;; 918(define_insn "movqi_const0" 919 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q") 920 (const_int 0))] 921 "" 922 "@ 923 clrb 924 clr\\t%b0 925 clr\\t%b0 926 ld%0\\t#0 927 clr%0") 928 929;; 930;; 8-bit operations on address registers. 931;; 932;; Switch temporary to the D register and load the value in B. 933;; This is possible as long as the address register does not 934;; appear in the source operand. 935;; 936(define_split 937 [(set (match_operand:QI 0 "hard_addr_reg_operand" "") 938 (match_operand:QI 1 "general_operand" ""))] 939 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode 940 && !reg_mentioned_p (operands[0], operands[1]) 941 && !D_REG_P (operands[1])" 942 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2)) 943 (set (match_dup 2) (reg:HI D_REGNUM))]) 944 (set (reg:QI D_REGNUM) (match_dup 1)) 945 (parallel [(set (reg:HI D_REGNUM) (match_dup 2)) 946 (set (match_dup 2) (reg:HI D_REGNUM))])] 947 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));") 948 949;; 950;; 8-bit operations on address registers. 951;; 952(define_split 953 [(set (match_operand:QI 0 "nonimmediate_operand" "") 954 (match_operand:QI 1 "hard_addr_reg_operand" ""))] 955 "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode 956 && !reg_mentioned_p (operands[1], operands[0]) 957 && !D_REG_P (operands[0])" 958 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2)) 959 (set (match_dup 2) (reg:HI D_REGNUM))]) 960 (set (match_dup 0) (reg:QI D_REGNUM)) 961 (parallel [(set (reg:HI D_REGNUM) (match_dup 2)) 962 (set (match_dup 2) (reg:HI D_REGNUM))])] 963 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));") 964 965(define_insn "*movqi2_push" 966 [(set (match_operand:QI 0 "push_operand" "=<,<") 967 (match_operand:QI 1 "general_operand" "d,!*A"))] 968 "" 969 "* 970{ 971 if (A_REG_P (operands[1])) 972 return \"#\"; 973 974 cc_status = cc_prev_status; 975 return \"pshb\"; 976}") 977 978 979(define_expand "movqi" 980 [(set (match_operand:QI 0 "nonimmediate_operand" "") 981 (match_operand:QI 1 "general_operand" ""))] 982 "" 983 " 984{ 985 if (reload_in_progress) 986 { 987 if (m68hc11_reload_operands (operands)) 988 { 989 DONE; 990 } 991 } 992 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0) 993 { 994 if (GET_CODE (operands[0]) == MEM 995 && (GET_CODE (operands[1]) == MEM 996 || GET_CODE (operands[1]) == CONST_INT)) 997 { 998 operands[1] = force_reg (QImode, operands[1]); 999 } 1000 else if (IS_STACK_PUSH (operands[0]) 1001 && GET_CODE (operands[1]) != REG) 1002 { 1003 operands[1] = force_reg (QImode, operands[1]); 1004 } 1005 } 1006 /* For push/pop, emit a REG_INC note to make sure the reload 1007 inheritance and reload CSE pass notice the change of the stack 1008 pointer. */ 1009 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1])) 1010 { 1011 rtx insn; 1012 1013 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); 1014 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, 1015 stack_pointer_rtx, 1016 REG_NOTES (insn)); 1017 DONE; 1018 } 1019}") 1020 1021(define_insn "*movqi_68hc12" 1022 [(set (match_operand:QI 0 "nonimmediate_operand" 1023 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m") 1024 (match_operand:QI 1 "general_operand" 1025 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))] 1026 "TARGET_M6812" 1027 "* 1028{ 1029 m68hc11_gen_movqi (insn, operands); 1030 return \"\"; 1031}") 1032 1033(define_insn "*movqi_m68hc11" 1034 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u") 1035 (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))] 1036 "TARGET_M6811" 1037 "* 1038{ 1039 m68hc11_gen_movqi (insn, operands); 1040 return \"\"; 1041}") 1042 1043;;-------------------------------------------------------------------- 1044;;- Swap registers 1045;;-------------------------------------------------------------------- 1046;; Swapping registers is used for split patterns. 1047(define_insn "swap_areg" 1048 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A") 1049 (match_operand:HI 1 "hard_reg_operand" "=A,d")) 1050 (set (match_dup 1) (match_dup 0))] 1051 "" 1052 "* 1053{ 1054 m68hc11_output_swap (insn, operands); 1055 return \"\"; 1056}") 1057 1058;;-------------------------------------------------------------------- 1059;;- Truncation insns. 1060;;-------------------------------------------------------------------- 1061;; 1062;; Truncation are not necessary because GCC knows how to truncate, 1063;; specially when values lie in consecutive registers. 1064;; 1065 1066(define_expand "floatunssisf2" 1067 [(set (match_operand:SF 0 "nonimmediate_operand" "") 1068 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))] 1069 "" 1070 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT, 1071 SFmode, SImode, 2, operands); 1072 DONE;") 1073 1074(define_expand "floatunssidf2" 1075 [(set (match_operand:DF 0 "nonimmediate_operand" "") 1076 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))] 1077 "" 1078 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT, 1079 DFmode, SImode, 2, operands); 1080 DONE;") 1081 1082;;-------------------------------------------------------------------- 1083;;- Zero extension insns. 1084;;-------------------------------------------------------------------- 1085 1086;; 1087;; 64-bit extend. The insn will be split into 16-bit instructions just 1088;; before the final pass. We need a scratch register for the split. 1089;; The final value can be generated on the stack directly. This is more 1090;; efficient and useful for conversions made during parameter passing rules. 1091;; 1092(define_insn "zero_extendqidi2" 1093 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u") 1094 (zero_extend:DI 1095 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B"))) 1096 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))] 1097 "" 1098 "#") 1099 1100(define_split 1101 [(set (match_operand:DI 0 "push_operand" "") 1102 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" ""))) 1103 (clobber (match_scratch:HI 2 "=&dB"))] 1104 "z_replacement_completed == 2" 1105 [(const_int 0)] 1106 " 1107{ 1108 rtx low = m68hc11_gen_lowpart (SImode, operands[0]); 1109 rtx push = m68hc11_gen_lowpart (HImode, low); 1110 rtx src = operands[1]; 1111 1112 /* Source operand must be in a hard register. */ 1113 if (!H_REG_P (src)) 1114 { 1115 src = gen_rtx (REG, QImode, REGNO (operands[2])); 1116 emit_move_insn (src, operands[1]); 1117 } 1118 1119 /* Source is in D, we can push B then one word of 0 and we do 1120 a correction on the stack pointer. */ 1121 if (D_REG_P (src)) 1122 { 1123 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src); 1124 emit_move_insn (operands[2], const0_rtx); 1125 if (D_REG_P (operands[2])) 1126 { 1127 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src); 1128 } 1129 else 1130 { 1131 emit_move_insn (push, operands[2]); 1132 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM), 1133 gen_rtx (REG, HImode, HARD_SP_REGNUM), 1134 const1_rtx)); 1135 } 1136 } 1137 else 1138 { 1139 /* Source is in X or Y. It's better to push the 16-bit register 1140 and then to some stack adjustment. */ 1141 src = gen_rtx (REG, HImode, REGNO (src)); 1142 emit_move_insn (push, src); 1143 emit_move_insn (operands[2], const0_rtx); 1144 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM), 1145 gen_rtx (REG, HImode, HARD_SP_REGNUM), 1146 const1_rtx)); 1147 emit_move_insn (push, operands[2]); 1148 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM), 1149 gen_rtx (REG, HImode, HARD_SP_REGNUM), 1150 const1_rtx)); 1151 } 1152 emit_move_insn (push, operands[2]); 1153 emit_move_insn (push, operands[2]); 1154 emit_move_insn (push, operands[2]); 1155 DONE; 1156}") 1157 1158(define_split 1159 [(set (match_operand:DI 0 "nonimmediate_operand" "") 1160 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" ""))) 1161 (clobber (match_scratch:HI 2 "=&dB"))] 1162 "z_replacement_completed == 2" 1163 [(const_int 0)] 1164 " 1165{ 1166 rtx low = m68hc11_gen_lowpart (SImode, operands[0]); 1167 rtx low2 = m68hc11_gen_lowpart (HImode, low); 1168 rtx src = operands[1]; 1169 1170 /* Source operand must be in a hard register. */ 1171 if (!H_REG_P (src)) 1172 { 1173 src = gen_rtx (REG, QImode, REGNO (operands[2])); 1174 emit_move_insn (src, operands[1]); 1175 } 1176 1177 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src); 1178 emit_move_insn (operands[2], const0_rtx); 1179 src = gen_rtx (REG, QImode, REGNO (operands[2])); 1180 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src); 1181 1182 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]); 1183 low = m68hc11_gen_highpart (SImode, operands[0]); 1184 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]); 1185 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]); 1186 DONE; 1187}") 1188 1189(define_insn "zero_extendhidi2" 1190 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u") 1191 (zero_extend:DI 1192 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u"))) 1193 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))] 1194 "" 1195 "#") 1196 1197(define_split 1198 [(set (match_operand:DI 0 "non_push_operand" "") 1199 (zero_extend:DI 1200 (match_operand:HI 1 "nonimmediate_operand" ""))) 1201 (clobber (match_scratch:HI 2 ""))] 1202 "z_replacement_completed == 2" 1203 [(const_int 0)] 1204 " 1205{ 1206 rtx low = m68hc11_gen_lowpart (SImode, operands[0]); 1207 rtx high = m68hc11_gen_highpart (SImode, operands[0]); 1208 rtx src = operands[1]; 1209 1210 /* Make sure the source is in a hard register. */ 1211 if (!H_REG_P (src)) 1212 { 1213 src = operands[2]; 1214 emit_move_insn (src, operands[1]); 1215 } 1216 1217 /* Move the low part first for the push. */ 1218 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src); 1219 1220 /* Now, use the scratch register to fill in the zeros. */ 1221 emit_move_insn (operands[2], const0_rtx); 1222 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]); 1223 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]); 1224 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]); 1225 DONE; 1226}") 1227 1228(define_insn "zero_extendsidi2" 1229 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u") 1230 (zero_extend:DI 1231 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du"))) 1232 (clobber (match_scratch:HI 2 "=d,d,d,d"))] 1233 "" 1234 "#") 1235 1236(define_split 1237 [(set (match_operand:DI 0 "nonimmediate_operand" "") 1238 (zero_extend:DI 1239 (match_operand:SI 1 "nonimmediate_operand" ""))) 1240 (clobber (match_scratch:HI 2 ""))] 1241 "z_replacement_completed == 2" 1242 [(const_int 0)] 1243 " 1244{ 1245 rtx low = m68hc11_gen_lowpart (SImode, operands[0]); 1246 rtx high = m68hc11_gen_highpart (SImode, operands[0]); 1247 1248 /* Move the low part first so that this is ok for a push. */ 1249 m68hc11_split_move (low, operands[1], operands[2]); 1250 1251 /* Use the scratch register to clear the high part of the destination. */ 1252 emit_move_insn (operands[2], const0_rtx); 1253 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]); 1254 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]); 1255 DONE; 1256}") 1257 1258;; 1259;; For 16->32bit unsigned extension, we don't allow generation on the stack 1260;; because it's less efficient. 1261;; 1262(define_insn "zero_extendhisi2" 1263 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u") 1264 (zero_extend:SI 1265 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u"))) 1266 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))] 1267 "" 1268 "#") 1269 1270(define_split 1271 [(set (match_operand:SI 0 "non_push_operand" "") 1272 (zero_extend:SI 1273 (match_operand:HI 1 "nonimmediate_operand" ""))) 1274 (clobber (match_scratch:HI 2 ""))] 1275 "reload_completed" 1276 [(const_int 0)] 1277 " 1278{ 1279 rtx src = operands[1]; 1280 1281 if (!H_REG_P (src) && !H_REG_P (operands[0])) 1282 { 1283 src = operands[2]; 1284 emit_move_insn (src, operands[1]); 1285 } 1286 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src); 1287 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx); 1288 DONE; 1289}") 1290 1291(define_insn "zero_extendqisi2" 1292 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u") 1293 (zero_extend:SI 1294 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))] 1295 "" 1296 "#") 1297 1298(define_split 1299 [(set (match_operand:SI 0 "non_push_operand" "") 1300 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] 1301 "reload_completed && !X_REG_P (operands[0])" 1302 [(set (match_dup 2) (zero_extend:HI (match_dup 1))) 1303 (set (match_dup 3) (const_int 0))] 1304 " 1305 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]); 1306 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);") 1307 1308(define_split 1309 [(set (match_operand:SI 0 "hard_reg_operand" "") 1310 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] 1311 "z_replacement_completed == 2 && X_REG_P (operands[0])" 1312 [(set (match_dup 2) (match_dup 3)) 1313 (set (match_dup 4) (const_int 0)) 1314 (set (match_dup 5) (zero_extend:HI (match_dup 6)))] 1315 " 1316 if (X_REG_P (operands[1])) 1317 { 1318 emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM), 1319 gen_rtx (REG, HImode, HARD_X_REGNUM))); 1320 emit_insn (gen_zero_extendqihi2 (gen_rtx (REG, HImode, HARD_D_REGNUM), 1321 gen_rtx (REG, QImode, HARD_D_REGNUM))); 1322 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), 1323 const0_rtx); 1324 DONE; 1325 } 1326 1327 if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[1])) 1328 { 1329 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode, 1330 operands[0]), 1331 operands[1])); 1332 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), const0_rtx); 1333 DONE; 1334 } 1335 operands[4] = m68hc11_gen_highpart (HImode, operands[0]); 1336 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]); 1337 if (A_REG_P (operands[1])) 1338 { 1339 operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 1340 operands[3] = gen_rtx (REG, HImode, REGNO (operands[1])); 1341 operands[6] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 1342 } 1343 else 1344 { 1345 operands[5] = operands[2] = 1346 operands[3] = gen_rtx (REG, HImode, HARD_D_REGNUM); 1347 operands[6] = operands[1]; 1348 } 1349") 1350 1351(define_insn "zero_extendqihi2" 1352 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u") 1353 (zero_extend:HI 1354 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))] 1355 "" 1356 "* 1357{ 1358 if (A_REG_P (operands[0])) 1359 return \"#\"; 1360 1361 if (H_REG_P (operands[0])) 1362 { 1363 output_asm_insn (\"clra\", operands); 1364 if (operands[0] != operands[1] 1365 && !(D_REG_P (operands[0]) && D_REG_P (operands[1]))) 1366 { 1367 if (X_REG_P (operands[1]) 1368 || (D_REG_P (operands[1]) && X_REG_P (operands[0]))) 1369 { 1370 output_asm_insn (\"stx\\t%t1\", operands); 1371 output_asm_insn (\"ldab\\t%T0\", operands); 1372 } 1373 else if (Y_REG_P (operands[1]) 1374 || (D_REG_P (operands[1]) && Y_REG_P (operands[0]))) 1375 { 1376 output_asm_insn (\"sty\\t%t1\", operands); 1377 output_asm_insn (\"ldab\\t%T0\", operands); 1378 } 1379 else 1380 { 1381 output_asm_insn (\"ldab\\t%b1\", operands); 1382 } 1383 cc_status.flags |= CC_NOT_NEGATIVE; 1384 } 1385 else 1386 { 1387 /* Status refers to the clra insn. Status is ok for others 1388 * since we have loaded the value in B. 1389 */ 1390 CC_STATUS_INIT; 1391 } 1392 return \"\"; 1393 } 1394 1395 if (A_REG_P (operands[1])) 1396 { 1397 output_asm_insn (\"st%1\\t%0\", operands); 1398 output_asm_insn (\"clr\\t%h0\", operands); 1399 CC_STATUS_INIT; 1400 } 1401 else 1402 { 1403 output_asm_insn (\"clr\\t%h0\", operands); 1404 output_asm_insn (\"stab\\t%b0\", operands); 1405 cc_status.flags |= CC_NOT_NEGATIVE; 1406 } 1407 1408 return \"\"; 1409}") 1410 1411 1412;;-------------------------------------------------------------------- 1413;;- Sign extension insns. 1414;;-------------------------------------------------------------------- 1415 1416(define_insn "extendqisi2" 1417 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u") 1418 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))] 1419 "" 1420 "* 1421{ 1422 rtx ops[3]; 1423 int need_tst = 0; 1424 1425 /* The 68HC12 has a sign-extension instruction. Use it when the 1426 destination is the register (X,D). First sign-extend the low 1427 part and fill X with the sign-extension of the high part. */ 1428 if (TARGET_M6812 && X_REG_P (operands[0])) 1429 { 1430 if (!D_REG_P (operands[1])) 1431 { 1432 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); 1433 ops[1] = operands[1]; 1434 m68hc11_gen_movqi (insn, ops); 1435 } 1436 return \"sex\\tb,d\\n\\tsex\\ta,x\"; 1437 } 1438 1439 ops[2] = gen_label_rtx (); 1440 1441 if (X_REG_P (operands[1])) 1442 { 1443 output_asm_insn (\"xgdx\", operands); 1444 need_tst = 1; 1445 } 1446 else if (X_REG_P (operands[0])) 1447 { 1448 /* X can be used as an indexed addressing in the source. 1449 Get the value before clearing it. */ 1450 if (reg_mentioned_p (ix_reg, operands[1])) 1451 { 1452 output_asm_insn (\"ldab\\t%b1\", operands); 1453 need_tst = 1; 1454 } 1455 output_asm_insn (\"ldx\\t#0\", operands); 1456 } 1457 1458 output_asm_insn (\"clra\", operands); 1459 if (!X_REG_P (operands[0])) 1460 { 1461 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]); 1462 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]); 1463 1464 if (IS_STACK_PUSH (operands[0])) 1465 { 1466 output_asm_insn (\"pshb\", ops); 1467 output_asm_insn (\"tstb\", ops); 1468 } 1469 else 1470 { 1471 output_asm_insn (\"stab\\t%b1\", ops); 1472 } 1473 } 1474 else if (D_REG_P (operands[1]) || need_tst) 1475 { 1476 output_asm_insn (\"tstb\", operands); 1477 } 1478 else 1479 { 1480 output_asm_insn (\"ldab\\t%b1\", operands); 1481 } 1482 output_asm_insn (\"bpl\\t%l2\", ops); 1483 output_asm_insn (\"deca\", operands); 1484 if (X_REG_P (operands[0])) 1485 output_asm_insn (\"dex\", operands); 1486 1487 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); 1488 1489 if (!X_REG_P (operands[0])) 1490 { 1491 if (IS_STACK_PUSH (operands[0])) 1492 { 1493 output_asm_insn (\"psha\", ops); 1494 output_asm_insn (\"psha\", ops); 1495 output_asm_insn (\"psha\", ops); 1496 } 1497 else 1498 { 1499 output_asm_insn (\"staa\\t%h0\", ops); 1500 1501 ops[0] = m68hc11_gen_highpart (HImode, operands[0]); 1502 if (dead_register_here (insn, d_reg)) 1503 { 1504 output_asm_insn (\"tab\", ops); 1505 output_asm_insn (\"std\\t%0\", ops); 1506 } 1507 else 1508 { 1509 output_asm_insn (\"staa\\t%b0\", ops); 1510 output_asm_insn (\"staa\\t%h0\", ops); 1511 } 1512 } 1513 } 1514 1515 CC_STATUS_INIT; 1516 return \"\"; 1517}") 1518 1519 1520(define_insn "extendqihi2" 1521 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u") 1522 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))] 1523 "" 1524 "* 1525{ 1526 rtx ops[2]; 1527 1528 if (A_REG_P (operands[0])) 1529 return \"#\"; 1530 1531 ops[0] = gen_label_rtx (); 1532 if (D_REG_P (operands[0])) 1533 { 1534 if (TARGET_M6812) 1535 { 1536 if (!D_REG_P (operands[1])) 1537 { 1538 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); 1539 ops[1] = operands[1]; 1540 m68hc11_gen_movqi (insn, ops); 1541 } 1542 return \"sex\\tb,d\"; 1543 } 1544 output_asm_insn (\"clra\", operands); 1545 if (H_REG_P (operands[1])) 1546 { 1547 output_asm_insn (\"tstb\", operands); 1548 } 1549 else 1550 { 1551 output_asm_insn (\"ldab\\t%b1\", operands); 1552 } 1553 output_asm_insn (\"bpl\\t%l0\", ops); 1554 output_asm_insn (\"deca\", operands); 1555 1556 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 1557 CODE_LABEL_NUMBER (ops[0])); 1558 } 1559 else 1560 { 1561 output_asm_insn (\"clr\\t%h0\", operands); 1562 if (m68hc11_register_indirect_p (operands[1], HImode)) 1563 { 1564 ops[1] = operands[1]; 1565 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops); 1566 CC_STATUS_INIT; 1567 } 1568 else 1569 { 1570 output_asm_insn (\"tst\\t%b1\", operands); 1571 output_asm_insn (\"bpl\\t%l0\", ops); 1572 } 1573 output_asm_insn (\"dec\\t%h0\", operands); 1574 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 1575 CODE_LABEL_NUMBER (ops[0])); 1576 } 1577 1578 return \"\"; 1579}") 1580 1581;; 1582;; Split the special case where the source of the sign extend is 1583;; either Y or Z. In that case, we can't move the source in the D 1584;; register directly. The movhi pattern handles this move by using 1585;; a temporary scratch memory location. 1586;; 1587(define_split 1588 [(set (match_operand:SI 0 "register_operand" "") 1589 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] 1590 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))" 1591 [(set (reg:HI D_REGNUM) (match_dup 1)) 1592 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))] 1593 "") 1594 1595(define_insn "extendhisi2" 1596 [(set (match_operand:SI 0 "register_operand" "=D,D,D") 1597 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))] 1598 "" 1599 "* 1600{ 1601 rtx ops[2]; 1602 int x_reg_used; 1603 1604 if (Y_REG_P (operands[1])) 1605 return \"#\"; 1606 1607 if (X_REG_P (operands[1])) 1608 { 1609 output_asm_insn (\"xgdx\", operands); 1610 x_reg_used = 1; 1611 } 1612 else 1613 { 1614 /* X can be used as an indexed addressing in the source. 1615 Get the value before clearing it. */ 1616 x_reg_used = reg_mentioned_p (ix_reg, operands[1]); 1617 if (x_reg_used) 1618 { 1619 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); 1620 ops[1] = operands[1]; 1621 m68hc11_gen_movhi (insn, ops); 1622 } 1623 } 1624 1625 CC_STATUS_INIT; 1626 if (TARGET_M6812 && 0) 1627 { 1628 /* This sequence of code is larger than the one for 68HC11. 1629 Don't use it; keep it for documentation. */ 1630 if (!D_REG_P (operands[1]) && !x_reg_used) 1631 { 1632 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); 1633 ops[1] = operands[1]; 1634 m68hc11_gen_movhi (insn, ops); 1635 } 1636 output_asm_insn (\"sex\\ta,x\", operands); 1637 output_asm_insn (\"xgdx\", operands); 1638 output_asm_insn (\"sex\\ta,d\", operands); 1639 return \"xgdx\"; 1640 } 1641 1642 output_asm_insn (\"ldx\\t#0\", operands); 1643 if (D_REG_P (operands[1]) || x_reg_used) 1644 { 1645 output_asm_insn (\"tsta\", operands); 1646 } 1647 else 1648 { 1649 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); 1650 ops[1] = operands[1]; 1651 m68hc11_gen_movhi (insn, ops); 1652 } 1653 1654 ops[0] = gen_label_rtx (); 1655 output_asm_insn (\"bpl\\t%l0\", ops); 1656 output_asm_insn (\"dex\", operands); 1657 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); 1658 1659 return \"\"; 1660}") 1661 1662 1663;;-------------------------------------------------------------------- 1664;;- Min and Max instructions (68HC12). 1665;;-------------------------------------------------------------------- 1666(define_insn "uminqi3" 1667 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") 1668 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") 1669 (match_operand:QI 2 "general_operand" "m,d")))] 1670 "TARGET_M6812 && TARGET_MIN_MAX" 1671 "* 1672{ 1673 /* Flags are set according to (sub:QI (operand 1) (operand2)). 1674 The mina/minm use A as the source or destination. This is the 1675 high part of D. There is no way to express that in the pattern 1676 so we must use 'exg a,b' to put the operand in the good register. */ 1677 CC_STATUS_INIT; 1678 if (D_REG_P (operands[0])) 1679 { 1680 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\"; 1681 } 1682 else 1683 { 1684 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\"; 1685 } 1686}") 1687 1688(define_insn "umaxqi3" 1689 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") 1690 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") 1691 (match_operand:QI 2 "general_operand" "m,d")))] 1692 "TARGET_M6812 && TARGET_MIN_MAX" 1693 "* 1694{ 1695 /* Flags are set according to (sub:QI (operand 1) (operand2)). 1696 The maxa/maxm use A as the source or destination. This is the 1697 high part of D. There is no way to express that in the pattern 1698 so we must use 'exg a,b' to put the operand in the good register. */ 1699 CC_STATUS_INIT; 1700 if (D_REG_P (operands[0])) 1701 { 1702 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\"; 1703 } 1704 else 1705 { 1706 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\"; 1707 } 1708}") 1709 1710(define_insn "uminhi3" 1711 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") 1712 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") 1713 (match_operand:HI 2 "general_operand" "m,d")))] 1714 "TARGET_M6812 && TARGET_MIN_MAX" 1715 "* 1716{ 1717 /* Flags are set according to (sub:HI (operand 1) (operand2)). */ 1718 CC_STATUS_INIT; 1719 if (D_REG_P (operands[0])) 1720 { 1721 return \"emind\\t%2\"; 1722 } 1723 else 1724 { 1725 return \"eminm\\t%0\"; 1726 } 1727}") 1728 1729(define_insn "umaxhi3" 1730 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") 1731 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") 1732 (match_operand:HI 2 "general_operand" "m,d")))] 1733 "TARGET_M6812 && TARGET_MIN_MAX" 1734 "* 1735{ 1736 /* Flags are set according to (sub:HI (operand 1) (operand2)). */ 1737 CC_STATUS_INIT; 1738 if (D_REG_P (operands[0])) 1739 { 1740 return \"emaxd\\t%2\"; 1741 } 1742 else 1743 { 1744 return \"emaxm\\t%0\"; 1745 } 1746}") 1747 1748 1749;;-------------------------------------------------------------------- 1750;;- Add instructions. 1751;;-------------------------------------------------------------------- 1752;; 64-bit: Use a library call because what GCC generates is huge. 1753;; 1754(define_expand "adddi3" 1755 [(set (match_operand:DI 0 "nonimmediate_operand" "") 1756 (plus:DI (match_operand:DI 1 "general_operand" "") 1757 (match_operand:DI 2 "general_operand" "")))] 1758 "" 1759 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands); 1760 DONE;") 1761 1762;; 1763;; - 32-bit Add. 1764;; 1765(define_expand "addsi3" 1766 [(parallel [(set (match_operand:SI 0 "register_operand" "") 1767 (plus:SI (match_operand:SI 1 "general_operand" "") 1768 (match_operand:SI 2 "general_operand" ""))) 1769 (clobber (match_scratch:HI 3 ""))])] 1770 "" 1771 "") 1772 1773(define_insn "*addsi3_zero_extendhi" 1774 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D") 1775 (plus:SI (zero_extend:SI 1776 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u")) 1777 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du"))) 1778 (clobber (match_scratch:HI 3 "=X,X,X,X"))] 1779 "" 1780 "* 1781{ 1782 rtx ops[3]; 1783 1784 if (X_REG_P (operands[2])) 1785 { 1786 ops[0] = operands[1]; 1787 } 1788 else 1789 { 1790 if (X_REG_P (operands[1])) 1791 { 1792 output_asm_insn (\"xgdx\", ops); 1793 } 1794 else if (!D_REG_P (operands[1])) 1795 { 1796 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); 1797 ops[1] = operands[1]; 1798 m68hc11_gen_movhi (insn, ops); 1799 } 1800 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]); 1801 ops[1] = m68hc11_gen_highpart (HImode, operands[2]); 1802 } 1803 ops[2] = gen_label_rtx (); 1804 1805 /* ldx preserves the carry, propagate it by incrementing X directly. */ 1806 output_asm_insn (\"addd\\t%0\", ops); 1807 if (!X_REG_P (operands[2])) 1808 output_asm_insn (\"ldx\\t%1\", ops); 1809 1810 output_asm_insn (\"bcc\\t%l2\", ops); 1811 output_asm_insn (\"inx\", ops); 1812 1813 CC_STATUS_INIT; 1814 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); 1815 return \"\"; 1816}") 1817 1818 1819(define_split /* "*addsi3_zero_extendqi" */ 1820 [(set (match_operand:SI 0 "register_operand" "") 1821 (plus:SI (zero_extend:SI 1822 (match_operand:QI 1 "general_operand" "")) 1823 (match_operand:SI 2 "memory_operand" ""))) 1824 (clobber (match_scratch:HI 3 "=X,X"))] 1825 "reload_completed" 1826 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1))) 1827 (parallel [(set (match_dup 0) 1828 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2))) 1829 (clobber (match_dup 3))])] 1830 "") 1831 1832(define_insn "*addsi3_zero_extendqi" 1833 [(set (match_operand:SI 0 "register_operand" "=D,D") 1834 (plus:SI (zero_extend:SI 1835 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu")) 1836 (match_operand:SI 2 "general_operand" "miD,!muiD"))) 1837 (clobber (match_scratch:HI 3 "=X,X"))] 1838 "" 1839 "* 1840{ 1841 rtx ops[4]; 1842 1843 if (GET_CODE (operands[2]) == MEM) 1844 return \"#\"; 1845 1846 if (X_REG_P (operands[2])) 1847 { 1848 if (H_REG_P (operands[1])) 1849 { 1850 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 1851 ops[1] = gen_rtx (REG, HImode, REGNO (operands[1])); 1852 m68hc11_gen_movhi (insn, ops); 1853 } 1854 else 1855 { 1856 ops[0] = operands[1]; 1857 } 1858 ops[1] = const0_rtx; 1859 } 1860 else 1861 { 1862 if (X_REG_P (operands[1])) 1863 { 1864 output_asm_insn (\"xgdx\", ops); 1865 } 1866 else if (!D_REG_P (operands[1])) 1867 { 1868 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); 1869 ops[1] = operands[1]; 1870 m68hc11_gen_movqi (insn, ops); 1871 } 1872 1873 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]); 1874 ops[1] = ops[0]; 1875 ops[2] = m68hc11_gen_highpart (HImode, operands[2]); 1876 output_asm_insn (\"clra\", ops); 1877 } 1878 1879 /* ldx preserves the carry, propagate it by incrementing X directly. */ 1880 output_asm_insn (\"addb\\t%b0\", ops); 1881 output_asm_insn (\"adca\\t%h1\", ops); 1882 if (!X_REG_P (operands[2])) 1883 output_asm_insn (\"ldx\\t%2\", ops); 1884 1885 /* If the above adca was adding some constant, we don't need to propagate 1886 the carry unless the constant was 0xff. */ 1887 if (X_REG_P (operands[2]) 1888 || GET_CODE (ops[1]) != CONST_INT 1889 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00)) 1890 { 1891 ops[3] = gen_label_rtx (); 1892 1893 output_asm_insn (\"bcc\\t%l3\", ops); 1894 output_asm_insn (\"inx\", ops); 1895 1896 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 1897 CODE_LABEL_NUMBER (ops[3])); 1898 } 1899 CC_STATUS_INIT; 1900 return \"\"; 1901}") 1902 1903(define_insn "*addsi3" 1904 [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D") 1905 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0") 1906 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu"))) 1907 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))] 1908 "" 1909 "* 1910{ 1911 rtx ops[3]; 1912 const char* add_insn; 1913 const char* inc_insn; 1914 const char* incb_mem; 1915 const char* inch_mem; 1916 HOST_WIDE_INT val; 1917 1918 if (which_alternative > 2) 1919 { 1920 return \"#\"; 1921 } 1922 1923 val = INTVAL (operands[2]); 1924 if ((val & 0x0ffffL) == 0) 1925 { 1926 if (!H_REG_P (operands[0])) 1927 { 1928 ops[0] = m68hc11_gen_highpart (HImode, operands[0]); 1929 ops[1] = m68hc11_gen_highpart (HImode, operands[2]); 1930 output_asm_insn (\"ldd\\t%0\", ops); 1931 output_asm_insn (\"addd\\t%1\", ops); 1932 output_asm_insn (\"std\\t%0\", ops); 1933 return \"\"; 1934 } 1935 else if (val == 1) 1936 { 1937 return \"inx\"; 1938 } 1939 else 1940 { 1941 return \"#\"; 1942 } 1943 } 1944 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L) 1945 { 1946 return \"#\"; 1947 } 1948 1949 if (val >= 0) 1950 { 1951 ops[1] = operands[2]; 1952 add_insn = \"addd\\t%1\"; 1953 inc_insn = \"inx\\t\"; 1954 incb_mem = \"inc\\t%b1\"; 1955 inch_mem = \"inc\\t%h1\"; 1956 } 1957 else 1958 { 1959 ops[1] = GEN_INT (- val); 1960 add_insn = \"subd\\t%1\"; 1961 inc_insn = \"dex\"; 1962 incb_mem = \"dec\\t%b1\"; 1963 inch_mem = \"dec\\t%h1\"; 1964 } 1965 1966 ops[2] = gen_label_rtx (); 1967 if (!H_REG_P (operands[0])) 1968 { 1969 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]); 1970 output_asm_insn (\"ldd\\t%0\", ops); 1971 } 1972 output_asm_insn (add_insn, ops); 1973 if (!H_REG_P (operands[0])) 1974 { 1975 output_asm_insn (\"std\\t%0\", ops); 1976 } 1977 output_asm_insn (\"bcc\\t%l2\", ops); 1978 if (H_REG_P (operands[0])) 1979 { 1980 output_asm_insn (inc_insn, ops); 1981 } 1982 else 1983 { 1984 ops[0] = m68hc11_gen_highpart (HImode, operands[0]); 1985 ops[1] = ops[0]; 1986 if (INTVAL (operands[2]) < 0) 1987 { 1988 output_asm_insn (\"ldd\\t%1\", ops); 1989 output_asm_insn (\"addd\\t#-1\", ops); 1990 output_asm_insn (\"std\\t%1\", ops); 1991 } 1992 else 1993 { 1994 output_asm_insn (incb_mem, ops); 1995 output_asm_insn (\"bne\\t%l2\", ops); 1996 output_asm_insn (inch_mem, ops); 1997 } 1998 } 1999 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); 2000 2001 CC_STATUS_INIT; 2002 return \"\"; 2003}") 2004 2005(define_split 2006 [(set (match_operand:SI 0 "register_operand" "") 2007 (plus:SI (match_operand:SI 1 "register_operand" "") 2008 (match_operand:SI 2 "const_int_operand" ""))) 2009 (clobber (match_scratch:HI 3 ""))] 2010 "reload_completed && z_replacement_completed == 2 2011 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)" 2012 [(set (match_dup 5) (match_dup 6)) 2013 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4))) 2014 (set (match_dup 6) (match_dup 5))] 2015 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]); 2016 if (X_REG_P (operands[0])) 2017 { 2018 operands[5] = operands[6] = gen_rtx (REG, HImode, HARD_D_REGNUM); 2019 } 2020 else 2021 { 2022 operands[6] = m68hc11_gen_highpart (HImode, operands[1]); 2023 operands[5] = operands[3]; 2024 } 2025 ") 2026 2027(define_split 2028 [(set (match_operand:SI 0 "register_operand" "") 2029 (plus:SI (match_operand:SI 1 "register_operand" "") 2030 (match_operand:SI 2 "general_operand" ""))) 2031 (clobber (match_scratch:HI 3 "=X"))] 2032 "reload_completed && z_replacement_completed == 2 2033 && (GET_CODE (operands[2]) != CONST_INT || 2034 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))" 2035 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3))) 2036 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) 2037 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))]) 2038 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4))) 2039 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5))) 2040 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) 2041 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])] 2042 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]); 2043 operands[4] = m68hc11_gen_highpart (HImode, operands[2]); 2044 operands[5] = m68hc11_gen_highpart (QImode, operands[4]); 2045 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);") 2046 2047;; 2048;; Instruction generated to propagate the carry of a 16-bit add 2049;; to the upper 16-bit part (in register X). 2050;; 2051(define_insn "*addsi_carry" 2052 [(set (match_operand:HI 0 "register_operand" "=x") 2053 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0") 2054 (const_int 0)) 2055 (reg:HI CC_REGNUM)))] 2056 "" 2057 "* 2058{ 2059 rtx ops[2]; 2060 2061 ops[0] = gen_label_rtx (); 2062 output_asm_insn (\"bcc\\t%l0\", ops); 2063 output_asm_insn (\"in%0\", operands); 2064 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); 2065 CC_STATUS_INIT; 2066 return \"\"; 2067}") 2068 2069;; 2070;; - 16-bit Add. 2071;; 2072(define_expand "addhi3" 2073 [(set (match_operand:HI 0 "register_operand" "") 2074 (plus:HI (match_operand:HI 1 "register_operand" "") 2075 (match_operand:HI 2 "general_operand" "")))] 2076 "" 2077 " 2078{ 2079 if (TARGET_M6811 && SP_REG_P (operands[0])) 2080 { 2081 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, 2082 gen_rtx (SET, VOIDmode, 2083 operand0, 2084 gen_rtx (PLUS, HImode, 2085 operand1, operand2)), 2086 gen_rtx (CLOBBER, VOIDmode, 2087 gen_rtx (SCRATCH, HImode))))); 2088 DONE; 2089 } 2090}") 2091 2092(define_insn "*addhi3_68hc12" 2093 [(set (match_operand:HI 0 "register_operand" "=xyd,d,xy*z*w,xy*z*w,xy*z") 2094 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*zw,0") 2095 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))] 2096 "TARGET_M6812" 2097 "* 2098{ 2099 int val; 2100 const char* insn_code; 2101 2102 if (which_alternative >= 4) 2103 { 2104 if (A_REG_P (operands[2])) 2105 { 2106 CC_STATUS_INIT; 2107 output_asm_insn (\"xgd%2\", operands); 2108 output_asm_insn (\"lea%0 d,%0\", operands); 2109 return \"xgd%2\"; 2110 } 2111 return \"#\"; 2112 } 2113 2114 if (D_REG_P (operands[0])) 2115 { 2116 if (X_REG_P (operands[2])) 2117 { 2118 m68hc11_notice_keep_cc (operands[0]); 2119 output_asm_insn (\"xgdx\", operands); 2120 output_asm_insn (\"leax\\td,%2\", operands); 2121 return \"xgdx\"; 2122 } 2123 else if (Y_REG_P (operands[2])) 2124 { 2125 m68hc11_notice_keep_cc (operands[0]); 2126 output_asm_insn (\"xgdy\", operands); 2127 output_asm_insn (\"leay\\td,%2\", operands); 2128 return \"xgdy\"; 2129 } 2130 else if (SP_REG_P (operands[2])) 2131 { 2132 output_asm_insn (\"sts\\t%t0\", operands); 2133 return \"addd\\t%t0\"; 2134 } 2135 return \"addd\\t%2\"; 2136 } 2137 2138 if (GET_CODE (operands[2]) == CONST_INT) 2139 val = INTVAL (operands[2]); 2140 else 2141 val = 1000; 2142 2143 if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1])) 2144 { 2145 m68hc11_notice_keep_cc (operands[0]); 2146 switch (REGNO (operands[0])) 2147 { 2148 case HARD_X_REGNUM: 2149 return \"leax\\t%i2,%1\"; 2150 2151 case HARD_Y_REGNUM: 2152 return \"leay\\t%i2,%1\"; 2153 2154 case HARD_SP_REGNUM: 2155 return \"leas\\t%i2,%1\"; 2156 2157 default: 2158 fatal_insn (\"Invalid operands in the instruction\", insn); 2159 } 2160 } 2161 if (val > 0) 2162 { 2163 insn_code = X_REG_P (operands[0]) ? \"inx\" 2164 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\"; 2165 } 2166 else 2167 { 2168 val = -val; 2169 insn_code = X_REG_P (operands[0]) ? \"dex\" 2170 : Y_REG_P (operands[0]) ? \"dey\" : \"des\"; 2171 } 2172 2173 /* For X and Y increment, the flags are not complete. Only the Z flag 2174 is updated. For SP increment, flags are not changed. */ 2175 if (SP_REG_P (operands[0])) 2176 { 2177 cc_status = cc_prev_status; 2178 if (INTVAL (operands[2]) < 0) 2179 { 2180 while (val > 2) 2181 { 2182 output_asm_insn (\"pshx\", operands); 2183 val -= 2; 2184 } 2185 if (val == 0) 2186 return \"\"; 2187 } 2188 } 2189 else 2190 { 2191 CC_STATUS_INIT; 2192 } 2193 2194 while (val) 2195 { 2196 output_asm_insn (insn_code, operands); 2197 val--; 2198 } 2199 return \"\"; 2200}") 2201 2202;; 2203;; Specific pattern to add to the stack pointer. 2204;; We also take care of the clobbering of the IY register. 2205;; 2206(define_insn "addhi_sp" 2207 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w") 2208 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0") 2209 (match_operand:HI 2 "general_operand" "P,im,u,im"))) 2210 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))] 2211 "!TARGET_M6812" 2212 "* 2213{ 2214 HOST_WIDE_INT val; 2215 2216 if (optimize && Y_REG_P (operands[3]) 2217 && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM))) 2218 operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM); 2219 2220 if (GET_CODE (operands[2]) == CONST_INT 2221 && (val = INTVAL (operands[2])) != 0 2222 && (CONST_OK_FOR_LETTER_P (val, 'P') 2223 || (val > 0 && val <= 8))) 2224 { 2225 while (val > 1 || val < -1) 2226 { 2227 if (val > 0) 2228 { 2229 if (!H_REG_P (operands[3])) 2230 break; 2231 2232 output_asm_insn (\"pul%3\", operands); 2233 val -= 2; 2234 } 2235 else 2236 { 2237 output_asm_insn (\"pshx\", operands); 2238 val += 2; 2239 } 2240 } 2241 while (val != 0) 2242 { 2243 if (val > 0) 2244 { 2245 output_asm_insn (\"ins\", operands); 2246 val--; 2247 } 2248 else 2249 { 2250 output_asm_insn (\"des\", operands); 2251 val++; 2252 } 2253 } 2254 cc_status = cc_prev_status; 2255 return \"\"; 2256 } 2257 2258 /* Need to transfer to SP to X/Y and then to D register. 2259 Register X/Y is lost, this is specified by the (clobber) statement. */ 2260 output_asm_insn (\"ts%3\", operands); 2261 if (GET_CODE (operands[2]) == CONST_INT 2262 && ((val = INTVAL (operands[2])) >= 0 && val < 0x100) 2263 && dead_register_here (insn, gen_rtx (REG, HImode, HARD_D_REGNUM))) 2264 { 2265 output_asm_insn (\"ldab\\t%2\", operands); 2266 output_asm_insn (\"ab%3\", operands); 2267 CC_STATUS_INIT; 2268 } 2269 else 2270 { 2271 output_asm_insn (\"xgd%3\", operands); 2272 output_asm_insn (\"addd\\t%2\", operands); 2273 output_asm_insn (\"xgd%3\", operands); 2274 } 2275 2276 /* The status flags correspond to the addd. xgdy and tys do not 2277 modify the flags. */ 2278 return \"t%3s\"; 2279}") 2280 2281(define_insn "*addhi3" 2282 [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,!d*A") 2283 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0") 2284 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,!u*d*w")))] 2285 "TARGET_M6811" 2286 "* 2287{ 2288 const char* insn_code; 2289 int val; 2290 2291 if (D_REG_P (operands[0]) && SP_REG_P (operands[2])) 2292 { 2293 output_asm_insn (\"sts\\t%t0\", operands); 2294 output_asm_insn (\"addd\\t%t0\", operands); 2295 return \"addd\\t#1\"; 2296 } 2297 if (GET_CODE (operands[2]) != CONST_INT) 2298 { 2299 /* Adding to an address register or with another/same register 2300 is not possible. This must be replaced. */ 2301 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 2302 return \"#\"; 2303 2304 return \"addd\\t%2\"; 2305 } 2306 val = INTVAL (operands[2]); 2307 if (!SP_REG_P (operands[0])) 2308 { 2309 if (D_REG_P (operands[0])) 2310 { 2311 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0])) 2312 { 2313 CC_STATUS_INIT; 2314 return \"adda\\t%h2\"; 2315 } 2316 else 2317 { 2318 return \"addd\\t%2\"; 2319 } 2320 } 2321 else if (GET_CODE (operands[2]) != CONST_INT 2322 || INTVAL (operands[2]) < -4 2323 || INTVAL (operands[2]) > 4) 2324 return \"#\"; 2325 } 2326 if (val > 0) 2327 { 2328 insn_code = X_REG_P (operands[0]) ? \"inx\" 2329 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\"; 2330 } 2331 else 2332 { 2333 val = -val; 2334 insn_code = X_REG_P (operands[0]) ? \"dex\" 2335 : Y_REG_P (operands[0]) ? \"dey\" : \"des\"; 2336 } 2337 2338 /* For X and Y increment, the flags are not complete. Only the Z flag 2339 is updated. For SP increment, flags are not changed. */ 2340 if (SP_REG_P (operands[0])) 2341 { 2342 cc_status = cc_prev_status; 2343 if (INTVAL (operands[2]) < 0) 2344 { 2345 while (val >= 2) 2346 { 2347 output_asm_insn (\"pshx\", operands); 2348 val -= 2; 2349 } 2350 } 2351 else if (optimize && dead_register_here (insn, ix_reg)) 2352 { 2353 while (val >= 2) 2354 { 2355 output_asm_insn (\"pulx\", operands); 2356 val -= 2; 2357 } 2358 } 2359 } 2360 else 2361 { 2362 CC_STATUS_INIT; 2363 } 2364 2365 while (val) 2366 { 2367 output_asm_insn (insn_code, operands); 2368 val--; 2369 } 2370 return \"\"; 2371}") 2372 2373(define_insn "*addhi3_zext" 2374 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d") 2375 (plus:HI (zero_extend:HI 2376 (match_operand:QI 1 "nonimmediate_operand" "d,um*A")) 2377 (match_operand:HI 2 "hard_reg_operand" "0,0")))] 2378 "" 2379 "* 2380{ 2381 CC_STATUS_INIT; 2382 if (A_REG_P (operands[0])) 2383 return \"ab%0\"; 2384 else if (A_REG_P (operands[1])) 2385 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\"; 2386 else 2387 return \"addb\\t%b1\\n\\tadca\\t#0\"; 2388}") 2389 2390;; 2391;; Translate d = d + d into d = << 1 2392;; We have to do this because adding a register to itself is not possible. 2393;; ??? It's not clear whether this is really necessary. 2394;; 2395(define_split 2396 [(set (match_operand:QI 0 "hard_reg_operand" "") 2397 (plus:QI (match_dup 0) 2398 (match_dup 0)))] 2399 "0 && reload_completed" 2400 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))] 2401 "") 2402 2403(define_insn "addqi3" 2404 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A") 2405 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") 2406 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))] 2407 "" 2408 "* 2409{ 2410 if (GET_CODE (operands[2]) == CONST_INT) 2411 { 2412 if (INTVAL (operands[2]) == 1) 2413 { 2414 if (DA_REG_P (operands[0])) 2415 { 2416 return \"inca\"; 2417 } 2418 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 2419 { 2420 return \"incb\"; 2421 2422 } 2423 else if (A_REG_P (operands[0])) 2424 { 2425 /* This applies on the 16-bit register. This should be ok since 2426 this is not a strict_low_part increment. */ 2427 return \"in%0\"; 2428 } 2429 else 2430 { 2431 return \"inc\\t%b0\"; 2432 } 2433 } 2434 else if (INTVAL (operands[2]) == -1) 2435 { 2436 if (DA_REG_P (operands[0])) 2437 { 2438 return \"deca\"; 2439 } 2440 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 2441 { 2442 return \"decb\"; 2443 } 2444 else if (A_REG_P (operands[0])) 2445 { 2446 /* This applies on the 16-bit register. This should be ok since 2447 this is not a strict_low_part decrement. */ 2448 return \"de%0\"; 2449 } 2450 else 2451 { 2452 return \"dec\\t%b0\"; 2453 } 2454 } 2455 } 2456 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 2457 return \"#\"; 2458 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 2459 return \"addb\\t%b2\"; 2460 else 2461 return \"adda\\t%b2\"; 2462}") 2463 2464;; 2465;; add with carry is used for 32-bit add. 2466;; 2467(define_insn "*adcq" 2468 [(set (match_operand:QI 0 "register_operand" "=q") 2469 (plus:QI (plus:QI (reg:QI CC_REGNUM) 2470 (match_operand:QI 1 "register_operand" "%0")) 2471 (match_operand:QI 2 "general_operand" "ium")))] 2472 "" 2473 "adc%0\\t%b2") 2474 2475;;-------------------------------------------------------------------- 2476;;- Subtract instructions. 2477;;-------------------------------------------------------------------- 2478 2479(define_expand "subdi3" 2480 [(set (match_operand:DI 0 "nonimmediate_operand" "") 2481 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") 2482 (match_operand:DI 2 "general_operand" "")))] 2483 "" 2484 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands); 2485 DONE;") 2486 2487;; 2488;; 32-bit Subtract (see addsi3) 2489;; Subtract with a constant are handled by addsi3. 2490;; 2491;; 2492;; - 32-bit Add. 2493;; 2494(define_expand "subsi3" 2495 [(parallel [(set (match_operand:SI 0 "register_operand" "") 2496 (minus:SI (match_operand:SI 1 "register_operand" "") 2497 (match_operand:SI 2 "general_operand" ""))) 2498 (clobber (match_scratch:HI 3 ""))])] 2499 "" 2500 "") 2501 2502(define_insn "*subsi3" 2503 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u") 2504 (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0") 2505 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui"))) 2506 (clobber (match_scratch:HI 3 "=X,X,X,X,d"))] 2507 "" 2508 "#") 2509 2510(define_insn "*subsi3_zero_extendhi" 2511 [(set (match_operand:SI 0 "register_operand" "=D") 2512 (minus:SI (match_operand:SI 1 "register_operand" "0") 2513 (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A")))) 2514 (clobber (match_scratch:HI 3 "=X"))] 2515 "" 2516 "* 2517{ 2518 rtx ops[2]; 2519 2520 if (A_REG_P (operands[2])) 2521 { 2522 if (TARGET_M6812) 2523 ops[0] = gen_rtx (MEM, HImode, 2524 gen_rtx (PRE_DEC, HImode, 2525 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 2526 else 2527 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 2528 2529 ops[1] = operands[2]; 2530 m68hc11_gen_movhi (insn, ops); 2531 if (TARGET_M6812) 2532 operands[2] = gen_rtx (MEM, HImode, 2533 gen_rtx (POST_INC, HImode, 2534 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 2535 else 2536 operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 2537 } 2538 ops[0] = gen_label_rtx (); 2539 output_asm_insn (\"subd\\t%2\", operands); 2540 output_asm_insn (\"bcc\\t%l0\", ops); 2541 output_asm_insn (\"dex\", ops); 2542 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); 2543 CC_STATUS_INIT; 2544 return \"\"; 2545}") 2546 2547(define_insn "*subsi3_zero_extendqi" 2548 [(set (match_operand:SI 0 "register_operand" "=D") 2549 (minus:SI (match_operand:SI 1 "register_operand" "0") 2550 (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A")))) 2551 (clobber (match_scratch:HI 3 "=X"))] 2552 "" 2553 "* 2554{ 2555 rtx ops[2]; 2556 2557 if (A_REG_P (operands[2])) 2558 { 2559 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 2560 ops[1] = operands[2]; 2561 m68hc11_gen_movhi (insn, ops); 2562 operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 2563 } 2564 ops[0] = gen_label_rtx (); 2565 output_asm_insn (\"subb\\t%b2\", operands); 2566 output_asm_insn (\"sbca\\t#0\", operands); 2567 output_asm_insn (\"bcc\\t%l0\", ops); 2568 output_asm_insn (\"dex\", ops); 2569 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); 2570 CC_STATUS_INIT; 2571 return \"\"; 2572}") 2573 2574;; 2575;; reg:HI 1 -> d reg:QI 6 -> B 2576;; reg:QI 7 -> ccr reg:QI 5 -> A 2577;; 2578(define_split /* "*subsi3" */ 2579 [(set (match_operand:SI 0 "register_operand" "") 2580 (minus:SI (match_operand:SI 1 "register_operand" "") 2581 (match_operand:SI 2 "general_operand" ""))) 2582 (clobber (match_scratch:HI 3 "=X"))] 2583 "reload_completed && z_replacement_completed == 2 2584 && X_REG_P (operands[1])" 2585 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3))) 2586 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM)) 2587 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))]) 2588 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4))) 2589 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5))) 2590 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM)) 2591 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])] 2592 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]); 2593 operands[4] = m68hc11_gen_highpart (HImode, operands[2]); 2594 operands[5] = m68hc11_gen_highpart (QImode, operands[4]); 2595 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);") 2596 2597(define_split /* "*subsi3" */ 2598 [(set (match_operand:SI 0 "register_operand" "") 2599 (minus:SI (match_operand:SI 1 "general_operand" "") 2600 (match_operand:SI 2 "register_operand" ""))) 2601 (clobber (match_scratch:HI 3 "=X"))] 2602 "reload_completed && z_replacement_completed == 2 2603 && X_REG_P (operands[2])" 2604 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3))) 2605 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM)) 2606 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))]) 2607 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4))) 2608 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5))) 2609 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM)) 2610 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))]) 2611 (set (reg:SI 0) (neg:SI (reg:SI 0)))] 2612 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]); 2613 operands[4] = m68hc11_gen_highpart (HImode, operands[1]); 2614 operands[5] = m68hc11_gen_highpart (QImode, operands[4]); 2615 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);") 2616 2617(define_split /* "*subsi3" */ 2618 [(set (match_operand:SI 0 "nonimmediate_operand" "") 2619 (minus:SI (match_operand:SI 1 "general_operand" "") 2620 (match_operand:SI 2 "general_operand" ""))) 2621 (clobber (match_scratch:HI 3 "=d"))] 2622 "reload_completed && z_replacement_completed == 2 2623 && !X_REG_P (operands[0])" 2624 [(set (match_dup 3) (match_dup 4)) 2625 (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5))) 2626 (set (match_dup 4) (match_dup 3)) 2627 (set (match_dup 3) (match_dup 6)) 2628 (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7))) 2629 (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8))) 2630 (set (match_dup 6) (match_dup 3))] 2631 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]); 2632 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]); 2633 operands[6] = m68hc11_gen_highpart (HImode, operands[1]); 2634 operands[7] = m68hc11_gen_highpart (HImode, operands[2]); 2635 operands[8] = m68hc11_gen_highpart (QImode, operands[7]); 2636 operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);") 2637 2638;; 2639;; - 16-bit Subtract. 2640;; 2641(define_expand "subhi3" 2642 [(set (match_operand:HI 0 "register_operand" "=r") 2643 (minus:HI (match_operand:HI 1 "register_operand" "0") 2644 (match_operand:HI 2 "general_operand" "g")))] 2645 "" 2646 "") 2647 2648;; 2649;; Subtract from stack. This is better if we provide a pattern. 2650;; 2651(define_insn "*subhi3_sp" 2652 [(set (match_operand:HI 0 "stack_register_operand" "=w,w") 2653 (minus:HI (match_operand:HI 1 "register_operand" "0,0") 2654 (match_operand:HI 2 "general_operand" "im*d,!u*A"))) 2655 (clobber (match_scratch:HI 3 "=A*d,A*d"))] 2656 "" 2657 "* 2658{ 2659 if (X_REG_P (operands[2])) 2660 { 2661 operands[2] = m68hc11_soft_tmp_reg; 2662 output_asm_insn (\"stx\\t%2\", operands); 2663 } 2664 else if (Y_REG_P (operands[2])) 2665 { 2666 operands[2] = m68hc11_soft_tmp_reg; 2667 output_asm_insn (\"sty\\t%2\", operands); 2668 } 2669 else if (D_REG_P (operands[2])) 2670 { 2671 operands[2] = m68hc11_soft_tmp_reg; 2672 output_asm_insn (\"std\\t%2\", operands); 2673 } 2674 2675 if (D_REG_P (operands[3])) 2676 { 2677 int save_x; 2678 2679 save_x = !dead_register_here (insn, ix_reg); 2680 if (save_x) 2681 output_asm_insn (\"xgdx\", operands); 2682 output_asm_insn (\"tsx\", operands); 2683 output_asm_insn (\"xgdx\", operands); 2684 output_asm_insn (\"subd\\t%2\", operands); 2685 output_asm_insn (\"xgdx\", operands); 2686 2687 /* The status flags correspond to the addd. xgdx/y and tx/ys do not 2688 modify the flags. */ 2689 output_asm_insn (\"txs\", operands); 2690 if (save_x) 2691 return \"xgdx\"; 2692 else 2693 return \"\"; 2694 } 2695 2696 /* Need to transfer to SP to X,Y and then to D register. 2697 Register X,Y is lost, this is specified by the (clobber) statement. */ 2698 output_asm_insn (\"ts%3\", operands); 2699 output_asm_insn (\"xgd%3\", operands); 2700 output_asm_insn (\"subd\\t%2\", operands); 2701 output_asm_insn (\"xgd%3\", operands); 2702 2703 /* The status flags correspond to the addd. xgdx/y and tx/ys do not 2704 modify the flags. */ 2705 return \"t%3s\"; 2706}") 2707 2708 2709(define_insn "*subhi3" 2710 [(set (match_operand:HI 0 "register_operand" "=d,*A,d*A") 2711 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0") 2712 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,!u")))] 2713 "" 2714 "* 2715{ 2716 /* Adding to an address register or with another/same register 2717 is not possible. This must be replaced. */ 2718 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 2719 return \"#\"; 2720 2721 return \"subd\\t%2\"; 2722}") 2723 2724(define_insn "*subhi3_zext" 2725 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d") 2726 (minus:HI (match_operand:HI 1 "hard_reg_operand" "0,0") 2727 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))] 2728 "" 2729 "* 2730{ 2731 CC_STATUS_INIT; 2732 if (A_REG_P (operands[2])) 2733 { 2734 rtx ops[2]; 2735 2736 ops[0] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 2737 ops[1] = operands[2]; 2738 m68hc11_gen_movqi (insn, ops); 2739 return \"subb\\t%T0\\n\\tsbca\\t#0\"; 2740 } 2741 return \"subb\\t%b2\\n\\tsbca\\t#0\"; 2742}") 2743 2744(define_insn "subqi3" 2745 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y") 2746 (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0") 2747 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))] 2748 "" 2749 "* 2750{ 2751 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 2752 return \"#\"; 2753 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 2754 return \"subb\\t%b2\"; 2755 else 2756 return \"suba\\t%b2\"; 2757}") 2758 2759;; 2760;; subtract with carry is used for 32-bit subtract. 2761;; 2762(define_insn "*subcq" 2763 [(set (match_operand:QI 0 "register_operand" "=q") 2764 (minus:QI (minus:QI (reg:QI CC_REGNUM) 2765 (match_operand:QI 1 "register_operand" "0")) 2766 (match_operand:QI 2 "general_operand" "ium")))] 2767 "" 2768 "sbc%0\\t%b2") 2769 2770;;-------------------------------------------------------------------- 2771;;- Multiply instructions. 2772;;-------------------------------------------------------------------- 2773;; 2774;; 32 and 64-bit multiply are handled by the library 2775;; 2776 2777(define_expand "mulsi3" 2778 [(set (match_operand:SI 0 "nonimmediate_operand" "") 2779 (mult:SI (match_operand:SI 1 "general_operand" "") 2780 (match_operand:SI 2 "general_operand" "")))] 2781 "" 2782 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands); 2783 DONE;") 2784 2785(define_expand "mulhi3" 2786 [(parallel [(set (match_operand:HI 0 "register_operand" "") 2787 (mult:HI (match_operand:HI 1 "register_operand" "") 2788 (match_operand:HI 2 "register_operand" ""))) 2789 (clobber (match_scratch:HI 3 ""))])] 2790 "" 2791 "") 2792 2793(define_insn "mulhi3_m68hc11" 2794 [(set (match_operand:HI 0 "register_operand" "=d") 2795 (mult:HI (match_operand:HI 1 "register_operand" "%0") 2796 (match_operand:HI 2 "register_operand" "x"))) 2797 (clobber (match_scratch:HI 3 "=X"))] 2798 "TARGET_M6811" 2799 "* 2800{ 2801 CC_STATUS_INIT; 2802 /* D * X -> D (X and Y are preserved by this function call). */ 2803 return \"jsr\\t___mulhi3\"; 2804}") 2805 2806(define_insn "mulhi3_m68hc12" 2807 [(set (match_operand:HI 0 "register_operand" "=d,d") 2808 (mult:HI (match_operand:HI 1 "register_operand" "%0,0") 2809 (match_operand:HI 2 "register_operand" "y,x"))) 2810 (clobber (match_scratch:HI 3 "=2,2"))] 2811 "TARGET_M6812" 2812 "* 2813{ 2814 CC_STATUS_INIT; 2815 if (X_REG_P (operands[2])) 2816 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\"; 2817 else 2818 return \"emul\"; 2819}") 2820 2821(define_insn "umulhisi3" 2822 [(set (match_operand:SI 0 "register_operand" "=D,D") 2823 (mult:SI (zero_extend:SI 2824 (match_operand:HI 1 "register_operand" "%d,d")) 2825 (zero_extend:SI 2826 (match_operand:HI 2 "register_operand" "y,x")))) 2827 (clobber (match_scratch:HI 3 "=2,X"))] 2828 "TARGET_M6812" 2829 "* 2830{ 2831 if (X_REG_P (operands [2])) 2832 output_asm_insn (\"exg\\tx,y\", operands); 2833 2834 /* Can't use the carry after that; other flags are ok when testing 2835 the 32-bit result. */ 2836 cc_status.flags |= CC_NO_OVERFLOW; 2837 return \"emul\\n\\texg\\tx,y\"; 2838}") 2839 2840(define_insn "mulhisi3" 2841 [(set (match_operand:SI 0 "register_operand" "=D,D") 2842 (mult:SI (sign_extend:SI 2843 (match_operand:HI 1 "register_operand" "%d,d")) 2844 (sign_extend:SI 2845 (match_operand:HI 2 "register_operand" "y,x")))) 2846 (clobber (match_scratch:HI 3 "=2,X"))] 2847 "TARGET_M6812" 2848 "* 2849{ 2850 if (X_REG_P (operands [2])) 2851 output_asm_insn (\"exg\\tx,y\", operands); 2852 2853 /* Can't use the carry after that; other flags are ok when testing 2854 the 32-bit result. */ 2855 cc_status.flags |= CC_NO_OVERFLOW; 2856 return \"emuls\\n\\texg\\tx,y\"; 2857}") 2858 2859(define_insn "umulqihi3" 2860 [(set (match_operand:HI 0 "register_operand" "=d") 2861 (mult:HI (zero_extend:HI 2862 (match_operand:QI 1 "nonimmediate_operand" "dm*u")) 2863 (zero_extend:HI 2864 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))] 2865 "" 2866 "* 2867{ 2868 if (D_REG_P (operands[1]) && D_REG_P (operands[2])) 2869 { 2870 output_asm_insn (\"tba\", operands); 2871 } 2872 else 2873 { 2874 rtx ops[2]; 2875 2876 if (D_REG_P (operands[2])) 2877 { 2878 rtx temp = operands[2]; 2879 operands[2] = operands[1]; 2880 operands[1] = temp; 2881 } 2882 2883 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); 2884 ops[1] = operands[2]; 2885 m68hc11_gen_movqi (insn, ops); 2886 2887 if (!D_REG_P (operands[1])) 2888 { 2889 output_asm_insn (\"ldab\\t%b1\", operands); 2890 } 2891 } 2892 2893 CC_STATUS_INIT; 2894 return \"mul\"; 2895}") 2896 2897(define_insn "mulqi3" 2898 [(set (match_operand:QI 0 "register_operand" "=d,*x,*y") 2899 (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%dum,0,0") 2900 (match_operand:QI 2 "general_operand" "dium,*xium,*yium")))] 2901 "" 2902 "* 2903{ 2904 if (A_REG_P (operands[0])) 2905 return \"#\"; 2906 2907 if (D_REG_P (operands[1]) && D_REG_P (operands[2])) 2908 { 2909 output_asm_insn (\"tba\", operands); 2910 } 2911 else 2912 { 2913 if (D_REG_P (operands[2])) 2914 { 2915 rtx temp = operands[2]; 2916 operands[2] = operands[1]; 2917 operands[1] = temp; 2918 } 2919 2920 output_asm_insn (\"ldaa\\t%b2\", operands); 2921 2922 if (!D_REG_P (operands[1])) 2923 { 2924 output_asm_insn (\"ldab\\t%b1\", operands); 2925 } 2926 } 2927 2928 CC_STATUS_INIT; 2929 return \"mul\"; 2930}") 2931 2932(define_split 2933 [(set (match_operand:QI 0 "hard_addr_reg_operand" "") 2934 (mult:QI (match_operand:QI 1 "general_operand" "") 2935 (match_operand:QI 2 "general_operand" "")))] 2936 "z_replacement_completed == 2" 2937 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3)) 2938 (set (match_dup 3) (reg:HI D_REGNUM))]) 2939 (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6))) 2940 (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) 2941 (set (match_dup 3) (reg:HI D_REGNUM))])] 2942 " 2943 operands[3] = gen_rtx (REG, HImode, REGNO (operands[0])); 2944 if (A_REG_P (operands[1])) 2945 operands[5] = gen_rtx (REG, QImode, HARD_D_REGNUM); 2946 else 2947 operands[5] = operands[1]; 2948 if (A_REG_P (operands[2])) 2949 operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM); 2950 else 2951 operands[6] = operands[2]; 2952 ") 2953 2954(define_insn "mulqihi3" 2955 [(set (match_operand:HI 0 "register_operand" "=d,d") 2956 (mult:HI (sign_extend:HI 2957 (match_operand:QI 1 "register_operand" "%0,0")) 2958 (sign_extend:HI 2959 (match_operand:QI 2 "nonimmediate_operand" "dm,*A"))))] 2960 "" 2961 "* 2962{ 2963 CC_STATUS_INIT; 2964 2965 /* Special case when multiplying the register with itself. */ 2966 if (D_REG_P (operands[2])) 2967 { 2968 output_asm_insn (\"tba\", operands); 2969 return \"mul\"; 2970 } 2971 2972 if (!H_REG_P (operands[2])) 2973 { 2974 output_asm_insn (\"ldaa\\t%b2\", operands); 2975 } 2976 else 2977 { 2978 rtx ops[2]; 2979 2980 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); 2981 ops[1] = operands[2]; 2982 m68hc11_gen_movqi (insn, ops); 2983 } 2984 return \"jsr\\t___mulqi3\"; 2985}") 2986 2987;;-------------------------------------------------------------------- 2988;;- Divide instructions. 2989;;-------------------------------------------------------------------- 2990 2991(define_insn "divmodhi4" 2992 [(set (match_operand:HI 0 "register_operand" "=d,d") 2993 (div:HI (match_operand:HI 1 "register_operand" "0,0") 2994 (match_operand:HI 2 "general_operand" "A,ium"))) 2995 (set (match_operand:HI 3 "register_operand" "=&x,&x") 2996 (mod:HI (match_dup 1) (match_dup 2)))] 2997 "" 2998 "* 2999{ 3000 if (!X_REG_P (operands[2])) 3001 { 3002 if (Y_REG_P (operands[2])) 3003 { 3004 output_asm_insn (\"sty\\t%t1\", operands); 3005 output_asm_insn (\"ldx\\t%t1\", operands); 3006 } 3007 else 3008 { 3009 output_asm_insn (\"ldx\\t%2\", operands); 3010 } 3011 } 3012 if (TARGET_M6812) 3013 { 3014 /* Flags are ok after that. */ 3015 return \"idivs\\n\\txgdx\"; 3016 } 3017 else 3018 { 3019 CC_STATUS_INIT; 3020 return \"bsr\\t__divmodhi4\"; 3021 } 3022}") 3023 3024(define_insn "udivmodhi4" 3025 [(set (match_operand:HI 0 "register_operand" "=d,d") 3026 (udiv:HI (match_operand:HI 1 "register_operand" "0,0") 3027 (match_operand:HI 2 "general_operand" "A,ium"))) 3028 (set (match_operand:HI 3 "register_operand" "=x,x") 3029 (umod:HI (match_dup 1) (match_dup 2)))] 3030 "" 3031 "* 3032{ 3033 if (!X_REG_P (operands[2])) 3034 { 3035 if (Y_REG_P (operands[2])) 3036 { 3037 output_asm_insn (\"sty\\t%t1\", operands); 3038 output_asm_insn (\"ldx\\t%t1\", operands); 3039 } 3040 else 3041 { 3042 output_asm_insn (\"ldx\\t%2\", operands); 3043 } 3044 } 3045 3046 /* Z V and C flags are set but N is unchanged. 3047 Since this is an unsigned divide, we can probably keep the flags 3048 and indicate this. */ 3049 cc_status.flags |= CC_NOT_NEGATIVE; 3050 return \"idiv\\n\\txgdx\"; 3051}") 3052 3053;;-------------------------------------------------------------------- 3054;;- and instructions. 3055;;-------------------------------------------------------------------- 3056 3057(define_insn "anddi3" 3058 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u") 3059 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu") 3060 (match_operand:DI 2 "general_operand" "imu,imu"))) 3061 (clobber (match_scratch:HI 3 "=d,d"))] 3062 "" 3063 "#") 3064 3065(define_insn "andsi3" 3066 [(set (match_operand:SI 0 "register_operand" "=D,!u") 3067 (and:SI (match_operand:SI 1 "register_operand" "%0,0") 3068 (match_operand:SI 2 "general_operand" "Dimu,imu"))) 3069 (clobber (match_scratch:HI 3 "=X,d"))] 3070 "" 3071 "#") 3072 3073(define_expand "andhi3" 3074 [(set (match_operand:HI 0 "register_operand" "") 3075 (and:HI (match_operand:HI 1 "register_operand" "") 3076 (match_operand:HI 2 "general_operand" "")))] 3077 "" 3078 "") 3079 3080(define_insn "*andhi3_mem" 3081 [(set (match_operand:HI 0 "memory_operand" "=Q,R") 3082 (and:HI (match_dup 0) 3083 (match_operand:HI 1 "immediate_operand" "i,i"))) 3084 (clobber (match_scratch:HI 2 "=xy,X"))] 3085 "TARGET_RELAX && !TARGET_M6812" 3086 "* 3087{ 3088 int val = INTVAL (operands[1]) & 0x0FFFF; 3089 3090 if (val == 0x0ffff) 3091 { 3092 cc_status = cc_prev_status; 3093 return \"\"; 3094 } 3095 3096 CC_STATUS_INIT; 3097 3098 /* The bclr instruction uses an inverted mask. */ 3099 operands[1] = GEN_INT ((~val) & 0x0FFFF); 3100 3101 /* When destination is a global variable, generate a .relax instruction 3102 and load the address in the clobber register. That load can be 3103 eliminated by the linker if the address is in page0. */ 3104 if (which_alternative == 0) 3105 { 3106 rtx ops[3]; 3107 3108 ops[0] = operands[2]; 3109 ops[1] = XEXP (operands[0], 0); 3110 ops[2] = gen_label_rtx (); 3111 output_asm_insn (\".relax\\t%l2\", ops); 3112 m68hc11_gen_movhi (insn, ops); 3113 if ((val & 0x0FF) != 0x0FF) 3114 output_asm_insn (\"bclr\\t1,%2, %b1\", operands); 3115 3116 if ((val & 0x0FF00) != 0x0FF00) 3117 output_asm_insn (\"bclr\\t0,%2, %h1\", operands); 3118 3119 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 3120 CODE_LABEL_NUMBER (ops[2])); 3121 return \"\"; 3122 } 3123 3124 if ((val & 0x0FF) != 0x0FF) 3125 output_asm_insn (\"bclr\\t%b0, %b1\", operands); 3126 3127 if ((val & 0x0FF00) != 0x0FF00) 3128 output_asm_insn (\"bclr\\t%h0, %h1\", operands); 3129 3130 return \"\"; 3131}") 3132 3133(define_insn "*andhi3_const" 3134 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A") 3135 (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0") 3136 (match_operand:HI 2 "const_int_operand" "")))] 3137 "" 3138 "* 3139{ 3140 int val = INTVAL (operands[2]) & 0x0FFFF; 3141 int lowpart_zero = 0; 3142 int highpart_zero = 0; 3143 int lowpart_unknown = 0; 3144 int highpart_unknown = 0; 3145 3146 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3147 return \"#\"; 3148 3149 if (val == 0x0ffff) 3150 { 3151 cc_status = cc_prev_status; 3152 return \"\"; 3153 } 3154 3155 /* First, try to clear the low and high part. 3156 If that's possible, the second 'and' will give 3157 the good status flags and we can avoid a tsthi. */ 3158 if ((val & 0x0FF) == 0) 3159 { 3160 if (D_REG_P (operands[0])) 3161 output_asm_insn (\"clrb\", operands); 3162 else 3163 output_asm_insn (\"clr\\t%b0\", operands); 3164 lowpart_zero = 1; 3165 } 3166 if ((val & 0x0FF00) == 0) 3167 { 3168 if (D_REG_P (operands[0])) 3169 output_asm_insn (\"clra\", operands); 3170 else 3171 output_asm_insn (\"clr\\t%h0\", operands); 3172 highpart_zero = 1; 3173 } 3174 3175 if ((val & 0x0FF) == 0x0FF) 3176 { 3177 lowpart_unknown = 1; 3178 } 3179 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0])) 3180 { 3181 rtx ops[2]; 3182 3183 ops[0] = operands[0]; 3184 ops[1] = GEN_INT ((~val) & 0x0FF); 3185 output_asm_insn (\"bclr\\t%b0, %1\", ops); 3186 } 3187 else if ((val & 0x0FF) != 0) 3188 { 3189 output_asm_insn (\"andb\\t%b2\", operands); 3190 } 3191 3192 if ((val & 0x0FF00) == 0x0FF00) 3193 { 3194 highpart_unknown = 1; 3195 } 3196 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0])) 3197 { 3198 rtx ops[2]; 3199 3200 ops[0] = operands[0]; 3201 ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8); 3202 output_asm_insn (\"bclr\\t%h0, %1\", ops); 3203 } 3204 else if ((val & 0x0FF00) != 0) 3205 { 3206 output_asm_insn (\"anda\\t%h2\", operands); 3207 } 3208 3209 if (highpart_unknown || lowpart_unknown) 3210 CC_STATUS_INIT; 3211 else if (highpart_zero == 0 && lowpart_zero == 0) 3212 CC_STATUS_INIT; 3213 3214 return \"\"; 3215}") 3216 3217(define_insn "*andhi3_gen" 3218 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") 3219 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0") 3220 (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))] 3221 "" 3222 "* 3223{ 3224 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3225 return \"#\"; 3226 3227 CC_STATUS_INIT; 3228 return \"anda\\t%h2\\n\\tandb\\t%b2\"; 3229}") 3230 3231(define_expand "andqi3" 3232 [(set (match_operand:QI 0 "register_operand" "") 3233 (and:QI (match_operand:QI 1 "register_operand" "") 3234 (match_operand:QI 2 "general_operand" "")))] 3235 "" 3236 "") 3237 3238(define_insn "*andqi3_mem" 3239 [(set (match_operand:QI 0 "memory_operand" "=Q,R") 3240 (and:QI (match_dup 0) 3241 (match_operand:QI 1 "const_int_operand" "i,i"))) 3242 (clobber (match_scratch:HI 2 "=xy,X"))] 3243 "TARGET_RELAX && !TARGET_M6812" 3244 "* 3245{ 3246 int val = INTVAL (operands[1]) & 0x0FF; 3247 3248 if (val == 0x0ff) 3249 { 3250 cc_status = cc_prev_status; 3251 return \"\"; 3252 } 3253 3254 /* The bclr instruction uses an inverted mask. */ 3255 operands[1] = GEN_INT ((~val) & 0x0FF); 3256 3257 /* When destination is a global variable, generate a .relax instruction 3258 and load the address in the clobber register. That load can be 3259 eliminated by the linker if the address is in page0. */ 3260 if (which_alternative == 0) 3261 { 3262 rtx ops[3]; 3263 3264 ops[0] = operands[2]; 3265 ops[1] = XEXP (operands[0], 0); 3266 ops[2] = gen_label_rtx (); 3267 output_asm_insn (\".relax\\t%l2\", ops); 3268 m68hc11_gen_movhi (insn, ops); 3269 output_asm_insn (\"bclr\\t0,%2, %1\", operands); 3270 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 3271 CODE_LABEL_NUMBER (ops[2])); 3272 return \"\"; 3273 } 3274 return \"bclr\\t%b0, %1\"; 3275}") 3276 3277(define_insn "*andqi3_const" 3278 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q") 3279 (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0") 3280 (match_operand:QI 2 "const_int_operand" "")))] 3281 "" 3282 "* 3283{ 3284 int val = INTVAL (operands[2]) & 0x0FF; 3285 3286 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3287 return \"#\"; 3288 3289 if (val == 0x0ff) 3290 { 3291 cc_status = cc_prev_status; 3292 return \"\"; 3293 } 3294 if (!H_REG_P (operands[0])) 3295 { 3296 rtx ops[2]; 3297 3298 ops[0] = operands[0]; 3299 ops[1] = GEN_INT ((~val) & 0x0FF); 3300 output_asm_insn (\"bclr\\t%b0, %b1\", ops); 3301 return \"\"; 3302 } 3303 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 3304 return \"andb\\t%b2\"; 3305 else if (DA_REG_P (operands[0])) 3306 return \"anda\\t%b2\"; 3307 else 3308 fatal_insn (\"Invalid operand in the instruction\", insn); 3309}") 3310 3311(define_insn "*andqi3_gen" 3312 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") 3313 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") 3314 (match_operand:QI 2 "general_operand" "mi,!u,?*A,!um,?*A*d,!um*A")))] 3315 "" 3316 "* 3317{ 3318 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3319 return \"#\"; 3320 3321 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 3322 return \"andb\\t%b2\"; 3323 else if (DA_REG_P (operands[0])) 3324 return \"anda\\t%b2\"; 3325 else 3326 fatal_insn (\"Invalid operand in the instruction\", insn); 3327}") 3328 3329;;-------------------------------------------------------------------- 3330;;- Bit set or instructions. 3331;;-------------------------------------------------------------------- 3332 3333(define_insn "iordi3" 3334 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u") 3335 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu") 3336 (match_operand:DI 2 "general_operand" "imu,imu"))) 3337 (clobber (match_scratch:HI 3 "=d,d"))] 3338 "" 3339 "#") 3340 3341(define_insn "iorsi3" 3342 [(set (match_operand:SI 0 "register_operand" "=D,!u") 3343 (ior:SI (match_operand:SI 1 "register_operand" "%0,0") 3344 (match_operand:SI 2 "general_operand" "Dimu,imu"))) 3345 (clobber (match_scratch:HI 3 "=X,d"))] 3346 "" 3347 "#") 3348 3349(define_expand "iorhi3" 3350 [(set (match_operand:HI 0 "register_operand" "") 3351 (ior:HI (match_operand:HI 1 "register_operand" "") 3352 (match_operand:HI 2 "general_operand" "")))] 3353 "" 3354 "") 3355 3356(define_insn "*iorhi3_mem" 3357 [(set (match_operand:HI 0 "memory_operand" "=Q,R") 3358 (ior:HI (match_dup 0) 3359 (match_operand:HI 1 "const_int_operand" ""))) 3360 (clobber (match_scratch:HI 2 "=xy,X"))] 3361 "TARGET_RELAX && !TARGET_M6812" 3362 "* 3363{ 3364 int val = INTVAL (operands[1]) & 0x0FFFF; 3365 3366 if (val == 0) 3367 { 3368 cc_status = cc_prev_status; 3369 return \"\"; 3370 } 3371 CC_STATUS_INIT; 3372 if (which_alternative == 0) 3373 { 3374 rtx ops[3]; 3375 3376 ops[0] = operands[2]; 3377 ops[1] = XEXP (operands[0], 0); 3378 ops[2] = gen_label_rtx (); 3379 output_asm_insn (\".relax\\t%l2\", ops); 3380 m68hc11_gen_movhi (insn, ops); 3381 if ((val & 0x0FF) != 0) 3382 output_asm_insn (\"bset\\t1,%2, %b1\", operands); 3383 3384 if ((val & 0x0FF00) != 0) 3385 output_asm_insn (\"bset\\t0,%2, %h1\", operands); 3386 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 3387 CODE_LABEL_NUMBER (ops[2])); 3388 return \"\"; 3389 } 3390 3391 if ((val & 0x0FF) != 0) 3392 output_asm_insn (\"bset\\t%b0, %b1\", operands); 3393 3394 if ((val & 0x0FF00) != 0) 3395 output_asm_insn (\"bset\\t%h0, %h1\", operands); 3396 3397 return \"\"; 3398}") 3399 3400(define_insn "*iorhi3_const" 3401 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A") 3402 (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0") 3403 (match_operand:HI 2 "const_int_operand" "")))] 3404 "" 3405 "* 3406{ 3407 int val = INTVAL (operands[2]) & 0x0FFFF; 3408 3409 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3410 return \"#\"; 3411 3412 if (val == 0) 3413 { 3414 cc_status = cc_prev_status; 3415 return \"\"; 3416 } 3417 3418 if ((val & 0x0FF) != 0) 3419 { 3420 if (!H_REG_P (operands[0])) 3421 output_asm_insn (\"bset\\t%b0, %b2\", operands); 3422 else 3423 output_asm_insn (\"orab\\t%b2\", operands); 3424 } 3425 3426 if ((val & 0x0FF00) != 0) 3427 { 3428 if (!H_REG_P (operands[0])) 3429 output_asm_insn (\"bset\\t%h0, %h2\", operands); 3430 else 3431 output_asm_insn (\"oraa\\t%h2\", operands); 3432 } 3433 3434 CC_STATUS_INIT; 3435 return \"\"; 3436}") 3437 3438(define_insn "*iorhi3_gen" 3439 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") 3440 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0") 3441 (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))] 3442 "" 3443 "* 3444{ 3445 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3446 return \"#\"; 3447 3448 CC_STATUS_INIT; 3449 return \"oraa\\t%h2\\n\\torab\\t%b2\"; 3450}") 3451 3452(define_expand "iorqi3" 3453 [(set (match_operand:QI 0 "register_operand" "") 3454 (ior:QI (match_operand:QI 1 "register_operand" "") 3455 (match_operand:QI 2 "general_operand" "")))] 3456 "" 3457 "") 3458 3459(define_insn "*iorqi3_mem" 3460 [(set (match_operand:QI 0 "memory_operand" "=Q,R") 3461 (ior:QI (match_dup 0) 3462 (match_operand:QI 1 "const_int_operand" ""))) 3463 (clobber (match_scratch:HI 2 "=xy,X"))] 3464 "TARGET_RELAX && !TARGET_M6812" 3465 "* 3466{ 3467 int val = INTVAL (operands[1]) & 0x0FF; 3468 3469 if (val == 0) 3470 { 3471 cc_status = cc_prev_status; 3472 return \"\"; 3473 } 3474 if (which_alternative == 0) 3475 { 3476 rtx ops[3]; 3477 3478 ops[0] = operands[2]; 3479 ops[1] = XEXP (operands[0], 0); 3480 ops[2] = gen_label_rtx (); 3481 output_asm_insn (\".relax\\t%l2\", ops); 3482 m68hc11_gen_movhi (insn, ops); 3483 output_asm_insn (\"bset\\t0,%2, %1\", operands); 3484 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 3485 CODE_LABEL_NUMBER (ops[2])); 3486 return \"\"; 3487 } 3488 return \"bset\\t%b0, %1\"; 3489}") 3490 3491(define_insn "*iorqi3_const" 3492 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q") 3493 (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0") 3494 (match_operand:QI 2 "const_int_operand" "")))] 3495 "" 3496 "* 3497{ 3498 int val = INTVAL (operands[2]) & 0x0FF; 3499 3500 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3501 return \"#\"; 3502 3503 if (val == 0) 3504 { 3505 cc_status = cc_prev_status; 3506 return \"\"; 3507 } 3508 if (!H_REG_P (operands[0])) 3509 { 3510 return \"bset\\t%b0, %2\"; 3511 } 3512 3513 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 3514 return \"orab\\t%b2\"; 3515 else if (DA_REG_P (operands[0])) 3516 return \"oraa\\t%b2\"; 3517 else 3518 fatal_insn (\"Invalid operand in the instruction\", insn); 3519}") 3520 3521(define_insn "*iorqi3_gen" 3522 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") 3523 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") 3524 (match_operand:QI 2 "general_operand" "mi,!u,!*A,!um,?*A*d,!um*A")))] 3525 "" 3526 "* 3527{ 3528 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3529 return \"#\"; 3530 3531 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 3532 return \"orab\\t%b2\"; 3533 else if (DA_REG_P (operands[0])) 3534 return \"oraa\\t%b2\"; 3535 else 3536 fatal_insn (\"Invalid operand in the instruction\", insn); 3537}") 3538 3539 3540;;-------------------------------------------------------------------- 3541;;- xor instructions. 3542;;-------------------------------------------------------------------- 3543 3544(define_insn "xordi3" 3545 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u") 3546 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu") 3547 (match_operand:DI 2 "general_operand" "imu,imu"))) 3548 (clobber (match_scratch:HI 3 "=d,d"))] 3549 "" 3550 "#") 3551 3552(define_insn "xorsi3" 3553 [(set (match_operand:SI 0 "register_operand" "=D,!u") 3554 (xor:SI (match_operand:SI 1 "register_operand" "%0,0") 3555 (match_operand:SI 2 "general_operand" "Dimu,imu"))) 3556 (clobber (match_scratch:HI 3 "=X,d"))] 3557 "" 3558 "#") 3559 3560(define_insn "xorhi3" 3561 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") 3562 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0") 3563 (match_operand:HI 2 "general_operand" "im,!u*A,!ium*A")))] 3564 "" 3565 "* 3566{ 3567 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3568 return \"#\"; 3569 3570 if (GET_CODE (operands[2]) == CONST_INT) 3571 { 3572 int val = INTVAL (operands[2]) & 0x0FFFF; 3573 3574 if (val == 0) 3575 { 3576 cc_status = cc_prev_status; 3577 return \"\"; 3578 } 3579 if ((val & 0x0FF) != 0) 3580 { 3581 output_asm_insn (\"eorb\\t%b2\", operands); 3582 } 3583 else if ((val & 0x0FF) == 0x0FF) 3584 { 3585 output_asm_insn (\"comb\", operands); 3586 } 3587 3588 if ((val & 0x0FF00) != 0) 3589 { 3590 output_asm_insn (\"eora\\t%h2\", operands); 3591 } 3592 else if ((val & 0x0FF00) == 0x0FF00) 3593 { 3594 output_asm_insn (\"coma\", operands); 3595 } 3596 3597 CC_STATUS_INIT; 3598 return \"\"; 3599 } 3600 3601 CC_STATUS_INIT; 3602 return \"eora\\t%h2\\n\\teorb\\t%b2\"; 3603}") 3604 3605(define_insn "xorqi3" 3606 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") 3607 (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") 3608 (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))] 3609 "" 3610 "* 3611{ 3612 if (A_REG_P (operands[0]) || H_REG_P (operands[2])) 3613 return \"#\"; 3614 3615 if (GET_CODE (operands[2]) == CONST_INT) 3616 { 3617 int val = INTVAL (operands[2]) & 0x0FF; 3618 3619 if (val == 0) 3620 { 3621 cc_status = cc_prev_status; 3622 return \"\"; 3623 } 3624 if (val == 0x0FF) 3625 { 3626 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 3627 return \"comb\"; 3628 else 3629 return \"coma\"; 3630 } 3631 } 3632 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 3633 return \"eorb\\t%b2\"; 3634 else if (DA_REG_P (operands[0])) 3635 return \"eora\\t%b2\"; 3636 else 3637 fatal_insn (\"Invalid operand in the instruction\", insn); 3638}") 3639 3640;;-------------------------------------------------------------------- 3641;;- Bit set or instructions. 3642;;-------------------------------------------------------------------- 3643 3644(define_insn "*logicalsi3_zexthi" 3645 [(set (match_operand:SI 0 "register_operand" "=D") 3646 (match_operator:SI 3 "m68hc11_logical_operator" 3647 [(zero_extend:SI 3648 (match_operand:HI 1 "general_operand" "imudA")) 3649 (match_operand:SI 2 "general_operand" "Dimu")]))] 3650 "" 3651 "#") 3652 3653(define_insn "*logicalsi3_zextqi" 3654 [(set (match_operand:SI 0 "register_operand" "=D,D,D") 3655 (match_operator:SI 3 "m68hc11_logical_operator" 3656 [(zero_extend:SI 3657 (match_operand:QI 1 "general_operand" "d,*A,imu")) 3658 (match_operand:SI 2 "general_operand" "imu,imu,0")]))] 3659 "" 3660 "#") 3661 3662(define_split /* logicalsi3_zextqi */ 3663 [(set (match_operand:SI 0 "register_operand" "") 3664 (match_operator:SI 3 "m68hc11_logical_operator" 3665 [(zero_extend:SI 3666 (match_operand:QI 1 "general_operand" "")) 3667 (match_operand:SI 2 "general_operand" "")]))] 3668 "z_replacement_completed == 2" 3669 [(set (reg:QI A_REGNUM) (match_dup 4)) 3670 (set (reg:QI D_REGNUM) (match_dup 7)) 3671 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)])) 3672 (set (reg:HI X_REGNUM) (match_dup 6))] 3673 "PUT_MODE (operands[3], QImode); 3674 if (X_REG_P (operands[2])) 3675 { 3676 operands[5] = operands[1]; 3677 /* Make all the (set (REG:x) (REG:y)) a nop set. */ 3678 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM); 3679 operands[7] = gen_rtx (REG, QImode, HARD_D_REGNUM); 3680 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM); 3681 } 3682 else 3683 { 3684 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]); 3685 operands[7] = operands[1]; 3686 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]); 3687 operands[4] = m68hc11_gen_highpart (QImode, operands[4]); 3688 operands[6] = m68hc11_gen_highpart (HImode, operands[2]); 3689 } 3690 /* For an AND, make sure the high 24-bit part is cleared. */ 3691 if (GET_CODE (operands[3]) == AND) 3692 { 3693 operands[4] = const0_rtx; 3694 operands[6] = const0_rtx; 3695 } 3696 ") 3697 3698(define_split /* logicalsi3_zexthi */ 3699 [(set (match_operand:SI 0 "register_operand" "") 3700 (match_operator:SI 3 "m68hc11_logical_operator" 3701 [(zero_extend:SI 3702 (match_operand:HI 1 "general_operand" "")) 3703 (match_operand:SI 2 "general_operand" "")]))] 3704 "reload_completed" 3705 [(set (reg:HI D_REGNUM) (match_dup 4)) 3706 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)])) 3707 (set (reg:HI X_REGNUM) (match_dup 6))] 3708 "PUT_MODE (operands[3], HImode); 3709 if (X_REG_P (operands[2])) 3710 { 3711 operands[5] = operands[1]; 3712 /* Make all the (set (REG:x) (REG:y)) a nop set. */ 3713 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM); 3714 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM); 3715 } 3716 else 3717 { 3718 operands[4] = operands[1]; 3719 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]); 3720 operands[6] = m68hc11_gen_highpart (HImode, operands[2]); 3721 } 3722 /* For an AND, make sure the high 16-bit part is cleared. */ 3723 if (GET_CODE (operands[3]) == AND) 3724 { 3725 operands[6] = const0_rtx; 3726 } 3727 ") 3728 3729(define_insn "*logicalhi3_zexthi_ashift8" 3730 [(set (match_operand:HI 0 "register_operand" "=d") 3731 (match_operator:HI 3 "m68hc11_logical_operator" 3732 [(zero_extend:HI 3733 (match_operand:QI 1 "general_operand" "imud")) 3734 (ashift:HI 3735 (match_operand:HI 2 "general_operand" "dimu") 3736 (const_int 8))]))] 3737 "" 3738 "#") 3739 3740(define_insn "*logicalhi3_zexthi" 3741 [(set (match_operand:HI 0 "register_operand" "=d,d") 3742 (match_operator:HI 3 "m68hc11_logical_operator" 3743 [(zero_extend:HI 3744 (match_operand:QI 1 "general_operand" "imd*A,?u")) 3745 (match_operand:HI 2 "general_operand" "dim,?dimu")]))] 3746 "" 3747 "#") 3748 3749(define_split /* logicalhi3_zexthi */ 3750 [(set (match_operand:HI 0 "register_operand" "") 3751 (match_operator:HI 3 "m68hc11_logical_operator" 3752 [(zero_extend:HI 3753 (match_operand:QI 1 "general_operand" "")) 3754 (match_operand:HI 2 "general_operand" "")]))] 3755 "z_replacement_completed == 2" 3756 [(set (reg:QI B_REGNUM) (match_dup 6)) 3757 (set (reg:QI A_REGNUM) (match_dup 4)) 3758 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))] 3759 " 3760 PUT_MODE (operands[3], QImode); 3761 if (D_REG_P (operands[2])) 3762 { 3763 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM); 3764 operands[5] = operands[1]; 3765 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM); 3766 } 3767 else 3768 { 3769 operands[4] = m68hc11_gen_highpart (QImode, operands[2]); 3770 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]); 3771 if (D_REG_P (operands[1])) 3772 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM); 3773 else 3774 operands[6] = operands[1]; 3775 } 3776 /* For an AND, make sure the high 8-bit part is cleared. */ 3777 if (GET_CODE (operands[3]) == AND) 3778 { 3779 operands[4] = const0_rtx; 3780 } 3781 ") 3782 3783(define_split /* logicalhi3_zexthi_ashift8 */ 3784 [(set (match_operand:HI 0 "register_operand" "") 3785 (match_operator:HI 3 "m68hc11_logical_operator" 3786 [(zero_extend:HI 3787 (match_operand:QI 1 "general_operand" "")) 3788 (ashift:HI 3789 (match_operand:HI 2 "general_operand" "") 3790 (const_int 8))]))] 3791 "z_replacement_completed == 2" 3792 [(set (reg:QI A_REGNUM) (match_dup 4)) 3793 (set (reg:QI B_REGNUM) (match_dup 5))] 3794 " 3795 if (GET_CODE (operands[3]) == AND) 3796 { 3797 emit_insn (gen_movhi (operands[0], const0_rtx)); 3798 DONE; 3799 } 3800 else 3801 { 3802 operands[5] = operands[1]; 3803 if (D_REG_P (operands[2])) 3804 { 3805 operands[4] = gen_rtx (REG, QImode, HARD_B_REGNUM); 3806 } 3807 else 3808 { 3809 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]); 3810 } 3811 } 3812 ") 3813 3814(define_insn "*logicalsi3_silshr16" 3815 [(set (match_operand:SI 0 "register_operand" "=D,D,D") 3816 (match_operator:SI 3 "m68hc11_logical_operator" 3817 [(lshiftrt:SI 3818 (match_operand:SI 1 "general_operand" "uim,uim,?D") 3819 (const_int 16)) 3820 (match_operand:SI 2 "general_operand" "uim,0,0")]))] 3821 "" 3822 "#") 3823 3824(define_split /* logicalsi3_silshr16 */ 3825 [(set (match_operand:SI 0 "register_operand" "") 3826 (match_operator:SI 3 "m68hc11_logical_operator" 3827 [(lshiftrt:SI 3828 (match_operand:SI 1 "general_operand" "") 3829 (const_int 16)) 3830 (match_operand:SI 2 "general_operand" "")]))] 3831 "reload_completed" 3832 [(set (reg:HI D_REGNUM) (match_dup 4)) 3833 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)])) 3834 (set (reg:HI X_REGNUM) (match_dup 6))] 3835 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]); 3836 if (X_REG_P (operands[2])) 3837 { 3838 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM); 3839 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM); 3840 } 3841 else 3842 { 3843 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]); 3844 operands[6] = m68hc11_gen_highpart (HImode, operands[2]); 3845 } 3846 PUT_MODE (operands[3], HImode); 3847 3848 /* For an AND, make sure the high 16-bit part is cleared. */ 3849 if (GET_CODE (operands[3]) == AND) 3850 { 3851 operands[6] = const0_rtx; 3852 } 3853") 3854 3855(define_insn "*logicalsi3_silshl16" 3856 [(set (match_operand:SI 0 "register_operand" "=D,D") 3857 (match_operator:SI 3 "m68hc11_logical_operator" 3858 [(ashift:SI 3859 (match_operand:SI 1 "general_operand" "uim,?D") 3860 (const_int 16)) 3861 (match_operand:SI 2 "general_operand" "0,0")]))] 3862 "" 3863 "#") 3864 3865(define_split /* logicalsi3_silshl16 */ 3866 [(set (match_operand:SI 0 "register_operand" "") 3867 (match_operator:SI 3 "m68hc11_logical_operator" 3868 [(ashift:SI 3869 (match_operand:SI 1 "general_operand" "") 3870 (const_int 16)) 3871 (match_operand:SI 2 "general_operand" "")]))] 3872 "z_replacement_completed == 2" 3873 [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)])) 3874 (set (reg:HI D_REGNUM) (match_dup 5))] 3875 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]); 3876 PUT_MODE (operands[3], HImode); 3877 3878 if (GET_CODE (operands[3]) == AND) 3879 operands[5] = const0_rtx; 3880 else 3881 operands[5] = gen_rtx (REG, HImode, HARD_D_REGNUM); 3882 ") 3883 3884 3885;;-------------------------------------------------------------------- 3886;;- 64/32-bit Logical Operations. Patterns are defined so that GCC 3887;; can optimize correctly. These insns are split by the `final' 3888;; pass (# pattern). They are split to fall in the corresponding 3889;; 16-bit logical patterns. 3890;;-------------------------------------------------------------------- 3891 3892;; Split 64-bit logical operations: anddi3, iordi3, xordi3 3893(define_split 3894 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "") 3895 (match_operator:DI 4 "m68hc11_logical_operator" 3896 [(match_operand:DI 1 "reg_or_some_mem_operand" "") 3897 (match_operand:DI 2 "general_operand" "")])) 3898 (clobber (match_scratch:HI 3 ""))] 3899 "reload_completed" 3900 [(const_int 0)] 3901 "m68hc11_split_logical (SImode, GET_CODE (operands[4]), operands); 3902 DONE;") 3903 3904;; Split 32-bit logical operations: andsi3, iorsi3, xorsi3 3905(define_split 3906 [(set (match_operand:SI 0 "register_operand" "") 3907 (match_operator:SI 3 "m68hc11_logical_operator" 3908 [(match_operand:SI 1 "register_operand" "") 3909 (match_operand:SI 2 "general_operand" "")]))] 3910 "0 && reload_completed" 3911 [(const_int 0)] 3912 "m68hc11_split_logical (HImode, GET_CODE (operands[3]), operands); 3913 DONE;") 3914 3915;; Split 32-bit logical operations: andsi3, iorsi3, xorsi3 3916(define_split 3917 [(set (match_operand:SI 0 "reg_or_some_mem_operand" "") 3918 (match_operator:SI 4 "m68hc11_logical_operator" 3919 [(match_operand:SI 1 "reg_or_some_mem_operand" "") 3920 (match_operand:SI 2 "general_operand" "")])) 3921 (clobber (match_scratch:HI 3 ""))] 3922 "reload_completed" 3923 [(const_int 0)] 3924 "m68hc11_split_logical (HImode, GET_CODE (operands[4]), operands); 3925 DONE;") 3926 3927;;-------------------------------------------------------------------- 3928;; 16-bit Arithmetic and logical operations on X and Y: 3929;; 3930;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT 3931;; 3932;; Operations on X or Y registers are split here. Instructions are 3933;; changed into: 3934;; - xgdx/xgdy instruction pattern, 3935;; - The same operation on register D, 3936;; - xgdx/xgdy instruction pattern. 3937;; This should allow the peephole to merge consecutive xgdx/xgdy instructions. 3938;; We also handle the case were the address register is used in both source 3939;; operands, such as: 3940;; 3941;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X)))) 3942;; or 3943;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X))) 3944;; 3945;; 3946(define_split 3947 [(set (match_operand:HI 0 "hard_addr_reg_operand" "") 3948 (match_operator:HI 3 "m68hc11_arith_operator" 3949 [(match_operand:HI 1 "hard_addr_reg_operand" "") 3950 (match_operand:HI 2 "general_operand" "")]))] 3951 "z_replacement_completed == 2 3952 /* If we are adding a small constant to X or Y, it's 3953 better to use one or several inx/iny instructions. */ 3954 && !(GET_CODE (operands[3]) == PLUS 3955 && ((TARGET_M6812 3956 && (immediate_operand (operands[2], HImode) 3957 || hard_reg_operand (operands[2], HImode))) 3958 || (GET_CODE (operands[2]) == CONST_INT 3959 && INTVAL (operands[2]) >= -4 3960 && INTVAL (operands[2]) <= 4)))" 3961 [(set (match_dup 9) (match_dup 0)) 3962 (set (match_dup 4) (match_dup 5)) 3963 (set (match_dup 8) (match_dup 7)) 3964 (set (match_dup 0) (match_dup 1)) 3965 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 3966 (set (match_dup 0) (reg:HI D_REGNUM))]) 3967 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)])) 3968 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 3969 (set (match_dup 0) (reg:HI D_REGNUM))])] 3970 " 3971 operands[9] = operands[0]; 3972 /* For 68HC12, push the value on the stack and do the operation 3973 with a pop. */ 3974 if (TARGET_M6812 3975 && m68hc11_non_shift_operator (operands[3], HImode) 3976 && (H_REG_P (operands[2]) 3977 || (m68hc11_small_indexed_indirect_p (operands[2], HImode) 3978 && reg_mentioned_p (operands[0], operands[2])))) 3979 { 3980 operands[4] = gen_rtx (MEM, HImode, 3981 gen_rtx (PRE_DEC, HImode, 3982 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 3983 operands[6] = gen_rtx (MEM, HImode, 3984 gen_rtx (POST_INC, HImode, 3985 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 3986 operands[5] = operands[2]; 3987 operands[8] = operands[7] = operands[0]; 3988 } 3989 /* Save the operand2 in a temporary location and use it. */ 3990 else if ((H_REG_P (operands[2]) 3991 || reg_mentioned_p (operands[0], operands[2])) 3992 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS)) 3993 { 3994 if (GET_CODE (operands[3]) == MINUS 3995 && reg_mentioned_p (operands[0], operands[2])) 3996 { 3997 operands[9] = gen_rtx (MEM, HImode, 3998 gen_rtx (PRE_DEC, HImode, 3999 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 4000 operands[1] = gen_rtx (MEM, HImode, 4001 gen_rtx (POST_INC, HImode, 4002 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 4003 operands[8] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 4004 operands[4] = operands[7] = operands[0]; 4005 operands[6] = operands[8]; 4006 operands[5] = operands[2]; 4007 } 4008 else 4009 { 4010 operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 4011 operands[6] = operands[4]; 4012 if (!H_REG_P (operands[2])) 4013 { 4014 operands[5] = operands[0]; 4015 operands[7] = operands[2]; 4016 operands[8] = operands[0]; 4017 } 4018 else 4019 { 4020 operands[5] = operands[2]; 4021 operands[8] = operands[7] = operands[0]; 4022 } 4023 } 4024 } 4025 else 4026 { 4027 operands[4] = operands[5] = operands[0]; 4028 operands[6] = operands[2]; 4029 operands[8] = operands[7] = operands[0]; 4030 } 4031 ") 4032 4033(define_split 4034 [(set (match_operand:HI 0 "hard_addr_reg_operand" "") 4035 (match_operator:HI 3 "m68hc11_arith_operator" 4036 [(match_operand:HI 1 "general_operand" "") 4037 (match_operand:HI 2 "general_operand" "")]))] 4038 "z_replacement_completed == 2 4039 /* If we are adding a small constant to X or Y, it's 4040 better to use one or several inx/iny instructions. */ 4041 && !(GET_CODE (operands[3]) == PLUS 4042 && ((TARGET_M6812 4043 && (immediate_operand (operands[2], HImode) 4044 || hard_reg_operand (operands[2], HImode))) 4045 || (GET_CODE (operands[2]) == CONST_INT 4046 && INTVAL (operands[2]) >= -4 4047 && INTVAL (operands[2]) <= 4)))" 4048 [(set (match_dup 0) (match_dup 1)) 4049 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 4050 (set (match_dup 0) (reg:HI D_REGNUM))]) 4051 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)])) 4052 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 4053 (set (match_dup 0) (reg:HI D_REGNUM))])] 4054 " 4055 ") 4056 4057;; 4058;; Next split handles the logical operations on D register with 4059;; another hard register for the second operand. For this, we 4060;; have to save the second operand in a scratch location and use 4061;; it instead. This must be supported because in some (rare) cases 4062;; the second operand can come in a hard register and the reload 4063;; pass doesn't know how to reload it in a memory location. 4064;; 4065;; PLUS MINUS AND IOR XOR 4066;; 4067;; The shift operators are special and must not appear here. 4068;; 4069(define_split 4070 [(set (match_operand:HI 0 "d_register_operand" "") 4071 (match_operator:HI 3 "m68hc11_non_shift_operator" 4072 [(match_operand:HI 1 "d_register_operand" "") 4073 (match_operand:HI 2 "hard_reg_operand" "")]))] 4074 "TARGET_M6811 4075 && z_replacement_completed == 2 && !SP_REG_P (operands[2])" 4076 [(set (match_dup 4) (match_dup 2)) 4077 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))] 4078 "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);") 4079 4080;; 4081;; For 68HC12, push the operand[2] value on the stack and do the 4082;; logical/arithmetic operation with a pop. 4083;; 4084(define_split 4085 [(set (match_operand:HI 0 "d_register_operand" "") 4086 (match_operator:HI 3 "m68hc11_non_shift_operator" 4087 [(match_operand:HI 1 "d_register_operand" "") 4088 (match_operand:HI 2 "hard_reg_operand" "")]))] 4089 "TARGET_M6812 4090 && z_replacement_completed == 2 && !SP_REG_P (operands[2])" 4091 [(set (match_dup 4) (match_dup 2)) 4092 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))] 4093 "operands[4] = gen_rtx (MEM, HImode, 4094 gen_rtx (PRE_DEC, HImode, 4095 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 4096 operands[5] = gen_rtx (MEM, HImode, 4097 gen_rtx (POST_INC, HImode, 4098 gen_rtx (REG, HImode, HARD_SP_REGNUM))); 4099 ") 4100 4101;;-------------------------------------------------------------------- 4102;; 16-bit Unary operations on X and Y: 4103;; 4104;; NOT NEG 4105;; 4106;; Operations on X or Y registers are split here. Instructions are 4107;; changed into: 4108;; - xgdx/xgdy instruction pattern, 4109;; - The same operation on register D, 4110;; - xgdx/xgdy instruction pattern. 4111;; This should allow the peephole to merge consecutive xgdx/xgdy instructions. 4112;; We also handle the case were the address register is used in both source 4113;; operands, such as: 4114;; 4115;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X)))) 4116;; or 4117;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X))) 4118;; 4119(define_split 4120 [(set (match_operand:HI 0 "hard_addr_reg_operand" "") 4121 (match_operator:HI 2 "m68hc11_unary_operator" 4122 [(match_operand 1 "general_operand" "")]))] 4123 "z_replacement_completed == 2" 4124 [(set (match_dup 4) (match_dup 5)) 4125 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 4126 (set (match_dup 0) (reg:HI D_REGNUM))]) 4127 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)])) 4128 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 4129 (set (match_dup 0) (reg:HI D_REGNUM))])] 4130 " 4131{ 4132 if ((H_REG_P (operands[1]) 4133 && !rtx_equal_p (operands[0], operands[1])) 4134 || reg_mentioned_p (operands[0], operands[1])) 4135 { 4136 /* Move to the destination register, before the xgdx. */ 4137 operands[4] = gen_rtx (REG, GET_MODE (operands[1]), 4138 REGNO (operands[0])); 4139 operands[5] = operands[1]; 4140 4141 /* Apply the operation on D. */ 4142 operands[3] = gen_rtx (REG, GET_MODE (operands[1]), HARD_D_REGNUM); 4143 } 4144 else 4145 { 4146 /* Generate a copy to same register (nop). */ 4147 operands[4] = operands[5] = operands[0]; 4148 operands[3] = operands[1]; 4149 } 4150}") 4151 4152;; 4153;; 8-bit operations on address registers. 4154;; 4155;; We have to take care that the address register is not used for the 4156;; source of operand2. If operand2 is the D register, we have to save 4157;; that register in a temporary location. 4158;; 4159;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT 4160;; 4161(define_split 4162 [(set (match_operand:QI 0 "hard_addr_reg_operand" "") 4163 (match_operator:QI 3 "m68hc11_arith_operator" 4164 [(match_operand:QI 1 "hard_addr_reg_operand" "") 4165 (match_operand:QI 2 "general_operand" "")]))] 4166 "z_replacement_completed == 2 4167 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the 4168 incqi pattern generates a better code. */ 4169 && !(GET_CODE (operands[3]) == PLUS 4170 && GET_CODE (operands[2]) == CONST_INT 4171 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))" 4172 [(set (match_dup 5) (match_dup 6)) 4173 (parallel [(set (reg:HI D_REGNUM) (match_dup 4)) 4174 (set (match_dup 4) (reg:HI D_REGNUM))]) 4175 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)])) 4176 (parallel [(set (reg:HI D_REGNUM) (match_dup 4)) 4177 (set (match_dup 4) (reg:HI D_REGNUM))])] 4178 "operands[4] = gen_rtx (REG, HImode, REGNO (operands[0])); 4179 4180 /* For the second operand is a hard register or if the address 4181 register appears in the source, we have to save the operand[2] 4182 value in a temporary location and then use that temp. 4183 Otherwise, it's ok and we generate a (set (D) (D)) that 4184 will result in a nop. */ 4185 if (H_REG_P (operands[2])) 4186 { 4187 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 4188 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2])); 4189 operands[7] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 4190 } 4191 else if (reg_mentioned_p (operands[0], operands[2])) 4192 { 4193 operands[5] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 4194 operands[6] = operands[2]; 4195 operands[7] = operands[5]; 4196 } 4197 else 4198 { 4199 operands[5] = operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM); 4200 operands[7] = operands[2]; 4201 } 4202 ") 4203 4204;; 4205;; Next split handles the logical operations on D register with 4206;; another hard register for the second operand. For this, we 4207;; have to save the second operand in a scratch location and use 4208;; it instead. This must be supported because in some (rare) cases 4209;; the second operand can come in a hard register and the reload 4210;; pass doesn't know how to reload it in a memory location. 4211;; 4212;; PLUS MINUS AND IOR XOR 4213;; 4214;; The shift operators are special and must not appear here. 4215;; 4216(define_split 4217 [(set (match_operand:QI 0 "d_register_operand" "") 4218 (match_operator:QI 3 "m68hc11_non_shift_operator" 4219 [(match_operand:QI 1 "d_register_operand" "") 4220 (match_operand:QI 2 "hard_reg_operand" "")]))] 4221 "reload_completed" 4222 [(set (match_dup 5) (match_dup 6)) 4223 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))] 4224 "operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); 4225 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); 4226 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));") 4227 4228;;-------------------------------------------------------------------- 4229;; 8-bit Unary operations on X and Y: 4230;; 4231;; NOT NEG 4232;; 4233;; Operations on X or Y registers are split here. Instructions are 4234;; changed into: 4235;; - xgdx/xgdy instruction pattern, 4236;; - The same operation on register D, 4237;; - xgdx/xgdy instruction pattern. 4238;; This should allow the peephole to merge consecutive xgdx/xgdy instructions. 4239;; We also handle the case were the address register is used in both source 4240;; operands, such as: 4241;; 4242;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X)))) 4243;; or 4244;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X))) 4245;; 4246(define_split 4247 [(set (match_operand:QI 0 "hard_addr_reg_operand" "") 4248 (match_operator:QI 2 "m68hc11_unary_operator" 4249 [(match_operand:QI 1 "general_operand" "")]))] 4250 "z_replacement_completed == 2" 4251 [(set (match_dup 4) (match_dup 5)) 4252 (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) 4253 (set (match_dup 3) (reg:HI D_REGNUM))]) 4254 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)])) 4255 (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) 4256 (set (match_dup 3) (reg:HI D_REGNUM))])] 4257 " 4258{ 4259 operands[3] = gen_rtx (REG, HImode, REGNO (operands[0])); 4260 if ((H_REG_P (operands[1]) 4261 && !rtx_equal_p (operands[0], operands[1])) 4262 || reg_mentioned_p (operands[0], operands[1])) 4263 { 4264 /* Move to the destination register, before the xgdx. */ 4265 operands[4] = operands[0]; 4266 operands[5] = operands[1]; 4267 4268 /* Apply the operation on D. */ 4269 operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM); 4270 } 4271 else 4272 { 4273 operands[4] = operands[5] = operands[0]; 4274 operands[6] = operands[1]; 4275 } 4276}") 4277 4278 4279;;-------------------------------------------------------------------- 4280;;- Complements 4281;;-------------------------------------------------------------------- 4282 4283(define_expand "negdi2" 4284 [(set (match_operand:DI 0 "nonimmediate_operand" "") 4285 (neg:DI (match_operand:DI 1 "general_operand" "")))] 4286 "" 4287 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands); 4288 DONE;") 4289 4290 4291(define_insn "negsi2" 4292 [(set (match_operand:SI 0 "register_operand" "=D") 4293 (neg:SI (match_operand:SI 1 "general_operand" "0")))] 4294 "" 4295 "* 4296{ 4297 rtx ops[1]; 4298 4299 CC_STATUS_INIT; 4300 4301 /* With -Os or without -O, use a special library call. */ 4302 if (optimize_size || optimize == 0) 4303 return \"bsr\\t___negsi2\"; 4304 4305 ops[0] = gen_label_rtx (); 4306 4307 /* 32-bit complement and add 1. */ 4308 output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands); 4309 output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands); 4310 output_asm_insn (\"bne\\t%l0\", ops); 4311 output_asm_insn (\"inx\", operands); 4312 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); 4313 return \"\"; 4314}") 4315 4316(define_insn "neghi2" 4317 [(set (match_operand:HI 0 "register_operand" "=d,d,x*y") 4318 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))] 4319 "" 4320 "@ 4321 coma\\n\\tcomb\\n\\taddd\\t#1 4322 clra\\n\\tclrb\\n\\tsubd\\t%1 4323 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0") 4324 4325(define_insn "negqi2" 4326 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A") 4327 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))] 4328 "" 4329 "@ 4330 negb 4331 neg\\t%b0 4332 neg\\t%b0 4333 #") 4334 4335;; 4336;; - 32-bit complement. GCC knows how to translate them but providing a 4337;; pattern generates better/smaller code. 4338;; 4339(define_expand "one_cmpldi2" 4340 [(set (match_operand:DI 0 "nonimmediate_operand" "") 4341 (not:DI (match_operand:DI 1 "general_operand" "")))] 4342 "" 4343 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands); 4344 DONE;") 4345 4346(define_insn "one_cmplsi2" 4347 [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u") 4348 (not:SI (match_operand:SI 1 "general_operand" "0,m,0"))) 4349 (clobber (match_scratch:HI 2 "=X,d,X"))] 4350 "" 4351 "@ 4352 bsr\\t___one_cmplsi2 4353 # 4354 #") 4355 4356(define_insn "one_cmplhi2" 4357 [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u") 4358 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))] 4359 "" 4360 "@ 4361 comb\\n\\tcoma 4362 com\\t%b0\\n\\tcom\\t%h0 4363 # 4364 com\\t%b0\\n\\tcom\\t%h0") 4365 4366(define_insn "one_cmplqi2" 4367 [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u") 4368 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))] 4369 "" 4370 "@ 4371 comb 4372 com\\t%b0 4373 # 4374 com\\t%b0") 4375 4376(define_split /* "*one_cmplsi2" */ 4377 [(set (match_operand:SI 0 "non_push_operand" "") 4378 (not:SI (match_dup 0))) 4379 (clobber (match_scratch:HI 1 ""))] 4380 "z_replacement_completed == 2 4381 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))" 4382 [(set (match_dup 2) (not:HI (match_dup 2))) 4383 (set (match_dup 3) (not:HI (match_dup 3)))] 4384 "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]); 4385 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);") 4386 4387(define_split /* "*one_cmplsi2" */ 4388 [(set (match_operand:SI 0 "non_push_operand" "") 4389 (not:SI (match_operand:SI 1 "non_push_operand" ""))) 4390 (clobber (match_operand:HI 2 "d_register_operand" ""))] 4391 "z_replacement_completed == 2 4392 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))" 4393 [(set (match_dup 2) (match_dup 3)) 4394 (set (match_dup 2) (not:HI (match_dup 2))) 4395 (set (match_dup 4) (match_dup 2)) 4396 (set (match_dup 2) (match_dup 5)) 4397 (set (match_dup 2) (not:HI (match_dup 2))) 4398 (set (match_dup 6) (match_dup 2))] 4399 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]); 4400 operands[5] = m68hc11_gen_highpart (HImode, operands[1]); 4401 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]); 4402 operands[6] = m68hc11_gen_highpart (HImode, operands[0]);") 4403 4404;;-------------------------------------------------------------------- 4405;;- arithmetic shifts 4406;;-------------------------------------------------------------------- 4407;; 4408;; Provide some 64-bit shift patterns. 4409(define_expand "ashldi3" 4410 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") 4411 (ashift:DI (match_operand:DI 1 "general_operand" "") 4412 (match_operand:HI 2 "general_operand" ""))) 4413 (clobber (match_scratch:HI 3 ""))])] 4414 "" 4415 " 4416{ 4417 if (GET_CODE (operands[2]) != CONST_INT 4418 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1)) 4419 { 4420 FAIL; 4421 } 4422}") 4423 4424(define_insn "*ashldi3_const32" 4425 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u") 4426 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi") 4427 (const_int 32))) 4428 (clobber (match_scratch:HI 2 "=&A,d,d"))] 4429 "" 4430 "#") 4431 4432(define_split 4433 [(set (match_operand:DI 0 "nonimmediate_operand" "") 4434 (ashift:DI (match_operand:DI 1 "general_operand" "") 4435 (const_int 32))) 4436 (clobber (match_scratch:HI 2 ""))] 4437 "reload_completed" 4438 [(const_int 0)] 4439 "/* Move the lowpart in the highpart first in case the shift 4440 is applied on the source. */ 4441 if (IS_STACK_PUSH (operands[0])) 4442 { 4443 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]), 4444 const0_rtx, operands[2]); 4445 } 4446 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]), 4447 m68hc11_gen_lowpart (SImode, operands[1]), 4448 operands[2]); 4449 if (!IS_STACK_PUSH (operands[0])) 4450 { 4451 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]), 4452 const0_rtx, operands[2]); 4453 } 4454 DONE;") 4455 4456(define_insn "*ashldi3_const1" 4457 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u") 4458 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi") 4459 (const_int 1))) 4460 (clobber (match_scratch:HI 2 "=d,d,d"))] 4461 "" 4462 "#") 4463 4464(define_split 4465 [(set (match_operand:DI 0 "non_push_operand" "") 4466 (ashift:DI (match_operand:DI 1 "general_operand" "") 4467 (const_int 1))) 4468 (clobber (match_scratch:HI 2 ""))] 4469 "z_replacement_completed == 2" 4470 [(set (match_dup 2) (match_dup 3)) 4471 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1))) 4472 (set (match_dup 4) (match_dup 2)) 4473 4474 (set (match_dup 2) (match_dup 5)) 4475 (parallel [(set (match_dup 2) 4476 (rotate:HI (match_dup 2) (const_int 1))) 4477 (clobber (reg:HI CC_REGNUM))]) 4478 (set (match_dup 6) (match_dup 2)) 4479 4480 (set (match_dup 2) (match_dup 7)) 4481 (parallel [(set (match_dup 2) 4482 (rotate:HI (match_dup 2) (const_int 1))) 4483 (clobber (reg:HI CC_REGNUM))]) 4484 (set (match_dup 8) (match_dup 2)) 4485 4486 (set (match_dup 2) (match_dup 9)) 4487 (parallel [(set (match_dup 2) 4488 (rotate:HI (match_dup 2) (const_int 1))) 4489 (clobber (reg:HI CC_REGNUM))]) 4490 (set (match_dup 10) (match_dup 2))] 4491 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]); 4492 operands[5] = m68hc11_gen_highpart (HImode, operands[3]); 4493 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]); 4494 4495 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]); 4496 operands[6] = m68hc11_gen_highpart (HImode, operands[4]); 4497 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]); 4498 4499 operands[7] = m68hc11_gen_highpart (SImode, operands[1]); 4500 operands[9] = m68hc11_gen_highpart (HImode, operands[7]); 4501 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]); 4502 4503 operands[8] = m68hc11_gen_highpart (SImode, operands[0]); 4504 operands[10] = m68hc11_gen_highpart (HImode, operands[8]); 4505 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);") 4506 4507(define_insn "addsi_silshr16" 4508 [(set (match_operand:SI 0 "register_operand" "=D,D") 4509 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0") 4510 (const_int 16)) 4511 (match_operand:SI 2 "general_operand" "0,m!*u")))] 4512 "" 4513 "#") 4514 4515(define_split 4516 [(set (match_operand:SI 0 "register_operand" "") 4517 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "") 4518 (const_int 16)) 4519 (match_operand:SI 2 "general_operand" "")))] 4520 "z_replacement_completed == 2 && !X_REG_P (operands[1])" 4521 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3))) 4522 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) 4523 (const_int 0)) 4524 (reg:HI CC_REGNUM)))] 4525 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);") 4526 4527(define_split 4528 [(set (match_operand:SI 0 "register_operand" "") 4529 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "") 4530 (const_int 16)) 4531 (match_operand:SI 2 "general_operand" "")))] 4532 "z_replacement_completed == 2 && X_REG_P (operands[1])" 4533 [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) 4534 (set (reg:HI X_REGNUM) (match_dup 3)) 4535 (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4))) 4536 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) 4537 (const_int 0)) 4538 (reg:HI CC_REGNUM)))] 4539 "operands[3] = m68hc11_gen_highpart (HImode, operands[2]); 4540 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);") 4541 4542(define_insn "addsi_ashift16" 4543 [(set (match_operand:SI 0 "register_operand" "=D") 4544 (plus:SI 4545 (mult:SI (match_operand:SI 2 "general_operand" "uim") 4546 (const_int 65536)) 4547 (match_operand:SI 1 "general_operand" "0"))) 4548 (clobber (match_scratch:HI 3 "=X"))] 4549 "0" 4550 "#") 4551 4552(define_split 4553 [(set (match_operand:SI 0 "register_operand" "") 4554 (plus:SI 4555 (mult:SI (match_operand:SI 2 "general_operand" "") 4556 (const_int 65536)) 4557 (match_operand:SI 1 "general_operand" ""))) 4558 (clobber (match_scratch:HI 3 "=X"))] 4559 "0 && reload_completed && z_replacement_completed == 2" 4560 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))] 4561 " 4562{ 4563 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]); 4564}") 4565 4566(define_insn "addsi_andshr16" 4567 [(set (match_operand:SI 0 "register_operand" "=D") 4568 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim") 4569 (const_int 65535)) 4570 (match_operand:SI 2 "general_operand" "0")))] 4571 "" 4572 "#") 4573 4574(define_split 4575 [(set (match_operand:SI 0 "register_operand" "") 4576 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "") 4577 (const_int 65535)) 4578 (match_operand:SI 2 "general_operand" "")))] 4579 "z_replacement_completed == 2" 4580 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3))) 4581 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))] 4582 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);") 4583 4584;; 4585;; 32-bit shifts are made by a small library routine that uses 4586;; a specific passing convention for parameters (for efficiency reasons). 4587;; 4588;; [D + X] -> Value to be shifted 4589;; Y -> Shift count 4590;; 4591;; The shift count is clobbered by the routine. 4592;; 4593(define_expand "ashlsi3" 4594 [(parallel 4595 [(set (match_operand:SI 0 "register_operand" "") 4596 (match_operand:SI 1 "general_operand" "")) 4597 (clobber (scratch:HI))]) 4598 (parallel 4599 [(set (match_dup 0) (ashift:SI (match_dup 0) 4600 (match_operand:HI 2 "nonmemory_operand" ""))) 4601 (clobber (scratch:HI))])] 4602 "" 4603 "") 4604 4605(define_split 4606 [(set (match_operand:SI 0 "nonimmediate_operand" "") 4607 (ashift:SI (match_operand:SI 1 "general_operand" "") 4608 (const_int 16))) 4609 (clobber (match_scratch:HI 3 ""))] 4610 "" 4611 [(set (match_dup 2) (match_dup 3)) 4612 (set (match_dup 4) (const_int 0))] 4613 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]); 4614 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]); 4615 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);") 4616 4617(define_insn "*ashlsi3_const16" 4618 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u") 4619 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D") 4620 (const_int 16))) 4621 (clobber (match_scratch:HI 2 "=X,X,X"))] 4622 "" 4623 "#") 4624 4625(define_insn "*ashlsi3_const16_zexthi" 4626 [(set (match_operand:SI 0 "nonimmediate_operand" "=D") 4627 (ashift:SI (zero_extend:HI 4628 (match_operand:HI 1 "general_operand" "duim*A")) 4629 (const_int 16))) 4630 (clobber (match_scratch:HI 2 "=X"))] 4631 "" 4632 "#") 4633 4634(define_split /* "*ashlsi3_const16_zexthi"*/ 4635 [(set (match_operand:SI 0 "nonimmediate_operand" "") 4636 (ashift:SI (zero_extend:HI 4637 (match_operand:HI 1 "general_operand" "")) 4638 (const_int 16))) 4639 (clobber (match_scratch:HI 2 "=X"))] 4640 "reload_completed" 4641 [(set (reg:HI X_REGNUM) (match_dup 1)) 4642 (set (reg:HI D_REGNUM) (const_int 0))] 4643 "") 4644 4645(define_insn "*ashlsi3_const1" 4646 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,!*u,?*um") 4647 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,*um,0,0,*um") 4648 (const_int 1))) 4649 (clobber (match_scratch:HI 2 "=X,X,&d,&d,&d"))] 4650 "" 4651 "* 4652{ 4653 CC_STATUS_INIT; 4654 if (X_REG_P (operands[1])) 4655 { 4656 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\"; 4657 } 4658 else 4659 { 4660 rtx ops[2]; 4661 4662 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]); 4663 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); 4664 m68hc11_gen_movhi (insn, ops); 4665 output_asm_insn (\"lsld\", ops); 4666 if (!X_REG_P (operands[0])) 4667 { 4668 ops[1] = ops[0]; 4669 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]); 4670 m68hc11_gen_movhi (insn, ops); 4671 ops[0] = ops[1]; 4672 ops[1] = m68hc11_gen_highpart (HImode, operands[1]); 4673 m68hc11_gen_movhi (insn, ops); 4674 } 4675 else 4676 { 4677 /* Load the high part in X in case the source operand 4678 uses X as a memory pointer. */ 4679 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM); 4680 ops[1] = m68hc11_gen_highpart (HImode, operands[1]); 4681 m68hc11_gen_movhi (insn, ops); 4682 output_asm_insn (\"xgdx\", ops); 4683 } 4684 output_asm_insn (\"rolb\", ops); 4685 output_asm_insn (\"rola\", ops); 4686 if (!X_REG_P (operands[0])) 4687 { 4688 ops[1] = ops[0]; 4689 ops[0] = m68hc11_gen_highpart (HImode, operands[0]); 4690 m68hc11_gen_movhi (insn, ops); 4691 } 4692 else 4693 { 4694 output_asm_insn (\"xgdx\", ops); 4695 } 4696 return \"\"; 4697 } 4698}") 4699 4700(define_insn "*ashlsi3_const" 4701 [(set (match_operand:SI 0 "register_operand" "+D") 4702 (ashift:SI (match_dup 0) 4703 (match_operand:HI 1 "const_int_operand" ""))) 4704 (clobber (match_scratch:HI 2 "=y"))] 4705 "" 4706 "* 4707{ 4708 CC_STATUS_INIT; 4709 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\"; 4710}") 4711 4712(define_insn "*ashlsi3" 4713 [(set (match_operand:SI 0 "register_operand" "+D,D") 4714 (ashift:SI (match_dup 0) 4715 (match_operand:HI 1 "general_operand" "y,m"))) 4716 (clobber (match_scratch:HI 2 "=1,X"))] 4717 "" 4718 "* 4719{ 4720 CC_STATUS_INIT; 4721 4722 /* There is a reload problem if we don't accept 'm' for the shift value. 4723 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS) 4724 and this conflicts with all reloads. Since X, Y, Z are used there 4725 is not enough register in class A_REGS. 4726 4727 Assuming that 'operands[1]' does not refer to the stack (which 4728 is true for 68hc11 only, we save temporary the value of Y. */ 4729 if (!Y_REG_P (operands[2])) 4730 { 4731 rtx ops[1]; 4732 int y_dead = dead_register_here (insn, iy_reg); 4733 4734 ops[0] = operands[1]; 4735 if (y_dead == 0) 4736 { 4737 output_asm_insn (\"pshy\", operands); 4738 if (reg_mentioned_p (stack_pointer_rtx, operands[1])) 4739 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); 4740 } 4741 output_asm_insn (\"ldy\\t%0\", ops); 4742 output_asm_insn (\"bsr\\t___ashlsi3\", operands); 4743 return y_dead == 0 ? \"puly\" : \"\"; 4744 } 4745 return \"bsr\\t___ashlsi3\"; 4746}") 4747 4748(define_expand "ashlhi3" 4749 [(set (match_operand:HI 0 "register_operand" "") 4750 (ashift:HI (match_operand:HI 1 "register_operand" "") 4751 (match_operand:HI 2 "general_operand" "")))] 4752 "" 4753 " 4754{ 4755 if (GET_CODE (operands[2]) != CONST_INT) 4756 { 4757 rtx scratch = gen_reg_rtx (HImode); 4758 emit_move_insn (scratch, operands[2]); 4759 emit_insn (gen_rtx (PARALLEL, VOIDmode, 4760 gen_rtvec (2, gen_rtx (SET, VOIDmode, 4761 operand0, 4762 gen_rtx_ASHIFT (HImode, 4763 operand1, scratch)), 4764 gen_rtx (CLOBBER, VOIDmode, scratch)))); 4765 DONE; 4766 } 4767}") 4768 4769(define_insn "*ashlhi3_const1" 4770 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A") 4771 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0") 4772 (const_int 1)))] 4773 "" 4774 "* 4775{ 4776 if (A_REG_P (operands[0])) 4777 return \"#\"; 4778 4779 if (D_REG_P (operands[0])) 4780 { 4781 return \"asld\"; 4782 } 4783 4784 output_asm_insn (\"asl\\t%b0\", operands); 4785 output_asm_insn (\"rol\\t%h0\", operands); 4786 CC_STATUS_INIT; 4787 return \"\"; 4788}") 4789 4790 4791(define_insn "*ashlhi3_2" 4792 [(set (match_operand:HI 0 "register_operand" "=d,*x") 4793 (ashift:HI (match_operand:HI 1 "register_operand" "0,0") 4794 (match_operand:HI 2 "register_operand" "+x,+d"))) 4795 (clobber (match_dup 2))] 4796 "" 4797 "* 4798{ 4799 if (A_REG_P (operands[0])) 4800 return \"#\"; 4801 4802 CC_STATUS_INIT; 4803 return \"bsr\\t___lshlhi3\"; 4804}") 4805 4806(define_insn "*ashlhi3" 4807 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) 4808 (ashift:HI (match_dup 0) 4809 (match_operand:HI 1 "register_operand" "+x"))) 4810 (clobber (match_dup 1))] 4811 "" 4812 "* 4813{ 4814 CC_STATUS_INIT; 4815 return \"bsr\\t___lshlhi3\"; 4816}") 4817 4818(define_insn "*ashlhi3" 4819 [(set (match_operand:HI 0 "register_operand" "=d,!*A") 4820 (ashift:HI (match_operand:HI 1 "register_operand" "0,0") 4821 (match_operand:HI 2 "const_int_operand" "")))] 4822 "" 4823 "* 4824{ 4825 int i; 4826 4827 if (A_REG_P (operands[0])) 4828 return \"#\"; 4829 4830 i = INTVAL (operands[2]); 4831 if (i >= 8) 4832 { 4833 CC_STATUS_INIT; 4834 output_asm_insn (\"tba\", operands); 4835 if (i == 15) 4836 { 4837 output_asm_insn (\"rora\", operands); 4838 output_asm_insn (\"anda\\t#0\", operands); 4839 output_asm_insn (\"rora\", operands); 4840 } 4841 else 4842 while (i != 8 ) 4843 { 4844 output_asm_insn (\"asla\", operands); 4845 i--; 4846 } 4847 return \"clrb\"; 4848 } 4849 for (i = 0; i < INTVAL (operands[2]) - 1; i++) 4850 { 4851 output_asm_insn (\"asld\", operands); 4852 } 4853 return \"asld\"; 4854}") 4855 4856(define_expand "ashlqi3" 4857 [(set (match_operand:QI 0 "register_operand" "") 4858 (ashift:QI (match_operand:QI 1 "register_operand" "") 4859 (match_operand:QI 2 "general_operand" "")))] 4860 "" 4861 "") 4862 4863(define_insn "*ashlqi3_const1" 4864 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A") 4865 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0") 4866 (const_int 1)))] 4867 "" 4868 "@ 4869 aslb 4870 asl\\t%b0 4871 asl\\t%b0 4872 asl%0 4873 #") 4874 4875(define_insn "*ashlqi3_const" 4876 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A") 4877 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0") 4878 (match_operand:QI 2 "const_int_operand" "")))] 4879 "" 4880 "* 4881{ 4882 int i; 4883 const char* insn_code; 4884 4885 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 4886 insn_code = \"aslb\"; 4887 else if (DA_REG_P (operands[0])) 4888 insn_code = \"asla\"; 4889 else 4890 return \"#\"; 4891 4892 i = INTVAL (operands[2]); 4893 if (i >= 8) 4894 { 4895 if (DA_REG_P (operands[0])) 4896 return \"clra\"; 4897 else 4898 return \"clrb\"; 4899 } 4900 else if (i == 7) 4901 { 4902 if (DA_REG_P (operands[0])) 4903 { 4904 output_asm_insn (\"rora\", operands); 4905 output_asm_insn (\"ldaa\\t#0\", operands); 4906 return \"rora\"; 4907 } 4908 else 4909 { 4910 output_asm_insn (\"rorb\", operands); 4911 output_asm_insn (\"ldab\\t#0\", operands); 4912 return \"rorb\"; 4913 } 4914 } 4915 else if (i == 6) 4916 { 4917 if (DA_REG_P (operands[0])) 4918 { 4919 output_asm_insn (\"rora\", operands); 4920 output_asm_insn (\"rora\", operands); 4921 output_asm_insn (\"rora\", operands); 4922 return \"anda\\t#0xC0\"; 4923 } 4924 else 4925 { 4926 output_asm_insn (\"rorb\", operands); 4927 output_asm_insn (\"rorb\", operands); 4928 output_asm_insn (\"rorb\", operands); 4929 return \"andb\\t#0xC0\"; 4930 } 4931 } 4932 while (--i >= 0) 4933 { 4934 output_asm_insn (insn_code, operands); 4935 } 4936 return \"\"; 4937}") 4938 4939(define_insn "*ashlqi3" 4940 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A") 4941 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0") 4942 (match_operand:QI 2 "nonimmediate_operand" 4943 "m*u*d*A,m*u*d*A,m*u")))] 4944 "" 4945 "* 4946{ 4947 rtx ops[2]; 4948 4949 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0])) 4950 return \"#\"; 4951 4952 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); 4953 ops[1] = operands[2]; 4954 m68hc11_gen_movqi (insn, ops); 4955 4956 CC_STATUS_INIT; 4957 return \"bsr\\t___lshlqi3\"; 4958}") 4959 4960(define_expand "ashrhi3" 4961 [(set (match_operand:HI 0 "register_operand" "") 4962 (ashiftrt:HI (match_operand:HI 1 "register_operand" "") 4963 (match_operand:HI 2 "general_operand" "")))] 4964 "" 4965 " 4966{ 4967 if (GET_CODE (operands[2]) != CONST_INT) 4968 { 4969 rtx scratch = gen_reg_rtx (HImode); 4970 4971 emit_move_insn (scratch, operands[2]); 4972 emit_insn (gen_rtx (PARALLEL, VOIDmode, 4973 gen_rtvec (2, gen_rtx (SET, VOIDmode, 4974 operand0, 4975 gen_rtx_ASHIFTRT (HImode, 4976 operand1, scratch)), 4977 gen_rtx (CLOBBER, VOIDmode, scratch)))); 4978 DONE; 4979 } 4980}") 4981 4982(define_insn "*ashrhi3_const1" 4983 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A") 4984 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0") 4985 (const_int 1)))] 4986 "" 4987 "* 4988{ 4989 if (A_REG_P (operands[0])) 4990 return \"#\"; 4991 4992 CC_STATUS_INIT; 4993 if (D_REG_P (operands[0])) 4994 { 4995 return \"asra\\n\\trorb\"; 4996 } 4997 4998 output_asm_insn (\"asr\\t%h0\", operands); 4999 output_asm_insn (\"ror\\t%b0\", operands); 5000 return \"\"; 5001}") 5002 5003 5004(define_insn "*ashrhi3_const" 5005 [(set (match_operand:HI 0 "register_operand" "=d,!*A") 5006 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0") 5007 (match_operand:HI 2 "const_int_operand" "")))] 5008 "" 5009 "* 5010{ 5011 rtx ops[2]; 5012 int val = INTVAL (operands[2]); 5013 5014 if (A_REG_P (operands[0])) 5015 return \"#\"; 5016 5017 if (val >= 15) 5018 { 5019 ops[0] = gen_label_rtx (); 5020 5021 output_asm_insn (\"clrb\", operands); 5022 output_asm_insn (\"rola\", operands); 5023 5024 /* Clear A without clearing the carry flag. */ 5025 output_asm_insn (\"tba\", operands); 5026 output_asm_insn (\"bcc\\t%l0\", ops); 5027 output_asm_insn (\"coma\", operands); 5028 output_asm_insn (\"comb\", operands); 5029 5030 CC_STATUS_INIT; 5031 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 5032 CODE_LABEL_NUMBER (ops[0])); 5033 return \"\"; 5034 } 5035 if (val >= 8) 5036 { 5037 ops[0] = gen_label_rtx (); 5038 5039 output_asm_insn (\"tab\", operands); 5040 output_asm_insn (\"clra\", operands); 5041 output_asm_insn (\"tstb\", operands); 5042 output_asm_insn (\"bge\\t%l0\", ops); 5043 output_asm_insn (\"deca\", operands); 5044 5045 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 5046 CODE_LABEL_NUMBER (ops[0])); 5047 5048 val -= 8; 5049 5050 while (val > 0) 5051 { 5052 output_asm_insn (\"asrb\", operands); 5053 val--; 5054 } 5055 /* Status is ok. */ 5056 return \"\"; 5057 } 5058 if (val == 7) 5059 { 5060 ops[0] = gen_label_rtx (); 5061 output_asm_insn (\"rolb\", operands); 5062 output_asm_insn (\"rola\", operands); 5063 output_asm_insn (\"tab\", operands); 5064 output_asm_insn (\"anda\\t#0\", operands); 5065 output_asm_insn (\"bcc\\t%l0\", ops); 5066 output_asm_insn (\"coma\", ops); 5067 5068 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 5069 CODE_LABEL_NUMBER (ops[0])); 5070 return \"\"; 5071 } 5072 while (val > 0) 5073 { 5074 output_asm_insn (\"asra\", operands); 5075 output_asm_insn (\"rorb\", operands); 5076 val--; 5077 } 5078 CC_STATUS_INIT; 5079 5080 return \"\"; 5081}") 5082 5083(define_insn "*ashrhi3" 5084 [(set (match_operand:HI 0 "register_operand" "=d,*x") 5085 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0") 5086 (match_operand:HI 2 "register_operand" "+x,+d"))) 5087 (clobber (match_dup 2))] 5088 "" 5089 "* 5090{ 5091 if (A_REG_P (operands[0])) 5092 return \"#\"; 5093 5094 output_asm_insn (\"bsr\\t___ashrhi3\", operands); 5095 return \"\"; 5096}") 5097 5098(define_expand "ashrsi3" 5099 [(parallel 5100 [(set (match_dup 0) (match_operand:SI 1 "general_operand" "")) 5101 (clobber (scratch:HI))]) 5102 (parallel 5103 [(set (match_operand:SI 0 "register_operand" "") 5104 (ashiftrt:SI (match_dup 0) 5105 (match_operand:HI 2 "general_operand" ""))) 5106 (clobber (scratch:HI))])] 5107 "" 5108 "") 5109 5110(define_insn "*ashrsi3_const" 5111 [(set (match_operand:SI 0 "register_operand" "+D") 5112 (ashiftrt:SI (match_dup 0) 5113 (match_operand:HI 1 "const_int_operand" ""))) 5114 (clobber (match_scratch:HI 2 "=y"))] 5115 "" 5116 "* 5117{ 5118 CC_STATUS_INIT; 5119 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\"; 5120}") 5121 5122(define_insn "*ashrsi3" 5123 [(set (match_operand:SI 0 "register_operand" "+D,D") 5124 (ashiftrt:SI (match_dup 0) 5125 (match_operand:HI 1 "general_operand" "y,m"))) 5126 (clobber (match_scratch:HI 2 "=1,X"))] 5127 "" 5128 "* 5129{ 5130 CC_STATUS_INIT; 5131 /* There is a reload problem if we don't accept 'm' for the shift value. 5132 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS) 5133 and this conflicts with all reloads. Since X, Y, Z are used there 5134 is not enough register in class A_REGS. 5135 5136 Assuming that 'operands[1]' does not refer to the stack (which 5137 is true for 68hc11 only, we save temporary the value of Y. */ 5138 if (!Y_REG_P (operands[2])) 5139 { 5140 rtx ops[1]; 5141 int y_dead = dead_register_here (insn, iy_reg); 5142 5143 ops[0] = operands[1]; 5144 if (y_dead == 0) 5145 { 5146 output_asm_insn (\"pshy\", operands); 5147 if (reg_mentioned_p (stack_pointer_rtx, operands[1])) 5148 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); 5149 } 5150 output_asm_insn (\"ldy\\t%0\", ops); 5151 output_asm_insn (\"bsr\\t___ashrsi3\", operands); 5152 return y_dead == 0 ? \"puly\" : \"\"; 5153 } 5154 return \"bsr\\t___ashrsi3\"; 5155}") 5156 5157(define_expand "ashrqi3" 5158 [(set (match_operand:QI 0 "register_operand" "") 5159 (ashiftrt:QI (match_operand:QI 1 "register_operand" "") 5160 (match_operand:QI 2 "general_operand" "")))] 5161 "" 5162 "") 5163 5164(define_insn "*ashrqi3_const1" 5165 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A") 5166 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0") 5167 (const_int 1)))] 5168 "" 5169 "@ 5170 asrb 5171 asr\\t%b0 5172 asr\\t%b0 5173 asr%0 5174 #") 5175 5176(define_insn "*ashrqi3_const" 5177 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A") 5178 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0") 5179 (match_operand:QI 2 "const_int_operand" "")))] 5180 "" 5181 "* 5182{ 5183 int i; 5184 const char* insn_code; 5185 5186 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 5187 insn_code = \"asrb\"; 5188 else if (DA_REG_P (operands[0])) 5189 insn_code = \"asra\"; 5190 else 5191 return \"#\"; 5192 5193 i = INTVAL (operands[2]); 5194 if (i > 8) 5195 i = 8; 5196 while (--i >= 0) 5197 { 5198 output_asm_insn (insn_code, operands); 5199 } 5200 return \"\"; 5201}") 5202 5203(define_insn "*ashrqi3" 5204 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A") 5205 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0") 5206 (match_operand:QI 2 "nonimmediate_operand" 5207 "m*u*d*A,m*u*d*A,m*u")))] 5208 "" 5209 "* 5210{ 5211 rtx ops[2]; 5212 5213 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0])) 5214 return \"#\"; 5215 5216 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); 5217 ops[1] = operands[2]; 5218 m68hc11_gen_movqi (insn, ops); 5219 5220 CC_STATUS_INIT; 5221 return \"bsr\\t___ashrqi3\"; 5222}") 5223 5224;;-------------------------------------------------------------------- 5225;; logical shift instructions 5226;;-------------------------------------------------------------------- 5227(define_expand "lshrdi3" 5228 [(parallel [(set (match_operand:DI 0 "general_operand" "") 5229 (lshiftrt:DI (match_operand:DI 1 "general_operand" "") 5230 (match_operand:HI 2 "general_operand" ""))) 5231 (clobber (match_scratch:HI 3 ""))])] 5232 "" 5233 " 5234{ 5235 if (GET_CODE (operands[2]) != CONST_INT 5236 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48 5237 && INTVAL (operands[2]) != 1)) 5238 { 5239 FAIL; 5240 } 5241}") 5242 5243(define_insn "*lshrdi3_const32" 5244 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u") 5245 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi") 5246 (const_int 32))) 5247 (clobber (match_scratch:HI 2 "=&A,d,d"))] 5248 "" 5249 "#") 5250 5251(define_split 5252 [(set (match_operand:DI 0 "nonimmediate_operand" "") 5253 (lshiftrt:DI (match_operand:DI 1 "general_operand" "") 5254 (const_int 32))) 5255 (clobber (match_scratch:HI 2 "=&A,d"))] 5256 "reload_completed" 5257 [(const_int 0)] 5258 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]), 5259 m68hc11_gen_highpart (SImode, operands[1]), 5260 operands[2]); 5261 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]), 5262 const0_rtx, operands[2]); 5263 DONE;") 5264 5265(define_insn "*lshrdi3_const63" 5266 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u") 5267 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi") 5268 (match_operand:DI 2 "const_int_operand" ""))) 5269 (clobber (match_scratch:HI 3 "=d,d"))] 5270 "INTVAL (operands[2]) >= 48" 5271 "#") 5272 5273(define_split 5274 [(set (match_operand:DI 0 "nonimmediate_operand" "") 5275 (lshiftrt:DI (match_operand:DI 1 "general_operand" "") 5276 (match_operand:DI 2 "const_int_operand" ""))) 5277 (clobber (match_scratch:HI 3 "=d"))] 5278 "z_replacement_completed && INTVAL (operands[2]) >= 56" 5279 [(set (reg:QI D_REGNUM) (match_dup 9)) 5280 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8))) 5281 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM))) 5282 (set (match_dup 4) (reg:HI D_REGNUM)) 5283 (set (reg:QI D_REGNUM) (const_int 0)) 5284 (set (match_dup 5) (reg:HI D_REGNUM)) 5285 (set (match_dup 6) (reg:HI D_REGNUM)) 5286 (set (match_dup 7) (reg:HI D_REGNUM))] 5287 "operands[8] = GEN_INT (INTVAL (operands[2]) - 56); 5288 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]); 5289 operands[5] = m68hc11_gen_highpart (HImode, operands[4]); 5290 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]); 5291 5292 operands[9] = m68hc11_gen_highpart (SImode, operands[1]); 5293 operands[9] = m68hc11_gen_highpart (HImode, operands[9]); 5294 operands[9] = m68hc11_gen_highpart (QImode, operands[9]); 5295 5296 operands[6] = m68hc11_gen_highpart (SImode, operands[0]); 5297 operands[7] = m68hc11_gen_highpart (HImode, operands[6]); 5298 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);") 5299 5300(define_split 5301 [(set (match_operand:DI 0 "nonimmediate_operand" "") 5302 (lshiftrt:DI (match_operand:DI 1 "general_operand" "") 5303 (match_operand:DI 2 "const_int_operand" ""))) 5304 (clobber (match_scratch:HI 3 "=d"))] 5305 "z_replacement_completed && INTVAL (operands[2]) >= 48 5306 && INTVAL (operands[2]) < 56" 5307 [(set (reg:HI D_REGNUM) (match_dup 9)) 5308 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8))) 5309 (set (match_dup 4) (reg:HI D_REGNUM)) 5310 (set (reg:HI D_REGNUM) (const_int 0)) 5311 (set (match_dup 5) (reg:HI D_REGNUM)) 5312 (set (match_dup 6) (reg:HI D_REGNUM)) 5313 (set (match_dup 7) (reg:HI D_REGNUM))] 5314 "operands[8] = GEN_INT (INTVAL (operands[2]) - 48); 5315 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]); 5316 operands[5] = m68hc11_gen_highpart (HImode, operands[4]); 5317 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]); 5318 5319 operands[9] = m68hc11_gen_highpart (SImode, operands[1]); 5320 operands[9] = m68hc11_gen_highpart (HImode, operands[1]); 5321 operands[6] = m68hc11_gen_highpart (SImode, operands[0]); 5322 operands[7] = m68hc11_gen_highpart (HImode, operands[6]); 5323 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);") 5324 5325(define_insn "*lshrdi_const1" 5326 [(set (match_operand:DI 0 "non_push_operand" "=m,u") 5327 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi") 5328 (const_int 1))) 5329 (clobber (match_scratch:HI 2 "=d,d"))] 5330 "" 5331 "#") 5332 5333(define_split 5334 [(set (match_operand:DI 0 "non_push_operand" "") 5335 (lshiftrt:DI (match_operand:DI 1 "general_operand" "") 5336 (const_int 1))) 5337 (clobber (match_scratch:HI 2 ""))] 5338 "z_replacement_completed == 2" 5339 [(set (match_dup 2) (match_dup 3)) 5340 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1))) 5341 (set (match_dup 4) (match_dup 2)) 5342 5343 (set (match_dup 2) (match_dup 5)) 5344 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) 5345 (clobber (reg:HI CC_REGNUM))]) 5346 (set (match_dup 6) (match_dup 2)) 5347 5348 (set (match_dup 2) (match_dup 7)) 5349 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) 5350 (clobber (reg:HI CC_REGNUM))]) 5351 (set (match_dup 8) (match_dup 2)) 5352 5353 (set (match_dup 2) (match_dup 9)) 5354 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) 5355 (clobber (reg:HI CC_REGNUM))]) 5356 (set (match_dup 10) (match_dup 2))] 5357 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]); 5358 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]); 5359 operands[3] = m68hc11_gen_highpart (HImode, operands[3]); 5360 5361 operands[4] = m68hc11_gen_highpart (SImode, operands[0]); 5362 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]); 5363 operands[4] = m68hc11_gen_highpart (HImode, operands[4]); 5364 5365 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]); 5366 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]); 5367 operands[7] = m68hc11_gen_highpart (HImode, operands[7]); 5368 5369 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]); 5370 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]); 5371 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);") 5372 5373(define_expand "lshrsi3" 5374 [(parallel 5375 [(set (match_dup 0) (match_operand:SI 1 "general_operand" "")) 5376 (clobber (scratch:HI))]) 5377 (parallel 5378 [(set (match_operand:SI 0 "register_operand" "") 5379 (lshiftrt:SI (match_dup 0) 5380 (match_operand:HI 2 "general_operand" ""))) 5381 (clobber (scratch:HI))])] 5382 "" 5383 "") 5384 5385(define_split 5386 [(set (match_operand:SI 0 "non_push_operand" "") 5387 (lshiftrt:SI (match_operand:SI 1 "general_operand" "") 5388 (const_int 16))) 5389 (clobber (match_scratch:HI 3 ""))] 5390 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))" 5391 [(set (match_dup 2) (match_dup 3)) 5392 (set (match_dup 4) (const_int 0))] 5393 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]); 5394 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]); 5395 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);") 5396 5397(define_insn "*lshrsi3_const16" 5398 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u") 5399 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D") 5400 (const_int 16))) 5401 (clobber (match_scratch:HI 2 "=X,X,X,X"))] 5402 "" 5403 "@ 5404 # 5405 xgdx\\n\\tldx\\t#0 5406 # 5407 #") 5408 5409(define_insn "*lshrsi3_const1" 5410 [(set (match_operand:SI 0 "non_push_operand" "=D,m,*u") 5411 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "D*um,*um,*um") 5412 (const_int 1))) 5413 (clobber (match_scratch:HI 2 "=X,&d,&d"))] 5414 "" 5415 "* 5416{ 5417 CC_STATUS_INIT; 5418 if (X_REG_P (operands[1])) 5419 { 5420 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\"; 5421 } 5422 else 5423 { 5424 rtx ops[2]; 5425 5426 ops[1] = m68hc11_gen_highpart (HImode, operands[1]); 5427 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); 5428 m68hc11_gen_movhi (insn, ops); 5429 output_asm_insn (\"lsrd\", ops); 5430 if (!X_REG_P (operands[0])) 5431 { 5432 ops[1] = ops[0]; 5433 ops[0] = m68hc11_gen_highpart (HImode, operands[0]); 5434 m68hc11_gen_movhi (insn, ops); 5435 ops[0] = ops[1]; 5436 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]); 5437 m68hc11_gen_movhi (insn, ops); 5438 } 5439 else 5440 { 5441 /* Load the lowpart in X in case the operands is some N,x. */ 5442 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM); 5443 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]); 5444 m68hc11_gen_movhi (insn, ops); 5445 output_asm_insn (\"xgdx\", ops); 5446 } 5447 output_asm_insn (\"rora\", ops); 5448 output_asm_insn (\"rorb\", ops); 5449 if (!X_REG_P (operands[0])) 5450 { 5451 ops[1] = ops[0]; 5452 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]); 5453 m68hc11_gen_movhi (insn, ops); 5454 } 5455 return \"\"; 5456 } 5457}") 5458 5459(define_insn "*lshrsi3_const" 5460 [(set (match_operand:SI 0 "register_operand" "+D") 5461 (lshiftrt:SI (match_dup 0) 5462 (match_operand:HI 1 "const_int_operand" ""))) 5463 (clobber (match_scratch:HI 2 "=y"))] 5464 "" 5465 "* 5466{ 5467 CC_STATUS_INIT; 5468 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\"; 5469}") 5470 5471(define_insn "*lshrsi3" 5472 [(set (match_operand:SI 0 "register_operand" "+D,D") 5473 (lshiftrt:SI (match_dup 0) 5474 (match_operand:HI 1 "general_operand" "y,m"))) 5475 (clobber (match_scratch:HI 2 "=1,X"))] 5476 "" 5477 "* 5478{ 5479 CC_STATUS_INIT; 5480 /* There is a reload problem if we don't accept 'm' for the shift value. 5481 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS) 5482 and this conflicts with all reloads. Since X, Y, Z are used there 5483 is not enough register in class A_REGS. 5484 5485 Assuming that 'operands[1]' does not refer to the stack (which 5486 is true for 68hc11 only, we save temporary the value of Y. */ 5487 if (!Y_REG_P (operands[2])) 5488 { 5489 rtx ops[1]; 5490 int y_dead = dead_register_here (insn, iy_reg); 5491 5492 ops[0] = operands[1]; 5493 if (y_dead == 0) 5494 { 5495 output_asm_insn (\"pshy\", operands); 5496 if (reg_mentioned_p (stack_pointer_rtx, operands[1])) 5497 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); 5498 } 5499 output_asm_insn (\"ldy\\t%0\", ops); 5500 output_asm_insn (\"bsr\\t___lshrsi3\", operands); 5501 return y_dead == 0 ? \"puly\" : \"\"; 5502 } 5503 return \"bsr\\t___lshrsi3\"; 5504}") 5505 5506(define_expand "lshrhi3" 5507 [(set (match_operand:HI 0 "register_operand" "") 5508 (lshiftrt:HI (match_operand:HI 1 "general_operand" "") 5509 (match_operand:HI 2 "general_operand" "")))] 5510 "" 5511 " 5512{ 5513 if (GET_CODE (operands[2]) != CONST_INT) 5514 { 5515 rtx scratch = gen_reg_rtx (HImode); 5516 operand1 = force_reg (HImode, operand1); 5517 5518 emit_move_insn (scratch, operands[2]); 5519 emit_insn (gen_rtx (PARALLEL, VOIDmode, 5520 gen_rtvec (2, gen_rtx (SET, VOIDmode, 5521 operand0, 5522 gen_rtx_LSHIFTRT (HImode, 5523 operand1, scratch)), 5524 gen_rtx (CLOBBER, VOIDmode, scratch)))); 5525 DONE; 5526 } 5527}") 5528 5529(define_insn "lshrhi3_const1" 5530 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A") 5531 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0") 5532 (const_int 1)))] 5533 "" 5534 "* 5535{ 5536 if (A_REG_P (operands[0])) 5537 return \"#\"; 5538 5539 if (D_REG_P (operands[0])) 5540 return \"lsrd\"; 5541 5542 CC_STATUS_INIT; 5543 return \"lsr\\t%h0\\n\\tror\\t%b0\"; 5544}") 5545 5546(define_insn "lshrhi3_const" 5547 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A") 5548 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u") 5549 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))] 5550 "" 5551 "* 5552{ 5553 int val = INTVAL (operands[2]); 5554 5555 if (A_REG_P (operands[0])) 5556 return \"#\"; 5557 5558 if (val >= 8) 5559 { 5560 if (val == 8) 5561 CC_STATUS_INIT; 5562 5563 if (!H_REG_P (operands[1])) 5564 { 5565 output_asm_insn (\"clra\", operands); 5566 output_asm_insn (\"ldab\\t%h1\", operands); 5567 } 5568 else if (A_REG_P (operands[1])) 5569 { 5570 output_asm_insn (\"st%1\\t%t0\", operands); 5571 output_asm_insn (\"ldab\\t%t0\", operands); 5572 output_asm_insn (\"clra\", operands); 5573 } 5574 else 5575 { 5576 output_asm_insn (\"tab\", operands); 5577 output_asm_insn (\"clra\", operands); 5578 } 5579 val -= 8; 5580 switch (val) 5581 { 5582 case 7: 5583 output_asm_insn (\"rolb\", operands); 5584 output_asm_insn (\"tab\", operands); 5585 output_asm_insn (\"rolb\", operands); 5586 break; 5587 5588 case 6: 5589 output_asm_insn (\"rolb\", operands); 5590 output_asm_insn (\"rolb\", operands); 5591 output_asm_insn (\"rolb\", operands); 5592 output_asm_insn (\"andb\\t#3\", operands); 5593 break; 5594 5595 default: 5596 while (val > 0) 5597 { 5598 val --; 5599 output_asm_insn (\"lsrb\", operands); 5600 } 5601 break; 5602 } 5603 return \"\"; 5604 } 5605 5606 if (!D_REG_P (operands[1])) 5607 m68hc11_gen_movhi (insn, operands); 5608 switch (val) 5609 { 5610 case 7: 5611 output_asm_insn (\"rolb\", operands); 5612 output_asm_insn (\"tab\", operands); 5613 output_asm_insn (\"rolb\", operands); 5614 output_asm_insn (\"rola\", operands); 5615 output_asm_insn (\"rola\", operands); 5616 output_asm_insn (\"anda\\t#1\", operands); 5617 CC_STATUS_INIT; 5618 break; 5619 5620 default: 5621 while (val > 0) 5622 { 5623 val --; 5624 output_asm_insn (\"lsrd\", operands); 5625 } 5626 } 5627 return \"\"; 5628}") 5629 5630(define_insn "*lshrhi3" 5631 [(set (match_operand:HI 0 "register_operand" "=d,*x") 5632 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0") 5633 (match_operand:HI 2 "register_operand" "+x,+d"))) 5634 (clobber (match_dup 2))] 5635 "" 5636 "* 5637{ 5638 if (A_REG_P (operands[0])) 5639 return \"#\"; 5640 5641 return \"bsr\\t___lshrhi3\"; 5642}") 5643 5644(define_expand "lshrqi3" 5645 [(set (match_operand:QI 0 "register_operand" "") 5646 (lshiftrt:QI (match_operand:QI 1 "register_operand" "") 5647 (match_operand:QI 2 "general_operand" "")))] 5648 "" 5649 "") 5650 5651(define_insn "*lshrqi3_const1" 5652 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A") 5653 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0") 5654 (const_int 1)))] 5655 "" 5656 "@ 5657 lsr\\t%b0 5658 lsrb 5659 lsr\\t%b0 5660 lsr%0 5661 #") 5662 5663(define_insn "*lshrqi3_const" 5664 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A") 5665 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0") 5666 (match_operand:QI 2 "const_int_operand" "")))] 5667 "" 5668 "* 5669{ 5670 int i; 5671 const char* insn_code; 5672 5673 if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) 5674 insn_code = \"lsrb\"; 5675 else if (DA_REG_P (operands[0])) 5676 insn_code = \"lsra\"; 5677 else 5678 return \"#\"; 5679 5680 i = INTVAL (operands[2]); 5681 if (i >= 8) 5682 { 5683 if (DA_REG_P (operands[0])) 5684 return \"clra\"; 5685 else 5686 return \"clrb\"; 5687 } 5688 else if (i == 7) 5689 { 5690 if (DA_REG_P (operands[0])) 5691 { 5692 output_asm_insn (\"rola\", operands); 5693 output_asm_insn (\"ldaa\\t#0\", operands); 5694 return \"rola\"; 5695 } 5696 else 5697 { 5698 output_asm_insn (\"rolb\", operands); 5699 output_asm_insn (\"ldab\\t#0\", operands); 5700 return \"rolb\"; 5701 } 5702 } 5703 else if (i == 6) 5704 { 5705 if (DA_REG_P (operands[0])) 5706 { 5707 output_asm_insn (\"rola\", operands); 5708 output_asm_insn (\"rola\", operands); 5709 output_asm_insn (\"rola\", operands); 5710 return \"anda\\t#3\"; 5711 } 5712 else 5713 { 5714 output_asm_insn (\"rolb\", operands); 5715 output_asm_insn (\"rolb\", operands); 5716 output_asm_insn (\"rolb\", operands); 5717 return \"andb\\t#3\"; 5718 } 5719 } 5720 while (--i >= 0) 5721 { 5722 output_asm_insn (insn_code, operands); 5723 } 5724 return \"\"; 5725}") 5726 5727(define_insn "*lshrqi3" 5728 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A") 5729 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0") 5730 (match_operand:QI 2 "nonimmediate_operand" 5731 "m*u*d*A,m*u*d*A,m*u")))] 5732 "" 5733 "* 5734{ 5735 rtx ops[2]; 5736 5737 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0])) 5738 return \"#\"; 5739 5740 CC_STATUS_INIT; 5741 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); 5742 ops[1] = operands[2]; 5743 m68hc11_gen_movqi (insn, ops); 5744 5745 if (!optimize || optimize_size) 5746 { 5747 return \"bsr\\t___lshrqi3\"; 5748 } 5749 5750 ops[0] = gen_label_rtx (); 5751 ops[1] = gen_label_rtx (); 5752 output_asm_insn (\"ble\\t%l1\", ops); 5753 5754 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 5755 CODE_LABEL_NUMBER (ops[0])); 5756 5757 output_asm_insn (\"lsrb\", operands); 5758 output_asm_insn (\"deca\", operands); 5759 output_asm_insn (\"bne\\t%l0\", ops); 5760 5761 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 5762 CODE_LABEL_NUMBER (ops[1])); 5763 return \"\"; 5764}") 5765 5766(define_insn "*rotlqi3_with_carry" 5767 [(set (match_operand:QI 0 "register_operand" "=d,!q") 5768 (rotate:QI (match_operand:QI 1 "register_operand" "0,0") 5769 (reg:QI CC_REGNUM)))] 5770 "" 5771 "* 5772{ 5773 if (DA_REG_P (operands[0])) 5774 return \"rola\"; 5775 else 5776 return \"rolb\"; 5777}") 5778 5779(define_insn "*rotlhi3_with_carry" 5780 [(set (match_operand:HI 0 "register_operand" "=d") 5781 (rotate:HI (match_operand:HI 1 "register_operand" "0") 5782 (const_int 1))) 5783 (clobber (reg:HI CC_REGNUM))] 5784 "" 5785 "* 5786{ 5787 CC_STATUS_INIT; 5788 return \"rolb\\n\\trola\"; 5789}") 5790 5791(define_insn "*rotrhi3_with_carry" 5792 [(set (match_operand:HI 0 "register_operand" "=d") 5793 (rotatert:HI (match_operand:HI 1 "register_operand" "0") 5794 (const_int 1))) 5795 (clobber (reg:HI CC_REGNUM))] 5796 "" 5797 "* 5798{ 5799 CC_STATUS_INIT; 5800 return \"rora\\n\\trorb\"; 5801}") 5802 5803(define_insn "rotlqi3" 5804 [(set (match_operand:QI 0 "register_operand" "=d,!q") 5805 (rotate:QI (match_operand:QI 1 "register_operand" "0,0") 5806 (match_operand:QI 2 "const_int_operand" "i,i")))] 5807 "" 5808 "* 5809{ 5810 m68hc11_gen_rotate (ROTATE, insn, operands); 5811 return \"\"; 5812}") 5813 5814(define_insn "rotrqi3" 5815 [(set (match_operand:QI 0 "register_operand" "=d,!q") 5816 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0") 5817 (match_operand:QI 2 "const_int_operand" "i,i")))] 5818 "" 5819 "* 5820{ 5821 m68hc11_gen_rotate (ROTATERT, insn, operands); 5822 return \"\"; 5823}") 5824 5825(define_expand "rotlhi3" 5826 [(set (match_operand:HI 0 "register_operand" "") 5827 (rotate:HI (match_operand:HI 1 "register_operand" "") 5828 (match_operand:HI 2 "general_operand" "")))] 5829 "" 5830 " 5831{ 5832 if (GET_CODE (operands[2]) != CONST_INT) 5833 { 5834 rtx scratch = gen_reg_rtx (HImode); 5835 operand1 = force_reg (HImode, operand1); 5836 5837 emit_move_insn (scratch, operands[2]); 5838 emit_insn (gen_rtx (PARALLEL, VOIDmode, 5839 gen_rtvec (2, gen_rtx (SET, VOIDmode, 5840 operand0, 5841 gen_rtx_ROTATE (HImode, 5842 operand1, scratch)), 5843 gen_rtx (CLOBBER, VOIDmode, scratch)))); 5844 DONE; 5845 } 5846}") 5847 5848(define_insn "rotlhi3_const" 5849 [(set (match_operand:HI 0 "register_operand" "=d") 5850 (rotate:HI (match_operand:HI 1 "register_operand" "0") 5851 (match_operand:HI 2 "const_int_operand" "i")))] 5852 "" 5853 "* 5854{ 5855 m68hc11_gen_rotate (ROTATE, insn, operands); 5856 return \"\"; 5857}") 5858 5859(define_insn "*rotlhi3" 5860 [(set (match_operand:HI 0 "register_operand" "=d,*x") 5861 (rotate:HI (match_operand:HI 1 "register_operand" "0,0") 5862 (match_operand:HI 2 "general_operand" "+x,+d"))) 5863 (clobber (match_dup 2))] 5864 "" 5865 "* 5866{ 5867 if (A_REG_P (operands[0])) 5868 return \"#\"; 5869 5870 return \"bsr\\t___rotlhi3\"; 5871}") 5872 5873(define_expand "rotrhi3" 5874 [(set (match_operand:HI 0 "register_operand" "") 5875 (rotatert:HI (match_operand:HI 1 "general_operand" "") 5876 (match_operand:HI 2 "general_operand" "")))] 5877 "" 5878 " 5879{ 5880 if (GET_CODE (operands[2]) != CONST_INT) 5881 { 5882 rtx scratch = gen_reg_rtx (HImode); 5883 operand1 = force_reg (HImode, operand1); 5884 5885 emit_move_insn (scratch, operands[2]); 5886 emit_insn (gen_rtx (PARALLEL, VOIDmode, 5887 gen_rtvec (2, gen_rtx (SET, VOIDmode, 5888 operand0, 5889 gen_rtx_ROTATERT (HImode, 5890 operand1, scratch)), 5891 gen_rtx (CLOBBER, VOIDmode, scratch)))); 5892 DONE; 5893 } 5894}") 5895 5896(define_insn "rotrhi3_const" 5897 [(set (match_operand:HI 0 "register_operand" "=d") 5898 (rotatert:HI (match_operand:HI 1 "register_operand" "0") 5899 (match_operand:HI 2 "const_int_operand" "i")))] 5900 "" 5901 "* 5902{ 5903 m68hc11_gen_rotate (ROTATERT, insn, operands); 5904 return \"\"; 5905}") 5906 5907(define_insn "*rotrhi3" 5908 [(set (match_operand:HI 0 "register_operand" "=d,*x") 5909 (rotatert:HI (match_operand:HI 1 "register_operand" "0,0") 5910 (match_operand:HI 2 "general_operand" "+x,+d"))) 5911 (clobber (match_dup 2))] 5912 "" 5913 "* 5914{ 5915 if (A_REG_P (operands[0])) 5916 return \"#\"; 5917 5918 return \"bsr\\t___rotrhi3\"; 5919}") 5920 5921;; Split a shift operation on an address register in a shift 5922;; on D_REGNUM. 5923(define_split /* "*rotrhi3_addr" */ 5924 [(set (match_operand:HI 0 "hard_addr_reg_operand" "") 5925 (match_operator:HI 3 "m68hc11_shift_operator" 5926 [(match_operand:HI 1 "register_operand" "") 5927 (match_operand:HI 2 "register_operand" "")])) 5928 (clobber (match_dup 2))] 5929 "z_replacement_completed == 2" 5930 [(parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 5931 (set (match_dup 0) (reg:HI D_REGNUM))]) 5932 (parallel [(set (reg:HI D_REGNUM) 5933 (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)])) 5934 (clobber (match_dup 0))]) 5935 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 5936 (set (match_dup 0) (reg:HI D_REGNUM))])] 5937 "") 5938 5939;;-------------------------------------------------------------------- 5940;;- 68HC12 Decrement/Increment and branch 5941;;-------------------------------------------------------------------- 5942;; These patterns are used by loop optimization as well as peephole2 5943;; They must handle reloading themselves and the scratch register 5944;; is used for that. Even if we accept memory operand, we must not 5945;; accept them on the predicate because it might create too many reloads. 5946;; (specially on HC12 due to its auto-incdec addressing modes). 5947;; 5948(define_expand "decrement_and_branch_until_zero" 5949 [(parallel [(set (pc) 5950 (if_then_else 5951 (ne (plus:HI (match_operand:HI 0 "register_operand" "") 5952 (const_int 0)) 5953 (const_int 1)) 5954 (label_ref (match_operand 1 "" "")) 5955 (pc))) 5956 (set (match_dup 0) 5957 (plus:HI (match_dup 0) 5958 (const_int -1))) 5959 (clobber (match_scratch:HI 2 ""))])] 5960 "TARGET_M6812" 5961 "") 5962 5963(define_expand "doloop_end" 5964 [(use (match_operand 0 "" "")) ; loop pseudo 5965 (use (match_operand 1 "" "")) ; iterations; zero if unknown 5966 (use (match_operand 2 "" "")) ; max iterations 5967 (use (match_operand 3 "" "")) ; loop level 5968 (use (match_operand 4 "" ""))] ; label 5969 "TARGET_M6812" 5970 " 5971{ 5972 /* Reject non-constant loops as it generates bigger code due to 5973 the handling of the loop register. We can do better by using 5974 the peephole2 dbcc/ibcc patterns. */ 5975 if (INTVAL (operands[1]) == 0) 5976 { 5977 FAIL; 5978 } 5979 if (GET_MODE (operands[0]) == HImode) 5980 { 5981 emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0], 5982 gen_rtx (NE, HImode), 5983 operands[4])); 5984 DONE; 5985 } 5986 if (GET_MODE (operands[0]) == QImode) 5987 { 5988 emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0], 5989 gen_rtx (NE, QImode), 5990 operands[4])); 5991 DONE; 5992 } 5993 5994 FAIL; 5995}") 5996 5997;; Decrement-and-branch insns. 5998(define_insn "m68hc12_dbcc_dec_hi" 5999 [(set (pc) 6000 (if_then_else 6001 (match_operator 1 "m68hc11_eq_compare_operator" 6002 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z") 6003 (const_int 1)]) 6004 (label_ref (match_operand 2 "" "")) 6005 (pc))) 6006 (set (match_dup 0) 6007 (plus:HI (match_dup 0) (const_int -1))) 6008 (clobber (match_scratch:HI 3 "=X,dxy"))] 6009 "TARGET_M6812" 6010 "* 6011{ 6012 if (!H_REG_P (operands[0])) 6013 return \"#\"; 6014 6015 CC_STATUS_INIT; 6016 if (GET_CODE (operands[1]) == EQ) 6017 return \"dbeq\\t%0,%l2\"; 6018 else 6019 return \"dbne\\t%0,%l2\"; 6020}") 6021 6022;; Decrement-and-branch insns. 6023(define_insn "m68hc12_dbcc_inc_hi" 6024 [(set (pc) 6025 (if_then_else 6026 (match_operator 1 "m68hc11_eq_compare_operator" 6027 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z") 6028 (const_int -1)]) 6029 (label_ref (match_operand 2 "" "")) 6030 (pc))) 6031 (set (match_dup 0) 6032 (plus:HI (match_dup 0) (const_int 1))) 6033 (clobber (match_scratch:HI 3 "=X,dxy"))] 6034 "TARGET_M6812" 6035 "* 6036{ 6037 if (!H_REG_P (operands[0])) 6038 return \"#\"; 6039 6040 CC_STATUS_INIT; 6041 if (GET_CODE (operands[1]) == EQ) 6042 return \"ibeq\\t%0,%l2\"; 6043 else 6044 return \"ibeq\\t%0,%l2\"; 6045}") 6046 6047;; Decrement-and-branch (QImode). 6048(define_insn "m68hc12_dbcc_dec_qi" 6049 [(set (pc) 6050 (if_then_else 6051 (match_operator 1 "m68hc11_eq_compare_operator" 6052 [(match_operand:QI 0 "register_operand" "+d,m*u*A") 6053 (const_int 1)]) 6054 (label_ref (match_operand 2 "" "")) 6055 (pc))) 6056 (set (match_dup 0) 6057 (plus:QI (match_dup 0) (const_int -1))) 6058 (clobber (match_scratch:QI 3 "=X,d"))] 6059 "TARGET_M6812" 6060 "* 6061{ 6062 if (!D_REG_P (operands[0])) 6063 return \"#\"; 6064 6065 CC_STATUS_INIT; 6066 if (GET_CODE (operands[1]) == EQ) 6067 return \"dbeq\\tb,%l2\"; 6068 else 6069 return \"dbne\\tb,%l2\"; 6070}") 6071 6072;; Increment-and-branch (QImode). 6073(define_insn "m68hc12_dbcc_inc_qi" 6074 [(set (pc) 6075 (if_then_else 6076 (match_operator 1 "m68hc11_eq_compare_operator" 6077 [(match_operand:QI 0 "register_operand" "+d,m*u*A") 6078 (const_int -1)]) 6079 (label_ref (match_operand 2 "" "")) 6080 (pc))) 6081 (set (match_dup 0) 6082 (plus:QI (match_dup 0) (const_int 1))) 6083 (clobber (match_scratch:QI 3 "=X,d"))] 6084 "TARGET_M6812" 6085 "* 6086{ 6087 if (!D_REG_P (operands[0])) 6088 return \"#\"; 6089 6090 CC_STATUS_INIT; 6091 if (GET_CODE (operands[1]) == EQ) 6092 return \"ibeq\\tb,%l2\"; 6093 else 6094 return \"ibeq\\tb,%l2\"; 6095}") 6096 6097;; Split the above to handle the case where operand 0 is in memory 6098;; (a register that couldn't get a hard register) 6099(define_split 6100 [(set (pc) 6101 (if_then_else 6102 (match_operator 3 "m68hc11_eq_compare_operator" 6103 [(match_operand:HI 0 "general_operand" "") 6104 (match_operand:HI 1 "const_int_operand" "")]) 6105 (label_ref (match_operand 4 "" "")) 6106 (pc))) 6107 (set (match_dup 0) 6108 (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" ""))) 6109 (clobber (match_operand:HI 5 "hard_reg_operand" ""))] 6110 "TARGET_M6812 && reload_completed" 6111 [(set (match_dup 5) (match_dup 0)) 6112 (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2))) 6113 (set (match_dup 0) (match_dup 5)) 6114 (set (pc) 6115 (if_then_else (match_op_dup 3 6116 [(match_dup 5) (const_int 0)]) 6117 (label_ref (match_dup 4)) (pc)))] 6118 "") 6119 6120;; Split the above to handle the case where operand 0 is in memory 6121;; (a register that couldn't get a hard register) 6122(define_split 6123 [(set (pc) 6124 (if_then_else 6125 (match_operator 3 "m68hc11_eq_compare_operator" 6126 [(match_operand:QI 0 "general_operand" "") 6127 (match_operand:QI 1 "const_int_operand" "")]) 6128 (label_ref (match_operand 4 "" "")) 6129 (pc))) 6130 (set (match_dup 0) 6131 (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" ""))) 6132 (clobber (match_operand:QI 5 "hard_reg_operand" ""))] 6133 "TARGET_M6812 && reload_completed" 6134 [(set (match_dup 5) (match_dup 0)) 6135 (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2))) 6136 (set (match_dup 0) (match_dup 5)) 6137 (set (pc) 6138 (if_then_else (match_op_dup 3 6139 [(match_dup 5) (const_int 0)]) 6140 (label_ref (match_dup 4)) (pc)))] 6141 "") 6142 6143;;-------------------------------------------------------------------- 6144;;- Jumps and transfers 6145;;-------------------------------------------------------------------- 6146(define_insn "jump" 6147 [(set (pc) 6148 (label_ref (match_operand 0 "" "")))] 6149 "" 6150 "bra\\t%l0") 6151 6152(define_expand "beq" 6153 [(set (pc) 6154 (if_then_else (eq (cc0) 6155 (const_int 0)) 6156 (label_ref (match_operand 0 "" "")) 6157 (pc)))] 6158 "" 6159 " 6160{ 6161 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0, 6162 m68hc11_compare_op1, 6163 operands[0]); 6164 DONE; 6165}") 6166 6167(define_expand "bne" 6168 [(set (pc) 6169 (if_then_else (ne (cc0) 6170 (const_int 0)) 6171 (label_ref (match_operand 0 "" "")) 6172 (pc)))] 6173 "" 6174 " 6175{ 6176 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0, 6177 m68hc11_compare_op1, 6178 operands[0]); 6179 DONE; 6180}") 6181 6182(define_expand "bgt" 6183 [(set (pc) 6184 (if_then_else (gt (cc0) 6185 (const_int 0)) 6186 (label_ref (match_operand 0 "" "")) 6187 (pc)))] 6188 "" 6189 " 6190{ 6191 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0, 6192 m68hc11_compare_op1, 6193 operands[0]); 6194 DONE; 6195}") 6196 6197(define_expand "bgtu" 6198 [(set (pc) 6199 (if_then_else (gtu (cc0) 6200 (const_int 0)) 6201 (label_ref (match_operand 0 "" "")) 6202 (pc)))] 6203 "" 6204 " 6205{ 6206 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0, 6207 m68hc11_compare_op1, 6208 operands[0]); 6209 DONE; 6210}") 6211 6212(define_expand "blt" 6213 [(set (pc) 6214 (if_then_else (lt (cc0) 6215 (const_int 0)) 6216 (label_ref (match_operand 0 "" "")) 6217 (pc)))] 6218 "" 6219 " 6220{ 6221 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0, 6222 m68hc11_compare_op1, 6223 operands[0]); 6224 DONE; 6225}") 6226 6227(define_expand "bltu" 6228 [(set (pc) 6229 (if_then_else (ltu (cc0) 6230 (const_int 0)) 6231 (label_ref (match_operand 0 "" "")) 6232 (pc)))] 6233 "" 6234 " 6235{ 6236 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0, 6237 m68hc11_compare_op1, 6238 operands[0]); 6239 DONE; 6240}") 6241 6242(define_expand "bge" 6243 [(set (pc) 6244 (if_then_else (ge (cc0) 6245 (const_int 0)) 6246 (label_ref (match_operand 0 "" "")) 6247 (pc)))] 6248 "" 6249 " 6250{ 6251 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0, 6252 m68hc11_compare_op1, 6253 operands[0]); 6254 DONE; 6255}") 6256 6257(define_expand "bgeu" 6258 [(set (pc) 6259 (if_then_else (geu (cc0) 6260 (const_int 0)) 6261 (label_ref (match_operand 0 "" "")) 6262 (pc)))] 6263 "" 6264 " 6265{ 6266 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0, 6267 m68hc11_compare_op1, 6268 operands[0]); 6269 DONE; 6270}") 6271 6272(define_expand "ble" 6273 [(set (pc) 6274 (if_then_else (le (cc0) 6275 (const_int 0)) 6276 (label_ref (match_operand 0 "" "")) 6277 (pc)))] 6278 "" 6279 " 6280{ 6281 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0, 6282 m68hc11_compare_op1, 6283 operands[0]); 6284 DONE; 6285}") 6286 6287(define_expand "bleu" 6288 [(set (pc) 6289 (if_then_else (leu (cc0) 6290 (const_int 0)) 6291 (label_ref (match_operand 0 "" "")) 6292 (pc)))] 6293 "" 6294 " 6295{ 6296 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0, 6297 m68hc11_compare_op1, 6298 operands[0]); 6299 DONE; 6300}") 6301 6302;; 6303;; Test and branch instructions for 68HC12 for EQ and NE. 6304;; 'z' must not appear in the constraints because the z replacement 6305;; pass does not know how to restore the replacement register. 6306;; 6307(define_insn "*tbeq" 6308 [(set (pc) 6309 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy") 6310 (const_int 0)) 6311 (label_ref (match_operand 1 "" "")) 6312 (pc)))] 6313 "TARGET_M6812" 6314 "* 6315{ 6316 /* If the flags are already set correctly, use 'bne/beq' which are 6317 smaller and a little bit faster. This happens quite often due 6318 to reloading of operands[0]. In that case, flags are set correctly 6319 due to the load instruction. */ 6320 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) 6321 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) 6322 return \"beq\\t%l1\"; 6323 else 6324 return \"tbeq\\t%0,%l1\"; 6325}") 6326 6327(define_insn "*tbne" 6328 [(set (pc) 6329 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy") 6330 (const_int 0)) 6331 (label_ref (match_operand 1 "" "")) 6332 (pc)))] 6333 "TARGET_M6812" 6334 "* 6335{ 6336 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) 6337 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) 6338 return \"bne\\t%l1\"; 6339 else 6340 return \"tbne\\t%0,%l1\"; 6341}") 6342 6343;; 6344;; Test and branch with 8-bit register. Register must be B (or A). 6345;; 6346(define_insn "*tbeq8" 6347 [(set (pc) 6348 (if_then_else (eq (match_operand:QI 0 "register_operand" "d") 6349 (const_int 0)) 6350 (label_ref (match_operand 1 "" "")) 6351 (pc)))] 6352 "TARGET_M6812" 6353 "* 6354{ 6355 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) 6356 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) 6357 return \"beq\\t%l1\"; 6358 else 6359 return \"tbeq\\tb,%l1\"; 6360}") 6361 6362(define_insn "*tbne8" 6363 [(set (pc) 6364 (if_then_else (ne (match_operand:QI 0 "register_operand" "d") 6365 (const_int 0)) 6366 (label_ref (match_operand 1 "" "")) 6367 (pc)))] 6368 "TARGET_M6812" 6369 "* 6370{ 6371 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) 6372 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) 6373 return \"bne\\t%l1\"; 6374 else 6375 return \"tbne\\tb,%l1\"; 6376}") 6377 6378(define_insn "*beq" 6379 [(set (pc) 6380 (if_then_else (eq (cc0) 6381 (const_int 0)) 6382 (label_ref (match_operand 0 "" "")) 6383 (pc)))] 6384 "" 6385 "beq\\t%l0") 6386 6387(define_insn "*bne" 6388 [(set (pc) 6389 (if_then_else (ne (cc0) 6390 (const_int 0)) 6391 (label_ref (match_operand 0 "" "")) 6392 (pc)))] 6393 "" 6394 "bne\\t%l0") 6395 6396(define_insn "*bgt" 6397 [(set (pc) 6398 (if_then_else (gt (cc0) 6399 (const_int 0)) 6400 (label_ref (match_operand 0 "" "")) 6401 (pc)))] 6402 "" 6403 "bgt\\t%l0") 6404 6405(define_insn "*bgtu" 6406 [(set (pc) 6407 (if_then_else (gtu (cc0) 6408 (const_int 0)) 6409 (label_ref (match_operand 0 "" "")) 6410 (pc)))] 6411 "" 6412 "bhi\\t%l0") 6413 6414(define_insn "*blt" 6415 [(set (pc) 6416 (if_then_else (lt (cc0) 6417 (const_int 0)) 6418 (label_ref (match_operand 0 "" "")) 6419 (pc)))] 6420 "" 6421 "* 6422{ 6423 if (cc_prev_status.flags & CC_NO_OVERFLOW) 6424 return \"bmi\\t%l0\"; 6425 else 6426 return \"blt\\t%l0\"; 6427}") 6428 6429(define_insn "*bltu" 6430 [(set (pc) 6431 (if_then_else (ltu (cc0) 6432 (const_int 0)) 6433 (label_ref (match_operand 0 "" "")) 6434 (pc)))] 6435 "" 6436 "blo\\t%l0") 6437 6438(define_insn "*bge" 6439 [(set (pc) 6440 (if_then_else (ge (cc0) 6441 (const_int 0)) 6442 (label_ref (match_operand 0 "" "")) 6443 (pc)))] 6444 "" 6445 "* 6446{ 6447 if (cc_prev_status.flags & CC_NO_OVERFLOW) 6448 return \"bpl\\t%l0\"; 6449 else 6450 return \"bge\\t%l0\"; 6451}") 6452 6453(define_insn "*bgeu" 6454 [(set (pc) 6455 (if_then_else (geu (cc0) 6456 (const_int 0)) 6457 (label_ref (match_operand 0 "" "")) 6458 (pc)))] 6459 "" 6460 "bhs\\t%l0") 6461 6462(define_insn "*ble" 6463 [(set (pc) 6464 (if_then_else (le (cc0) 6465 (const_int 0)) 6466 (label_ref (match_operand 0 "" "")) 6467 (pc)))] 6468 "" 6469 "* 6470{ 6471 if (cc_prev_status.flags & CC_NO_OVERFLOW) 6472 return \"bmi\\t%l0\\n\\tbeq\\t%l0\"; 6473 else 6474 return \"ble\\t%l0\"; 6475}") 6476 6477(define_insn "*bleu" 6478 [(set (pc) 6479 (if_then_else (leu (cc0) 6480 (const_int 0)) 6481 (label_ref (match_operand 0 "" "")) 6482 (pc)))] 6483 "" 6484 "bls\\t%l0") 6485 6486;;-------------------------------------------------------------------- 6487;;- Negative test and branch 6488;;-------------------------------------------------------------------- 6489(define_insn "" 6490 [(set (pc) 6491 (if_then_else (eq (cc0) 6492 (const_int 0)) 6493 (pc) 6494 (label_ref (match_operand 0 "" ""))))] 6495 "" 6496 "bne\\t%l0") 6497 6498(define_insn "" 6499 [(set (pc) 6500 (if_then_else (ne (cc0) 6501 (const_int 0)) 6502 (pc) 6503 (label_ref (match_operand 0 "" ""))))] 6504 "" 6505 "beq\\t%l0") 6506 6507(define_insn "" 6508 [(set (pc) 6509 (if_then_else (gt (cc0) 6510 (const_int 0)) 6511 (pc) 6512 (label_ref (match_operand 0 "" ""))))] 6513 "" 6514 "* 6515{ 6516 if (cc_prev_status.flags & CC_NO_OVERFLOW) 6517 return \"bmi\\t%l0\\n\\tbeq\\t%l0\"; 6518 else 6519 return \"ble\\t%l0\"; 6520}") 6521 6522(define_insn "" 6523 [(set (pc) 6524 (if_then_else (gtu (cc0) 6525 (const_int 0)) 6526 (pc) 6527 (label_ref (match_operand 0 "" ""))))] 6528 "" 6529 "bls\\t%l0") 6530 6531(define_insn "" 6532 [(set (pc) 6533 (if_then_else (lt (cc0) 6534 (const_int 0)) 6535 (pc) 6536 (label_ref (match_operand 0 "" ""))))] 6537 "" 6538 "* 6539{ 6540 if (cc_prev_status.flags & CC_NO_OVERFLOW) 6541 return \"bpl\\t%l0\"; 6542 else 6543 return \"bge\\t%l0\"; 6544}") 6545 6546(define_insn "" 6547 [(set (pc) 6548 (if_then_else (ltu (cc0) 6549 (const_int 0)) 6550 (pc) 6551 (label_ref (match_operand 0 "" ""))))] 6552 "" 6553 "bhs\\t%l0") 6554 6555(define_insn "" 6556 [(set (pc) 6557 (if_then_else (ge (cc0) 6558 (const_int 0)) 6559 (pc) 6560 (label_ref (match_operand 0 "" ""))))] 6561 "" 6562 "* 6563{ 6564 if (cc_prev_status.flags & CC_NO_OVERFLOW) 6565 return \"bmi\\t%l0\"; 6566 else 6567 return \"blt\\t%l0\"; 6568}") 6569 6570(define_insn "" 6571 [(set (pc) 6572 (if_then_else (geu (cc0) 6573 (const_int 0)) 6574 (pc) 6575 (label_ref (match_operand 0 "" ""))))] 6576 "" 6577 "blo\\t%l0") 6578 6579(define_insn "" 6580 [(set (pc) 6581 (if_then_else (le (cc0) 6582 (const_int 0)) 6583 (pc) 6584 (label_ref (match_operand 0 "" ""))))] 6585 "" 6586 "bgt\\t%l0") 6587 6588(define_insn "" 6589 [(set (pc) 6590 (if_then_else (leu (cc0) 6591 (const_int 0)) 6592 (pc) 6593 (label_ref (match_operand 0 "" ""))))] 6594 "" 6595 "bhi\\t%l0") 6596 6597;;-------------------------------------------------------------------- 6598;;- Calls 6599;;-------------------------------------------------------------------- 6600;; 6601;;- Call a function that returns no value. 6602(define_insn "call" 6603 [(call (match_operand:QI 0 "memory_operand" "m") 6604 (match_operand:SI 1 "general_operand" "g"))] 6605 ;; Operand 1 not really used on the m68hc11. 6606 "" 6607 "* 6608{ 6609 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) 6610 { 6611 if (m68hc11_is_far_symbol (operands[0])) 6612 { 6613 if (TARGET_M6812) 6614 { 6615 output_asm_insn (\"call\\t%0\", operands); 6616 return \"\"; 6617 } 6618 else 6619 { 6620 output_asm_insn (\"pshb\", operands); 6621 output_asm_insn (\"ldab\\t#%%page(%0)\", operands); 6622 output_asm_insn (\"ldy\\t#%%addr(%0)\", operands); 6623 return \"jsr\\t__call_a32\"; 6624 } 6625 } 6626 if (m68hc11_is_trap_symbol (operands[0])) 6627 return \"swi\"; 6628 else 6629 return \"bsr\\t%0\"; 6630 } 6631 else 6632 { 6633 return \"jsr\\t%0\"; 6634 } 6635}") 6636 6637(define_insn "call_value" 6638 [(set (match_operand 0 "" "=g") 6639 (call (match_operand:QI 1 "memory_operand" "m") 6640 (match_operand:SI 2 "general_operand" "g")))] 6641 "" 6642 "* 6643{ 6644 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) 6645 { 6646 if (m68hc11_is_far_symbol (operands[1])) 6647 { 6648 if (TARGET_M6812) 6649 { 6650 output_asm_insn (\"call\\t%1\", operands); 6651 return \"\"; 6652 } 6653 else 6654 { 6655 output_asm_insn (\"pshb\", operands); 6656 output_asm_insn (\"ldab\\t#%%page(%1)\", operands); 6657 output_asm_insn (\"ldy\\t#%%addr(%1)\", operands); 6658 return \"jsr\\t__call_a32\"; 6659 } 6660 } 6661 if (m68hc11_is_trap_symbol (operands[1])) 6662 return \"swi\"; 6663 else 6664 return \"bsr\\t%1\"; 6665 } 6666 else 6667 { 6668 return \"jsr\\t%1\"; 6669 } 6670}") 6671 6672;; Call subroutine returning any type. 6673 6674(define_expand "untyped_call" 6675 [(parallel [(call (match_operand 0 "" "") 6676 (const_int 0)) 6677 (match_operand 1 "" "") 6678 (match_operand 2 "" "")])] 6679 "" 6680 " 6681{ 6682 int i; 6683 6684 emit_call_insn (gen_call (operands[0], const0_rtx)); 6685 6686 for (i = 0; i < XVECLEN (operands[2], 0); i++) 6687 { 6688 rtx set = XVECEXP (operands[2], 0, i); 6689 emit_move_insn (SET_DEST (set), SET_SRC (set)); 6690 } 6691 6692 /* The optimizer does not know that the call sets the function value 6693 registers we stored in the result block. We avoid problems by 6694 claiming that all hard registers are used and clobbered at this 6695 point. */ 6696 emit_insn (gen_blockage ()); 6697 6698 DONE; 6699}") 6700 6701;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 6702;; all of memory. This blocks insns from being moved across this point. 6703 6704(define_insn "blockage" 6705 [(unspec_volatile [(const_int 0)] 0)] 6706 "" 6707 "") 6708 6709(define_insn "nop" 6710 [(const_int 0)] 6711 "" 6712 "nop") 6713 6714(define_expand "prologue" 6715 [(const_int 0)] 6716 "" 6717 " 6718{ 6719 expand_prologue (); 6720 DONE; 6721}") 6722 6723(define_expand "epilogue" 6724 [(return)] 6725 "" 6726 " 6727{ 6728 expand_epilogue (); 6729 DONE; 6730}") 6731 6732;; Used for frameless functions which save no regs and allocate no locals. 6733(define_expand "return" 6734 [(return)] 6735 "reload_completed && m68hc11_total_frame_size () == 0" 6736 " 6737{ 6738 int ret_size = 0; 6739 6740 if (current_function_return_rtx) 6741 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx)); 6742 6743 /* Emit use notes only when HAVE_return is true. */ 6744 if (m68hc11_total_frame_size () != 0) 6745 ret_size = 0; 6746 6747 if (ret_size && ret_size <= 2) 6748 { 6749 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, 6750 gen_rtvec (2, gen_rtx_RETURN (VOIDmode), 6751 gen_rtx_USE (VOIDmode, 6752 gen_rtx_REG (HImode, 1))))); 6753 DONE; 6754 } 6755 if (ret_size) 6756 { 6757 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, 6758 gen_rtvec (2, gen_rtx_RETURN (VOIDmode), 6759 gen_rtx_USE (VOIDmode, 6760 gen_rtx_REG (SImode, 0))))); 6761 DONE; 6762 } 6763}") 6764 6765(define_insn "*return_void" 6766 [(return)] 6767 "reload_completed" 6768 "* 6769{ 6770 rtx next = next_active_insn (insn); 6771 6772 if (next 6773 && GET_CODE (next) == JUMP_INSN 6774 && GET_CODE (PATTERN (next)) == RETURN) 6775 return \"\"; 6776 if (current_function_interrupt || current_function_trap) 6777 return \"rti\"; 6778 else if (!current_function_far) 6779 return \"rts\"; 6780 else if (TARGET_M6812) 6781 return \"rtc\"; 6782 else 6783 { 6784 int ret_size = 0; 6785 6786 if (current_function_return_rtx) 6787 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx)); 6788 6789 if (ret_size == 0) 6790 return \"jmp\\t__return_void\"; 6791 if (ret_size <= 2) 6792 return \"jmp\\t__return_16\"; 6793 if (ret_size <= 4) 6794 return \"jmp\\t__return_32\"; 6795 return \"jmp\\t__return_16\"; 6796 } 6797}") 6798 6799(define_insn "*return_16bit" 6800 [(return) 6801 (use (reg:HI D_REGNUM))] 6802 "reload_completed && m68hc11_total_frame_size () == 0" 6803 "* 6804{ 6805 rtx next = next_active_insn (insn); 6806 6807 if (next 6808 && GET_CODE (next) == JUMP_INSN 6809 && GET_CODE (PATTERN (next)) == RETURN) 6810 return \"\"; 6811 if (current_function_interrupt || current_function_trap) 6812 return \"rti\"; 6813 else if (!current_function_far) 6814 return \"rts\"; 6815 else if (TARGET_M6812) 6816 return \"rtc\"; 6817 else 6818 return \"jmp\\t__return_16\"; 6819}") 6820 6821(define_insn "*return_32bit" 6822 [(return) 6823 (use (reg:SI 0))] 6824 "reload_completed && m68hc11_total_frame_size () == 0" 6825 "* 6826{ 6827 rtx next = next_active_insn (insn); 6828 6829 if (next 6830 && GET_CODE (next) == JUMP_INSN 6831 && GET_CODE (PATTERN (next)) == RETURN) 6832 return \"\"; 6833 if (current_function_interrupt || current_function_trap) 6834 return \"rti\"; 6835 else if (!current_function_far) 6836 return \"rts\"; 6837 else if (TARGET_M6812) 6838 return \"rtc\"; 6839 else 6840 return \"jmp\\t__return_32\"; 6841}") 6842 6843(define_insn "indirect_jump" 6844 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))] 6845 "" 6846 "jmp\\t0,%0") 6847 6848;;-------------------------------------------------------------------- 6849;;- Table jump 6850;;-------------------------------------------------------------------- 6851;; 6852;; Operand 0 is the address of the table element to use 6853;; operand 1 is the CODE_LABEL for the table 6854;;-------------------------------------------------------------------- 6855(define_expand "tablejump" 6856 [(parallel [(set (pc) (match_operand 0 "" "")) 6857 (use (label_ref (match_operand 1 "" "")))])] 6858 "" 6859 "") 6860 6861(define_insn "*jump_indirect" 6862 [(parallel [ 6863 (set (pc) (match_operand:HI 0 "register_operand" "xy")) 6864 (use (label_ref (match_operand 1 "" "")))])] 6865 "" 6866 "jmp\\t0,%0") 6867 6868;;-------------------------------------------------------------------- 6869;;- Peepholes 6870;;-------------------------------------------------------------------- 6871 6872;;-------------------------------------------------------------------- 6873;;- 68HC12 dbcc/ibcc peepholes 6874;;-------------------------------------------------------------------- 6875;; 6876;; Replace: "addd #-1; bne L1" into "dbne d,L1" 6877;; "addd #-1; beq L1" into "dbeq d,L1" 6878;; "addd #1; bne L1" into "ibne d,L1" 6879;; "addd #1; beq L1" into "ibeq d,L1" 6880;; 6881(define_peephole2 6882 [(set (match_operand:HI 0 "hard_reg_operand" "") 6883 (plus:HI (match_dup 0) 6884 (match_operand:HI 1 "const_int_operand" ""))) 6885 (set (pc) 6886 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator" 6887 [(match_dup 0) 6888 (const_int 0)]) 6889 (label_ref (match_operand 3 "" "")) (pc)))] 6890 "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)" 6891 [(parallel [ 6892 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)]) 6893 (label_ref (match_dup 3)) (pc))) 6894 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1))) 6895 (clobber (match_dup 4))])] 6896 "operands[4] = gen_rtx_SCRATCH(HImode); 6897 operands[5] = GEN_INT (-INTVAL (operands[1]));") 6898 6899 6900;; 6901;; Replace: "addb #-1; bne L1" into "dbne b,L1" 6902;; "addb #-1; beq L1" into "dbeq b,L1" 6903;; 6904(define_peephole2 6905 [(set (match_operand:QI 0 "hard_reg_operand" "") 6906 (plus:QI (match_dup 0) 6907 (match_operand:QI 1 "const_int_operand" ""))) 6908 (set (pc) 6909 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator" 6910 [(match_dup 0) 6911 (const_int 0)]) 6912 (label_ref (match_operand 3 "" "")) (pc)))] 6913 "TARGET_M6812 && D_REG_P (operands[0]) 6914 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)" 6915 [(parallel [ 6916 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)]) 6917 (label_ref (match_dup 3)) (pc))) 6918 (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1))) 6919 (clobber (match_dup 4))])] 6920 "operands[4] = gen_rtx_SCRATCH(QImode); 6921 operands[5] = GEN_INT (-INTVAL (operands[1]));") 6922 6923 6924;;-------------------------------------------------------------------- 6925;;- Move peephole2 6926;;-------------------------------------------------------------------- 6927 6928;; 6929;; Replace "leas 2,sp" with a "pulx" or a "puly". 6930;; On 68HC12, this is one cycle slower but one byte smaller. 6931;; pr target/6899: This peephole is not valid because a register CSE 6932;; pass removes the pulx/puly. 6933;; 6934(define_peephole2 6935 [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2))) 6936 (match_scratch:HI 0 "xy")] 6937 "0 && TARGET_M6812 && optimize_size" 6938 [(set (match_dup 0) (match_dup 1))] 6939 "operands[1] = gen_rtx (MEM, HImode, 6940 gen_rtx (POST_INC, HImode, 6941 gen_rtx_REG (HImode, HARD_SP_REGNUM)));") 6942 6943;; 6944;; Optimize memory<->memory moves when the value is also loaded in 6945;; a register. 6946;; 6947(define_peephole2 6948 [(set (match_operand:QI 0 "memory_operand" "") 6949 (match_operand:QI 1 "memory_operand" "")) 6950 (set (reg:QI D_REGNUM) 6951 (match_operand:QI 2 "memory_operand" ""))] 6952 "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0])) 6953 || (GET_CODE (XEXP (operands[0], 0)) == REG 6954 && GET_CODE (XEXP (operands[2], 0)) == POST_INC 6955 && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))" 6956 [(set (reg:QI D_REGNUM) (match_dup 1)) 6957 (set (match_dup 2) (reg:QI D_REGNUM))] 6958 "") 6959 6960;; 6961;; Remove a possible move before a compare instruction when that 6962;; move will go in a dead register. Compare with the source then. 6963;; 6964(define_peephole2 6965 [(set (match_operand:HI 0 "hard_reg_operand" "") 6966 (match_operand:HI 1 "hard_reg_operand" "")) 6967 (set (cc0) 6968 (compare (match_dup 0) 6969 (match_operand:HI 2 "cmp_operand" "")))] 6970 "(X_REG_P (operands[1]) || Y_REG_P (operands[1])) 6971 && peep2_reg_dead_p (2, operands[0]) 6972 && !reg_mentioned_p (operands[0], operands[2])" 6973 [(set (cc0) (compare (match_dup 1) (match_dup 2)))] 6974 "") 6975 6976;; 6977;; Optimize loading a constant to memory when that same constant 6978;; is loaded to a hard register. Switch the two to use the register 6979;; for memory initialization. In most cases, the constant is 0. 6980;; 6981(define_peephole2 6982 [(set (match_operand:HI 0 "memory_operand" "") 6983 (match_operand:HI 1 "immediate_operand" "")) 6984 (set (match_operand:HI 2 "hard_reg_operand" "") 6985 (match_dup 1))] 6986 "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2])) 6987 && !reg_mentioned_p (operands[2], operands[0])" 6988 [(set (match_dup 2) (match_dup 1)) 6989 (set (match_dup 0) (match_dup 2))] 6990 "") 6991 6992;; 6993;; Reorganize to optimize address computations. 6994;; 6995(define_peephole2 6996 [(set (match_operand:HI 0 "hard_reg_operand" "") 6997 (match_operand:HI 1 "const_int_operand" "")) 6998 (set (match_dup 0) 6999 (plus:HI (match_dup 0) 7000 (match_operand:HI 2 "general_operand" "")))] 7001 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)" 7002 [(set (match_dup 0) (match_dup 2)) 7003 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] 7004 "") 7005 7006;; 7007;; Optimize an address register increment and a compare to use 7008;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn 7009;; before reload, but can be enabled after). 7010;; 7011(define_peephole2 7012 [(set (match_operand:HI 0 "hard_reg_operand" "") 7013 (plus:HI (match_dup 0) 7014 (match_operand:HI 1 "const_int_operand" ""))) 7015 (set (cc0) 7016 (match_operand:QI 2 "memory_operand" ""))] 7017 "TARGET_AUTO_INC_DEC 7018 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) 7019 && reg_mentioned_p (operands[0], operands[2])" 7020 [(set (cc0) (match_dup 3))] 7021 "if (INTVAL (operands[1]) == 1) 7022 operands[3] = gen_rtx (MEM, QImode, 7023 gen_rtx (PRE_INC, HImode, operands[0])); 7024 else 7025 operands[3] = gen_rtx (MEM, QImode, 7026 gen_rtx (PRE_DEC, HImode, operands[0])); 7027 ") 7028 7029;; 7030;; Likewise for compare. 7031;; 7032(define_peephole2 7033 [(set (match_operand:HI 0 "hard_reg_operand" "") 7034 (plus:HI (match_dup 0) 7035 (match_operand:HI 1 "const_int_operand" ""))) 7036 (set (cc0) 7037 (compare (match_operand:QI 2 "hard_reg_operand" "") 7038 (match_operand:QI 3 "memory_operand" "")))] 7039 "TARGET_AUTO_INC_DEC 7040 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) 7041 && reg_mentioned_p (operands[0], operands[3])" 7042 [(set (cc0) (compare (match_dup 2) (match_dup 4)))] 7043 "if (INTVAL (operands[1]) == 1) 7044 operands[4] = gen_rtx (MEM, QImode, 7045 gen_rtx (PRE_INC, HImode, operands[0])); 7046 else 7047 operands[4] = gen_rtx (MEM, QImode, 7048 gen_rtx (PRE_DEC, HImode, operands[0])); 7049 ") 7050 7051(define_peephole2 7052 [(set (match_operand:HI 0 "hard_reg_operand" "") 7053 (plus:HI (match_dup 0) 7054 (match_operand:HI 1 "const_int_operand" ""))) 7055 (set (cc0) 7056 (compare (match_operand:QI 2 "memory_operand" "") 7057 (match_operand:QI 3 "hard_reg_operand" "")))] 7058 "TARGET_AUTO_INC_DEC 7059 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) 7060 && reg_mentioned_p (operands[0], operands[2])" 7061 [(set (cc0) (compare (match_dup 4) (match_dup 3)))] 7062 "if (INTVAL (operands[1]) == 1) 7063 operands[4] = gen_rtx (MEM, QImode, 7064 gen_rtx (PRE_INC, HImode, operands[0])); 7065 else 7066 operands[4] = gen_rtx (MEM, QImode, 7067 gen_rtx (PRE_DEC, HImode, operands[0])); 7068 ") 7069 7070;; 7071;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n" 7072;; (avoids many temporary moves because we can't add sp to another reg easily) 7073;; 7074(define_peephole2 7075 [(set (match_operand:HI 0 "hard_reg_operand" "") 7076 (match_operand:HI 1 "const_int_operand" "")) 7077 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))] 7078 "" 7079 [(set (match_dup 0) (reg:HI SP_REGNUM)) 7080 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] 7081 "") 7082 7083;; 7084;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N". 7085;; 7086(define_peephole2 7087 [(set (match_operand:HI 0 "hard_reg_operand" "") 7088 (match_operand:HI 1 "const_int_operand" "")) 7089 (set (match_dup 0) 7090 (plus:HI (match_dup 0) 7091 (match_operand:HI 2 "general_operand" "")))] 7092 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)" 7093 [(set (match_dup 0) (match_dup 2)) 7094 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] 7095 "") 7096 7097;; 7098;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx". 7099;; 7100(define_peephole2 7101 [(set (match_operand:HI 0 "hard_reg_operand" "") 7102 (match_operand:HI 1 "memory_operand" "")) 7103 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) 7104 (match_dup 0)) 7105 (match_scratch:HI 2 "x")] 7106 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])" 7107 [(set (match_dup 2) (match_dup 1)) 7108 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))] 7109 "") 7110 7111;; 7112;; Replace a "ldd <mem>; addd #N; std <mem>" into a 7113;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register 7114;; and the constant is small. 7115;; 7116(define_peephole2 7117 [(set (match_operand:HI 0 "hard_reg_operand" "") 7118 (match_operand:HI 1 "general_operand" "")) 7119 (set (match_dup 0) (plus:HI (match_dup 0) 7120 (match_operand:HI 2 "const_int_operand" ""))) 7121 (set (match_operand:HI 3 "nonimmediate_operand" "") 7122 (match_dup 0)) 7123 (match_scratch:HI 4 "xy")] 7124 "D_REG_P (operands[0]) 7125 && (TARGET_M6812 7126 || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2)) 7127 && peep2_reg_dead_p (3, operands[0])" 7128 [(set (match_dup 4) (match_dup 1)) 7129 (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2))) 7130 (set (match_dup 3) (match_dup 4))] 7131 "if (reg_mentioned_p (operands[4], operands[1])) FAIL; 7132 if (reg_mentioned_p (operands[4], operands[3])) FAIL;") 7133 7134;; 7135;; This peephole catches the address computations generated by the reload 7136;; pass. 7137(define_peephole 7138 [(set (match_operand:HI 0 "hard_reg_operand" "xy") 7139 (match_operand:HI 1 "const_int_operand" "")) 7140 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 7141 (set (match_dup 0) (reg:HI D_REGNUM))]) 7142 (set (reg:HI D_REGNUM) 7143 (plus (reg:HI D_REGNUM) 7144 (match_operand:HI 2 "general_operand" ""))) 7145 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 7146 (set (match_dup 0) (reg:HI D_REGNUM))])] 7147 "(INTVAL (operands[1]) & 0x0FF) == 0" 7148 "* 7149{ 7150 int value_loaded = 1; 7151 7152 if (X_REG_P (operands[0]) || SP_REG_P (operands[2])) 7153 { 7154 rtx ops[2]; 7155 7156 ops[0] = operands[0]; 7157 ops[1] = operands[2]; 7158 m68hc11_gen_movhi (insn, ops); 7159 output_asm_insn (\"xgd%0\", operands); 7160 } 7161 else if (Y_REG_P (operands[0])) 7162 { 7163 if (reg_mentioned_p (iy_reg, operands[2])) 7164 output_asm_insn (\"ldy\\t%2\", operands); 7165 else 7166 value_loaded = 0; 7167 output_asm_insn (\"xgdy\", operands); 7168 } 7169 else 7170 { 7171 output_asm_insn (\"ldd\\t%2\", operands); 7172 } 7173 7174 if (value_loaded == 0) 7175 output_asm_insn (\"ldd\\t%2\", operands); 7176 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100) 7177 output_asm_insn (\"inca\", operands); 7178 else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00) 7179 output_asm_insn (\"deca\", operands); 7180 else if (INTVAL (operands[1]) != 0) 7181 output_asm_insn (\"adda\\t%h1\", operands); 7182 7183 if (X_REG_P (operands[0])) 7184 return \"xgdx\"; 7185 else if (Y_REG_P (operands[0])) 7186 return \"xgdy\"; 7187 else 7188 return \"\"; 7189} 7190") 7191 7192(define_peephole 7193 [(set (match_operand:HI 0 "hard_reg_operand" "h") 7194 (match_operand:HI 1 "non_push_operand" "g")) 7195 (set (match_operand:HI 2 "hard_reg_operand" "h") 7196 (match_dup 0))] 7197 "find_regno_note (insn, REG_DEAD, REGNO (operands[0])) 7198 && !S_REG_P (operands[2])" 7199 "* 7200{ 7201 rtx ops[2]; 7202 7203 ops[0] = operands[2]; 7204 ops[1] = operands[1]; 7205 m68hc11_gen_movhi (insn, ops); 7206 return \"\"; 7207} 7208") 7209 7210(define_peephole 7211 [(set (match_operand:HI 0 "hard_reg_operand" "h") 7212 (match_operand:HI 1 "hard_reg_operand" "h")) 7213 (set (match_operand:HI 2 "non_push_operand" "g") 7214 (match_dup 0))] 7215 "find_regno_note (insn, REG_DEAD, REGNO (operands[0])) 7216 && !S_REG_P (operands[2])" 7217 "* 7218{ 7219 rtx ops[2]; 7220 7221 ops[0] = operands[2]; 7222 ops[1] = operands[1]; 7223 m68hc11_gen_movhi (insn, ops); 7224 return \"\"; 7225} 7226") 7227 7228;; 7229;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after 7230;; the set, so we don't need to emit anything. 'ins1' refers to the 7231;; (set ...) insn. 7232;; 7233(define_peephole 7234 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM)) 7235 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 7236 (set (match_dup 0) (reg:HI D_REGNUM))])] 7237 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)" 7238 "* 7239{ 7240 cc_status = cc_prev_status; 7241 return \"\"; 7242} 7243") 7244 7245;; Same as above but due to some split, there may be a noop set 7246;; between the two. 7247(define_peephole 7248 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM)) 7249 (set (match_dup 0) (match_dup 0)) 7250 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 7251 (set (match_dup 0) (reg:HI D_REGNUM))])] 7252 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)" 7253 "* 7254{ 7255 cc_status = cc_prev_status; 7256 return \"\"; 7257} 7258") 7259 7260;; 7261;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead 7262;; and we must, at least, setup X/Y with value of D. 7263;; 7264(define_peephole 7265 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM)) 7266 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 7267 (set (match_dup 0) (reg:HI D_REGNUM))])] 7268 "" 7269 "* 7270{ 7271 rtx ops[2]; 7272 7273 ops[0] = operands[0]; 7274 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM); 7275 m68hc11_gen_movhi (insn, ops); 7276 return \"\"; 7277} 7278") 7279 7280;;; 7281;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't 7282;;; need to emit anything. Otherwise, we just need an copy of D to X/Y. 7283;;; 7284(define_peephole 7285 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) 7286 (set (match_dup 0) (reg:HI D_REGNUM))]) 7287 (set (reg:HI D_REGNUM) (match_dup 0))] 7288 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" 7289 "* 7290{ 7291 cc_status = cc_prev_status; 7292 return \"\"; 7293} 7294") 7295 7296;;; 7297;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't 7298;;; need to emit anything. Otherwise, we just need an copy of D to X/Y. 7299;;; 7300(define_peephole 7301 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) 7302 (set (match_dup 0) (reg:HI D_REGNUM))]) 7303 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))] 7304 "REGNO (operands[0]) == REGNO (operands[1]) 7305 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" 7306 "* 7307{ 7308 cc_status = cc_prev_status; 7309 return \"\"; 7310} 7311") 7312 7313;;; 7314;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't 7315;;; need to emit anything. Otherwise, we just need a copy of D to X/Y. 7316;;; 7317(define_peephole 7318 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) 7319 (set (match_dup 0) (reg:HI D_REGNUM))]) 7320 (set (reg:HI D_REGNUM) (match_dup 0))] 7321 "" 7322 "* 7323{ 7324 rtx ops[2]; 7325 7326 ops[0] = operands[0]; 7327 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM); 7328 m68hc11_gen_movhi (insn, ops); 7329 return \"\"; 7330} 7331") 7332 7333;;; 7334;;; Same peephole with a QI set. The copy is made as 16-bit to comply 7335;;; with the xgdx. 7336;;; 7337(define_peephole 7338 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) 7339 (set (match_dup 0) (reg:HI D_REGNUM))]) 7340 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))] 7341 "REGNO (operands[0]) == REGNO (operands[1])" 7342 "* 7343{ 7344 rtx ops[2]; 7345 7346 ops[0] = operands[0]; 7347 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM); 7348 m68hc11_gen_movhi (insn, ops); 7349 return \"\"; 7350} 7351") 7352 7353;;; 7354;;; Catch two consecutive xgdx or xgdy, emit nothing. 7355;;; 7356(define_peephole 7357 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) 7358 (set (match_dup 0) (reg:HI D_REGNUM))]) 7359 (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) 7360 (set (match_dup 0) (reg:HI D_REGNUM))])] 7361 "" 7362 "* 7363{ 7364 cc_status = cc_prev_status; 7365 return \"\"; 7366} 7367") 7368 7369(define_peephole 7370 [(set (match_operand:HI 0 "hard_reg_operand" "") 7371 (match_operand:HI 1 "stack_register_operand" "")) 7372 (set (match_operand:HI 2 "hard_reg_operand" "") 7373 (match_operand:HI 3 "memory_operand" "m")) 7374 (set (match_dup 0) 7375 (match_operand:HI 4 "memory_operand" "m"))] 7376 "IS_STACK_POP (operands[4]) 7377 && (GET_CODE (operands[3]) == MEM && 7378 rtx_equal_p (operands[0], XEXP (operands[3], 0)))" 7379 "* 7380{ 7381 rtx ops[2]; 7382 7383 ops[0] = operands[2]; 7384 ops[1] = gen_rtx (MEM, HImode, 7385 gen_rtx (POST_INC, HImode, stack_pointer_rtx)); 7386 m68hc11_gen_movhi (insn, ops); 7387 return \"\"; 7388} 7389") 7390 7391;; 7392;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP. 7393;; 7394(define_peephole 7395 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1)) 7396 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))] 7397 "TARGET_M6811" 7398 "* 7399{ 7400 return \"sts\\t%t0\\n\\tld%0\\t%t0\"; 7401} 7402") 7403