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