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