1;; Machine description for GNU compiler, 2;; for ATMEL AVR micro controllers. 3;; Copyright (C) 1998-2015 Free Software Foundation, Inc. 4;; Contributed by Denis Chertykov (chertykov@gmail.com) 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 3, 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 COPYING3. If not see 20;; <http://www.gnu.org/licenses/>. 21 22;; Special characters after '%': 23;; A No effect (add 0). 24;; B Add 1 to REG number, MEM address or CONST_INT. 25;; C Add 2. 26;; D Add 3. 27;; E reg number in XEXP(x, 0). 28;; F Add 1 to reg number. 29;; I reg number in XEXP(XEXP(x, 0), 0). 30;; J Add 1 to reg number. 31;; j Branch condition. 32;; k Reverse branch condition. 33;;..m..Constant Direct Data memory address. 34;; i Print the SFR address quivalent of a CONST_INT or a CONST_INT 35;; RAM address. The resulting address is suitable to be used in IN/OUT. 36;; o Displacement for (mem (plus (reg) (const_int))) operands. 37;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z) 38;; r POST_INC or PRE_DEC address as a register (r26, r28, r30) 39;; r Print a REG without the register prefix 'r'. 40;; T/T Print operand suitable for BLD/BST instruction, i.e. register and 41;; bit number. This gets 2 operands: The first %T gets a REG_P and 42;; just cashes the operand for the next %T. The second %T gets 43;; a CONST_INT that represents a bit position. 44;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13) 45;; "%T0%T1" it will print "r19,5". 46;; Notice that you must not write a comma between %T0 and %T1. 47;; T/t Similar to above, but don't print the comma and the bit number. 48;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13) 49;; "%T0%t1" it will print "r19". 50;;..x..Constant Direct Program memory address. 51;; ~ Output 'r' if not AVR_HAVE_JMP_CALL. 52;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL. 53 54 55(define_constants 56 [(REG_X 26) 57 (REG_Y 28) 58 (REG_Z 30) 59 (REG_W 24) 60 (REG_SP 32) 61 (LPM_REGNO 0) ; implicit target register of LPM 62 (TMP_REGNO 0) ; temporary register r0 63 (ZERO_REGNO 1) ; zero register r1 64 ]) 65 66(define_constants 67 [(TMP_REGNO_TINY 16) ; r16 is temp register for AVR_TINY 68 (ZERO_REGNO_TINY 17) ; r17 is zero register for AVR_TINY 69 ]) 70 71(define_c_enum "unspec" 72 [UNSPEC_STRLEN 73 UNSPEC_MOVMEM 74 UNSPEC_INDEX_JMP 75 UNSPEC_FMUL 76 UNSPEC_FMULS 77 UNSPEC_FMULSU 78 UNSPEC_COPYSIGN 79 UNSPEC_IDENTITY 80 UNSPEC_INSERT_BITS 81 UNSPEC_ROUND 82 ]) 83 84(define_c_enum "unspecv" 85 [UNSPECV_PROLOGUE_SAVES 86 UNSPECV_EPILOGUE_RESTORES 87 UNSPECV_WRITE_SP 88 UNSPECV_GOTO_RECEIVER 89 UNSPECV_ENABLE_IRQS 90 UNSPECV_MEMORY_BARRIER 91 UNSPECV_NOP 92 UNSPECV_SLEEP 93 UNSPECV_WDR 94 UNSPECV_DELAY_CYCLES 95 ]) 96 97 98(include "predicates.md") 99(include "constraints.md") 100 101;; Condition code settings. 102(define_attr "cc" "none,set_czn,set_zn,set_vzn,set_n,compare,clobber, 103 plus,ldi" 104 (const_string "none")) 105 106(define_attr "type" "branch,branch1,arith,xcall" 107 (const_string "arith")) 108 109;; The size of instructions in bytes. 110;; XXX may depend from "cc" 111 112(define_attr "length" "" 113 (cond [(eq_attr "type" "branch") 114 (if_then_else (and (ge (minus (pc) (match_dup 0)) 115 (const_int -63)) 116 (le (minus (pc) (match_dup 0)) 117 (const_int 62))) 118 (const_int 1) 119 (if_then_else (and (ge (minus (pc) (match_dup 0)) 120 (const_int -2045)) 121 (le (minus (pc) (match_dup 0)) 122 (const_int 2045))) 123 (const_int 2) 124 (const_int 3))) 125 (eq_attr "type" "branch1") 126 (if_then_else (and (ge (minus (pc) (match_dup 0)) 127 (const_int -62)) 128 (le (minus (pc) (match_dup 0)) 129 (const_int 61))) 130 (const_int 2) 131 (if_then_else (and (ge (minus (pc) (match_dup 0)) 132 (const_int -2044)) 133 (le (minus (pc) (match_dup 0)) 134 (const_int 2043))) 135 (const_int 3) 136 (const_int 4))) 137 (eq_attr "type" "xcall") 138 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 139 (const_int 1) 140 (const_int 2))] 141 (const_int 2))) 142 143;; Lengths of several insns are adjusted in avr.c:adjust_insn_length(). 144;; Following insn attribute tells if and how the adjustment has to be 145;; done: 146;; no No adjustment needed; attribute "length" is fine. 147;; Otherwise do special processing depending on the attribute. 148 149(define_attr "adjust_len" 150 "out_bitop, plus, addto_sp, sext, 151 tsthi, tstpsi, tstsi, compare, compare64, call, 152 mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32, 153 ufract, sfract, round, 154 xload, lpm, movmem, 155 ashlqi, ashrqi, lshrqi, 156 ashlhi, ashrhi, lshrhi, 157 ashlsi, ashrsi, lshrsi, 158 ashlpsi, ashrpsi, lshrpsi, 159 insert_bits, 160 no" 161 (const_string "no")) 162 163;; Flavours of instruction set architecture (ISA), used in enabled attribute 164 165;; mov : ISA has no MOVW movw : ISA has MOVW 166;; rjmp : ISA has no CALL/JMP jmp : ISA has CALL/JMP 167;; ijmp : ISA has no EICALL/EIJMP eijmp : ISA has EICALL/EIJMP 168;; lpm : ISA has no LPMX lpmx : ISA has LPMX 169;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX 170;; no_xmega: non-XMEGA core xmega : XMEGA core 171;; no_tiny: non-TINY core tiny : TINY core 172 173(define_attr "isa" 174 "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, no_tiny,tiny, 175 standard" 176 (const_string "standard")) 177 178(define_attr "enabled" "" 179 (cond [(eq_attr "isa" "standard") 180 (const_int 1) 181 182 (and (eq_attr "isa" "mov") 183 (match_test "!AVR_HAVE_MOVW")) 184 (const_int 1) 185 186 (and (eq_attr "isa" "movw") 187 (match_test "AVR_HAVE_MOVW")) 188 (const_int 1) 189 190 (and (eq_attr "isa" "rjmp") 191 (match_test "!AVR_HAVE_JMP_CALL")) 192 (const_int 1) 193 194 (and (eq_attr "isa" "jmp") 195 (match_test "AVR_HAVE_JMP_CALL")) 196 (const_int 1) 197 198 (and (eq_attr "isa" "ijmp") 199 (match_test "!AVR_HAVE_EIJMP_EICALL")) 200 (const_int 1) 201 202 (and (eq_attr "isa" "eijmp") 203 (match_test "AVR_HAVE_EIJMP_EICALL")) 204 (const_int 1) 205 206 (and (eq_attr "isa" "lpm") 207 (match_test "!AVR_HAVE_LPMX")) 208 (const_int 1) 209 210 (and (eq_attr "isa" "lpmx") 211 (match_test "AVR_HAVE_LPMX")) 212 (const_int 1) 213 214 (and (eq_attr "isa" "elpm") 215 (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX")) 216 (const_int 1) 217 218 (and (eq_attr "isa" "elpmx") 219 (match_test "AVR_HAVE_ELPMX")) 220 (const_int 1) 221 222 (and (eq_attr "isa" "xmega") 223 (match_test "AVR_XMEGA")) 224 (const_int 1) 225 226 (and (eq_attr "isa" "tiny") 227 (match_test "AVR_TINY")) 228 (const_int 1) 229 230 (and (eq_attr "isa" "no_xmega") 231 (match_test "!AVR_XMEGA")) 232 (const_int 1) 233 234 (and (eq_attr "isa" "no_tiny") 235 (match_test "!AVR_TINY")) 236 (const_int 1) 237 238 ] (const_int 0))) 239 240 241;; Define mode iterators 242(define_mode_iterator QIHI [QI HI]) 243(define_mode_iterator QIHI2 [QI HI]) 244(define_mode_iterator QISI [QI HI PSI SI]) 245(define_mode_iterator QIDI [QI HI PSI SI DI]) 246(define_mode_iterator HISI [HI PSI SI]) 247 248(define_mode_iterator ALL1 [QI QQ UQQ]) 249(define_mode_iterator ALL2 [HI HQ UHQ HA UHA]) 250(define_mode_iterator ALL4 [SI SQ USQ SA USA]) 251 252;; All supported move-modes 253(define_mode_iterator MOVMODE [QI QQ UQQ 254 HI HQ UHQ HA UHA 255 SI SQ USQ SA USA 256 SF PSI]) 257 258;; Supported ordered modes that are 2, 3, 4 bytes wide 259(define_mode_iterator ORDERED234 [HI SI PSI 260 HQ UHQ HA UHA 261 SQ USQ SA USA]) 262 263;; Define code iterators 264;; Define two incarnations so that we can build the cross product. 265(define_code_iterator any_extend [sign_extend zero_extend]) 266(define_code_iterator any_extend2 [sign_extend zero_extend]) 267 268(define_code_iterator xior [xor ior]) 269(define_code_iterator eqne [eq ne]) 270 271(define_code_iterator ss_addsub [ss_plus ss_minus]) 272(define_code_iterator us_addsub [us_plus us_minus]) 273(define_code_iterator ss_abs_neg [ss_abs ss_neg]) 274 275;; Define code attributes 276(define_code_attr extend_su 277 [(sign_extend "s") 278 (zero_extend "u")]) 279 280(define_code_attr extend_u 281 [(sign_extend "") 282 (zero_extend "u")]) 283 284(define_code_attr extend_s 285 [(sign_extend "s") 286 (zero_extend "")]) 287 288;; Constrain input operand of widening multiply, i.e. MUL resp. MULS. 289(define_code_attr mul_r_d 290 [(zero_extend "r") 291 (sign_extend "d")]) 292 293(define_code_attr abelian 294 [(ss_minus "") (us_minus "") 295 (ss_plus "%") (us_plus "%")]) 296 297;; Map RTX code to its standard insn name 298(define_code_attr code_stdname 299 [(ashift "ashl") 300 (ashiftrt "ashr") 301 (lshiftrt "lshr") 302 (ior "ior") 303 (xor "xor") 304 (rotate "rotl") 305 (ss_plus "ssadd") (ss_minus "sssub") (ss_neg "ssneg") (ss_abs "ssabs") 306 (us_plus "usadd") (us_minus "ussub") (us_neg "usneg") 307 ]) 308 309;;======================================================================== 310;; The following is used by nonlocal_goto and setjmp. 311;; The receiver pattern will create no instructions since internally 312;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28 313;; This avoids creating add/sub offsets in frame_pointer save/resore. 314;; The 'null' receiver also avoids problems with optimisation 315;; not recognising incoming jmp and removing code that resets frame_pointer. 316;; The code derived from builtins.c. 317 318(define_expand "nonlocal_goto_receiver" 319 [(set (reg:HI REG_Y) 320 (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))] 321 "" 322 { 323 emit_move_insn (virtual_stack_vars_rtx, 324 gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, 325 gen_int_mode (STARTING_FRAME_OFFSET, 326 Pmode))); 327 /* ; This might change the hard frame pointer in ways that aren't 328 ; apparent to early optimization passes, so force a clobber. */ 329 emit_clobber (hard_frame_pointer_rtx); 330 DONE; 331 }) 332 333 334;; Defining nonlocal_goto_receiver means we must also define this. 335;; even though its function is identical to that in builtins.c 336 337(define_expand "nonlocal_goto" 338 [(use (match_operand 0 "general_operand")) 339 (use (match_operand 1 "general_operand")) 340 (use (match_operand 2 "general_operand")) 341 (use (match_operand 3 "general_operand"))] 342 "" 343 { 344 rtx r_label = copy_to_reg (operands[1]); 345 rtx r_fp = operands[3]; 346 rtx r_sp = operands[2]; 347 348 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); 349 350 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); 351 352 emit_move_insn (hard_frame_pointer_rtx, r_fp); 353 emit_stack_restore (SAVE_NONLOCAL, r_sp); 354 355 emit_use (hard_frame_pointer_rtx); 356 emit_use (stack_pointer_rtx); 357 358 emit_indirect_jump (r_label); 359 360 DONE; 361 }) 362 363;; "pushqi1" 364;; "pushqq1" "pushuqq1" 365(define_insn "push<mode>1" 366 [(set (mem:ALL1 (post_dec:HI (reg:HI REG_SP))) 367 (match_operand:ALL1 0 "reg_or_0_operand" "r,Y00"))] 368 "" 369 "@ 370 push %0 371 push __zero_reg__" 372 [(set_attr "length" "1,1")]) 373 374(define_insn "pushhi1_insn" 375 [(set (mem:HI (post_dec:HI (reg:HI REG_SP))) 376 (match_operand:HI 0 "register_operand" "r"))] 377 "" 378 "push %B0\;push %A0" 379 [(set_attr "length" "2")]) 380 381;; All modes for a multi-byte push. We must include complex modes here too, 382;; lest emit_single_push_insn "helpfully" create the auto-inc itself. 383(define_mode_iterator MPUSH 384 [CQI 385 HI CHI HA UHA HQ UHQ 386 SI CSI SA USA SQ USQ 387 DI CDI DA UDA DQ UDQ 388 TA UTA 389 SF SC 390 PSI]) 391 392(define_expand "push<mode>1" 393 [(match_operand:MPUSH 0 "" "")] 394 "" 395 { 396 if (MEM_P (operands[0]) 397 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[0]))) 398 { 399 // Avoid (subreg (mem)) for non-generic address spaces. Because 400 // of the poor addressing capabilities of these spaces it's better to 401 // load them in one chunk. And it avoids PR61443. 402 403 operands[0] = copy_to_mode_reg (<MODE>mode, operands[0]); 404 } 405 else if (REG_P (operands[0]) 406 && IN_RANGE (REGNO (operands[0]), FIRST_VIRTUAL_REGISTER, 407 LAST_VIRTUAL_REGISTER)) 408 { 409 // Byte-wise pushing of virtual regs might result in something like 410 // 411 // (set (mem:QI (post_dec:HI (reg:HI 32 SP))) 412 // (subreg:QI (plus:HI (reg:HI 28) 413 // (const_int 17)) 0)) 414 // 415 // after elimination. This cannot be handled by reload, cf. PR64452. 416 // Reload virtuals in one chunk. That way it's possible to reload 417 // above situation and finally 418 // 419 // (set (reg:HI **) 420 // (const_int 17)) 421 // (set (reg:HI **) 422 // (plus:HI (reg:HI **) 423 // (reg:HI 28))) 424 // (set (mem:HI (post_dec:HI (reg:HI 32 SP)) 425 // (reg:HI **))) 426 427 emit_insn (gen_pushhi1_insn (operands[0])); 428 DONE; 429 } 430 431 for (int i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i) 432 { 433 rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i); 434 if (part != const0_rtx) 435 part = force_reg (QImode, part); 436 emit_insn (gen_pushqi1 (part)); 437 } 438 DONE; 439 }) 440 441;; Notice a special-case when adding N to SP where N results in a 442;; zero REG_ARGS_SIZE. This is equivalent to a move from FP. 443(define_split 444 [(set (reg:HI REG_SP) 445 (match_operand:HI 0 "register_operand" ""))] 446 "reload_completed 447 && frame_pointer_needed 448 && !cfun->calls_alloca 449 && find_reg_note (insn, REG_ARGS_SIZE, const0_rtx)" 450 [(set (reg:HI REG_SP) 451 (reg:HI REG_Y))]) 452 453;;======================================================================== 454;; Move stuff around 455 456;; Secondary input reload from non-generic 16-bit address spaces 457(define_insn "reload_in<mode>" 458 [(set (match_operand:MOVMODE 0 "register_operand" "=r") 459 (match_operand:MOVMODE 1 "flash_operand" "m")) 460 (clobber (match_operand:QI 2 "d_register_operand" "=d"))] 461 ;; Fixme: The insn condition must not test the address space. 462 ;; Because the gen tools refuse to generate insns for address spaces 463 ;; and will generate insn-codes.h to look like: 464 ;; #define CODE_FOR_reload_inhi CODE_FOR_nothing 465 "reload_completed || reload_in_progress" 466 { 467 return avr_out_lpm (insn, operands, NULL); 468 } 469 [(set_attr "adjust_len" "lpm") 470 (set_attr "cc" "clobber")]) 471 472 473;; "loadqi_libgcc" 474;; "loadhi_libgcc" 475;; "loadpsi_libgcc" 476;; "loadsi_libgcc" 477;; "loadsf_libgcc" 478(define_expand "load<mode>_libgcc" 479 [(set (match_dup 3) 480 (match_dup 2)) 481 (set (reg:MOVMODE 22) 482 (match_operand:MOVMODE 1 "memory_operand" "")) 483 (set (match_operand:MOVMODE 0 "register_operand" "") 484 (reg:MOVMODE 22))] 485 "avr_load_libgcc_p (operands[1])" 486 { 487 operands[3] = gen_rtx_REG (HImode, REG_Z); 488 operands[2] = force_operand (XEXP (operands[1], 0), NULL_RTX); 489 operands[1] = replace_equiv_address (operands[1], operands[3]); 490 set_mem_addr_space (operands[1], ADDR_SPACE_FLASH); 491 }) 492 493;; "load_qi_libgcc" 494;; "load_hi_libgcc" 495;; "load_psi_libgcc" 496;; "load_si_libgcc" 497;; "load_sf_libgcc" 498(define_insn "load_<mode>_libgcc" 499 [(set (reg:MOVMODE 22) 500 (match_operand:MOVMODE 0 "memory_operand" "m,m"))] 501 "avr_load_libgcc_p (operands[0]) 502 && REG_P (XEXP (operands[0], 0)) 503 && REG_Z == REGNO (XEXP (operands[0], 0))" 504 { 505 operands[0] = GEN_INT (GET_MODE_SIZE (<MODE>mode)); 506 return "%~call __load_%0"; 507 } 508 [(set_attr "length" "1,2") 509 (set_attr "isa" "rjmp,jmp") 510 (set_attr "cc" "clobber")]) 511 512 513;; "xload8qi_A" 514;; "xload8qq_A" "xload8uqq_A" 515(define_insn_and_split "xload8<mode>_A" 516 [(set (match_operand:ALL1 0 "register_operand" "=r") 517 (match_operand:ALL1 1 "memory_operand" "m")) 518 (clobber (reg:HI REG_Z))] 519 "can_create_pseudo_p() 520 && !avr_xload_libgcc_p (<MODE>mode) 521 && avr_mem_memx_p (operands[1]) 522 && REG_P (XEXP (operands[1], 0))" 523 { gcc_unreachable(); } 524 "&& 1" 525 [(clobber (const_int 0))] 526 { 527 /* ; Split away the high part of the address. GCC's register allocator 528 ; in not able to allocate segment registers and reload the resulting 529 ; expressions. Notice that no address register can hold a PSImode. */ 530 531 rtx_insn *insn; 532 rtx addr = XEXP (operands[1], 0); 533 rtx hi8 = gen_reg_rtx (QImode); 534 rtx reg_z = gen_rtx_REG (HImode, REG_Z); 535 536 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0)); 537 emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2)); 538 539 insn = emit_insn (gen_xload<mode>_8 (operands[0], hi8)); 540 set_mem_addr_space (SET_SRC (single_set (insn)), 541 MEM_ADDR_SPACE (operands[1])); 542 DONE; 543 }) 544 545;; "xloadqi_A" "xloadqq_A" "xloaduqq_A" 546;; "xloadhi_A" "xloadhq_A" "xloaduhq_A" "xloadha_A" "xloaduha_A" 547;; "xloadsi_A" "xloadsq_A" "xloadusq_A" "xloadsa_A" "xloadusa_A" 548;; "xloadpsi_A" 549;; "xloadsf_A" 550(define_insn_and_split "xload<mode>_A" 551 [(set (match_operand:MOVMODE 0 "register_operand" "=r") 552 (match_operand:MOVMODE 1 "memory_operand" "m")) 553 (clobber (reg:MOVMODE 22)) 554 (clobber (reg:QI 21)) 555 (clobber (reg:HI REG_Z))] 556 "can_create_pseudo_p() 557 && avr_mem_memx_p (operands[1]) 558 && REG_P (XEXP (operands[1], 0))" 559 { gcc_unreachable(); } 560 "&& 1" 561 [(clobber (const_int 0))] 562 { 563 rtx addr = XEXP (operands[1], 0); 564 rtx reg_z = gen_rtx_REG (HImode, REG_Z); 565 rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2); 566 addr_space_t as = MEM_ADDR_SPACE (operands[1]); 567 rtx_insn *insn; 568 569 /* Split the address to R21:Z */ 570 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0)); 571 emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8); 572 573 /* Load with code from libgcc */ 574 insn = emit_insn (gen_xload_<mode>_libgcc ()); 575 set_mem_addr_space (SET_SRC (single_set (insn)), as); 576 577 /* Move to destination */ 578 emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22)); 579 580 DONE; 581 }) 582 583;; Move value from address space memx to a register 584;; These insns must be prior to respective generic move insn. 585 586;; "xloadqi_8" 587;; "xloadqq_8" "xloaduqq_8" 588(define_insn "xload<mode>_8" 589 [(set (match_operand:ALL1 0 "register_operand" "=&r,r") 590 (mem:ALL1 (lo_sum:PSI (match_operand:QI 1 "register_operand" "r,r") 591 (reg:HI REG_Z))))] 592 "!avr_xload_libgcc_p (<MODE>mode)" 593 { 594 return avr_out_xload (insn, operands, NULL); 595 } 596 [(set_attr "length" "4,4") 597 (set_attr "adjust_len" "*,xload") 598 (set_attr "isa" "lpmx,lpm") 599 (set_attr "cc" "none")]) 600 601;; R21:Z : 24-bit source address 602;; R22 : 1-4 byte output 603 604;; "xload_qi_libgcc" "xload_qq_libgcc" "xload_uqq_libgcc" 605;; "xload_hi_libgcc" "xload_hq_libgcc" "xload_uhq_libgcc" "xload_ha_libgcc" "xload_uha_libgcc" 606;; "xload_si_libgcc" "xload_sq_libgcc" "xload_usq_libgcc" "xload_sa_libgcc" "xload_usa_libgcc" 607;; "xload_sf_libgcc" 608;; "xload_psi_libgcc" 609(define_insn "xload_<mode>_libgcc" 610 [(set (reg:MOVMODE 22) 611 (mem:MOVMODE (lo_sum:PSI (reg:QI 21) 612 (reg:HI REG_Z)))) 613 (clobber (reg:QI 21)) 614 (clobber (reg:HI REG_Z))] 615 "avr_xload_libgcc_p (<MODE>mode)" 616 { 617 rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode)); 618 619 output_asm_insn ("%~call __xload_%0", &x_bytes); 620 return ""; 621 } 622 [(set_attr "type" "xcall") 623 (set_attr "cc" "clobber")]) 624 625 626;; General move expanders 627 628;; "movqi" "movqq" "movuqq" 629;; "movhi" "movhq" "movuhq" "movha" "movuha" 630;; "movsi" "movsq" "movusq" "movsa" "movusa" 631;; "movsf" 632;; "movpsi" 633(define_expand "mov<mode>" 634 [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "") 635 (match_operand:MOVMODE 1 "general_operand" ""))] 636 "" 637 { 638 rtx dest = operands[0]; 639 rtx src = avr_eval_addr_attrib (operands[1]); 640 641 if (avr_mem_flash_p (dest)) 642 DONE; 643 644 /* One of the operands has to be in a register. */ 645 if (!register_operand (dest, <MODE>mode) 646 && !reg_or_0_operand (src, <MODE>mode)) 647 { 648 operands[1] = src = copy_to_mode_reg (<MODE>mode, src); 649 } 650 651 if (avr_mem_memx_p (src)) 652 { 653 rtx addr = XEXP (src, 0); 654 655 if (!REG_P (addr)) 656 src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr)); 657 658 if (!avr_xload_libgcc_p (<MODE>mode)) 659 /* ; No <mode> here because gen_xload8<mode>_A only iterates over ALL1. 660 ; insn-emit does not depend on the mode, it's all about operands. */ 661 emit_insn (gen_xload8qi_A (dest, src)); 662 else 663 emit_insn (gen_xload<mode>_A (dest, src)); 664 665 DONE; 666 } 667 668 if (avr_load_libgcc_p (src)) 669 { 670 /* For the small devices, do loads per libgcc call. */ 671 emit_insn (gen_load<mode>_libgcc (dest, src)); 672 DONE; 673 } 674 }) 675 676;;======================================================================== 677;; move byte 678;; The last alternative (any immediate constant to any register) is 679;; very expensive. It should be optimized by peephole2 if a scratch 680;; register is available, but then that register could just as well be 681;; allocated for the variable we are loading. But, most of NO_LD_REGS 682;; are call-saved registers, and most of LD_REGS are call-used registers, 683;; so this may still be a win for registers live across function calls. 684 685;; "movqi_insn" 686;; "movqq_insn" "movuqq_insn" 687(define_insn "mov<mode>_insn" 688 [(set (match_operand:ALL1 0 "nonimmediate_operand" "=r ,d ,Qm ,r ,q,r,*r") 689 (match_operand:ALL1 1 "nox_general_operand" "r Y00,n Ynn,r Y00,Qm,r,q,i"))] 690 "register_operand (operands[0], <MODE>mode) 691 || reg_or_0_operand (operands[1], <MODE>mode)" 692 { 693 return output_movqi (insn, operands, NULL); 694 } 695 [(set_attr "length" "1,1,5,5,1,1,4") 696 (set_attr "adjust_len" "mov8") 697 (set_attr "cc" "ldi,none,clobber,clobber,none,none,clobber")]) 698 699;; This is used in peephole2 to optimize loading immediate constants 700;; if a scratch register from LD_REGS happens to be available. 701 702;; "*reload_inqi" 703;; "*reload_inqq" "*reload_inuqq" 704(define_insn "*reload_in<mode>" 705 [(set (match_operand:ALL1 0 "register_operand" "=l") 706 (match_operand:ALL1 1 "const_operand" "i")) 707 (clobber (match_operand:QI 2 "register_operand" "=&d"))] 708 "reload_completed" 709 "ldi %2,lo8(%1) 710 mov %0,%2" 711 [(set_attr "length" "2") 712 (set_attr "cc" "none")]) 713 714(define_peephole2 715 [(match_scratch:QI 2 "d") 716 (set (match_operand:ALL1 0 "l_register_operand" "") 717 (match_operand:ALL1 1 "const_operand" ""))] 718 ; No need for a clobber reg for 0x0, 0x01 or 0xff 719 "!satisfies_constraint_Y00 (operands[1]) 720 && !satisfies_constraint_Y01 (operands[1]) 721 && !satisfies_constraint_Ym1 (operands[1])" 722 [(parallel [(set (match_dup 0) 723 (match_dup 1)) 724 (clobber (match_dup 2))])]) 725 726;;============================================================================ 727;; move word (16 bit) 728 729;; Move register $1 to the Stack Pointer register SP. 730;; This insn is emit during function prologue/epilogue generation. 731;; $2 = 0: We know that IRQs are off 732;; $2 = 1: We know that IRQs are on 733;; $2 = 2: SP has 8 bits only, IRQ state does not matter 734;; $2 = -1: We don't know anything about IRQ on/off 735;; Always write SP via unspec, see PR50063 736 737(define_insn "movhi_sp_r" 738 [(set (match_operand:HI 0 "stack_register_operand" "=q,q,q,q,q") 739 (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r,r,r,r") 740 (match_operand:HI 2 "const_int_operand" "L,P,N,K,LPN")] 741 UNSPECV_WRITE_SP))] 742 "" 743 "@ 744 out %B0,%B1\;out %A0,%A1 745 cli\;out %B0,%B1\;sei\;out %A0,%A1 746 in __tmp_reg__,__SREG__\;cli\;out %B0,%B1\;out __SREG__,__tmp_reg__\;out %A0,%A1 747 out %A0,%A1 748 out %A0,%A1\;out %B0,%B1" 749 [(set_attr "length" "2,4,5,1,2") 750 (set_attr "isa" "no_xmega,no_xmega,no_xmega,*,xmega") 751 (set_attr "cc" "none")]) 752 753(define_peephole2 754 [(match_scratch:QI 2 "d") 755 (set (match_operand:ALL2 0 "l_register_operand" "") 756 (match_operand:ALL2 1 "const_or_immediate_operand" ""))] 757 "operands[1] != CONST0_RTX (<MODE>mode)" 758 [(parallel [(set (match_dup 0) 759 (match_dup 1)) 760 (clobber (match_dup 2))])]) 761 762;; '*' because it is not used in rtl generation, only in above peephole 763;; "*reload_inhi" 764;; "*reload_inhq" "*reload_inuhq" 765;; "*reload_inha" "*reload_inuha" 766(define_insn "*reload_in<mode>" 767 [(set (match_operand:ALL2 0 "l_register_operand" "=l") 768 (match_operand:ALL2 1 "immediate_operand" "i")) 769 (clobber (match_operand:QI 2 "register_operand" "=&d"))] 770 "reload_completed" 771 { 772 return output_reload_inhi (operands, operands[2], NULL); 773 } 774 [(set_attr "length" "4") 775 (set_attr "adjust_len" "reload_in16") 776 (set_attr "cc" "clobber")]) 777 778;; "*movhi" 779;; "*movhq" "*movuhq" 780;; "*movha" "*movuha" 781(define_insn "*mov<mode>" 782 [(set (match_operand:ALL2 0 "nonimmediate_operand" "=r,r ,r,m ,d,*r,q,r") 783 (match_operand:ALL2 1 "nox_general_operand" "r,Y00,m,r Y00,i,i ,r,q"))] 784 "register_operand (operands[0], <MODE>mode) 785 || reg_or_0_operand (operands[1], <MODE>mode)" 786 { 787 return output_movhi (insn, operands, NULL); 788 } 789 [(set_attr "length" "2,2,6,7,2,6,5,2") 790 (set_attr "adjust_len" "mov16") 791 (set_attr "cc" "none,none,clobber,clobber,none,clobber,none,none")]) 792 793(define_peephole2 ; movw 794 [(set (match_operand:ALL1 0 "even_register_operand" "") 795 (match_operand:ALL1 1 "even_register_operand" "")) 796 (set (match_operand:ALL1 2 "odd_register_operand" "") 797 (match_operand:ALL1 3 "odd_register_operand" ""))] 798 "AVR_HAVE_MOVW 799 && REGNO (operands[0]) == REGNO (operands[2]) - 1 800 && REGNO (operands[1]) == REGNO (operands[3]) - 1" 801 [(set (match_dup 4) 802 (match_dup 5))] 803 { 804 operands[4] = gen_rtx_REG (HImode, REGNO (operands[0])); 805 operands[5] = gen_rtx_REG (HImode, REGNO (operands[1])); 806 }) 807 808(define_peephole2 ; movw_r 809 [(set (match_operand:ALL1 0 "odd_register_operand" "") 810 (match_operand:ALL1 1 "odd_register_operand" "")) 811 (set (match_operand:ALL1 2 "even_register_operand" "") 812 (match_operand:ALL1 3 "even_register_operand" ""))] 813 "AVR_HAVE_MOVW 814 && REGNO (operands[2]) == REGNO (operands[0]) - 1 815 && REGNO (operands[3]) == REGNO (operands[1]) - 1" 816 [(set (match_dup 4) 817 (match_dup 5))] 818 { 819 operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); 820 operands[5] = gen_rtx_REG (HImode, REGNO (operands[3])); 821 }) 822 823;; For LPM loads from AS1 we split 824;; R = *Z 825;; to 826;; R = *Z++ 827;; Z = Z - sizeof (R) 828;; 829;; so that the second instruction can be optimized out. 830 831(define_split ; "split-lpmx" 832 [(set (match_operand:HISI 0 "register_operand" "") 833 (match_operand:HISI 1 "memory_operand" ""))] 834 "reload_completed 835 && AVR_HAVE_LPMX" 836 [(set (match_dup 0) 837 (match_dup 2)) 838 (set (match_dup 3) 839 (plus:HI (match_dup 3) 840 (match_dup 4)))] 841 { 842 rtx addr = XEXP (operands[1], 0); 843 844 if (!avr_mem_flash_p (operands[1]) 845 || !REG_P (addr) 846 || reg_overlap_mentioned_p (addr, operands[0])) 847 { 848 FAIL; 849 } 850 851 operands[2] = replace_equiv_address (operands[1], 852 gen_rtx_POST_INC (Pmode, addr)); 853 operands[3] = addr; 854 operands[4] = gen_int_mode (-GET_MODE_SIZE (<MODE>mode), HImode); 855 }) 856 857;;========================================================================== 858;; xpointer move (24 bit) 859 860(define_peephole2 ; *reload_inpsi 861 [(match_scratch:QI 2 "d") 862 (set (match_operand:PSI 0 "l_register_operand" "") 863 (match_operand:PSI 1 "immediate_operand" "")) 864 (match_dup 2)] 865 "operands[1] != const0_rtx 866 && operands[1] != constm1_rtx" 867 [(parallel [(set (match_dup 0) 868 (match_dup 1)) 869 (clobber (match_dup 2))])]) 870 871;; '*' because it is not used in rtl generation. 872(define_insn "*reload_inpsi" 873 [(set (match_operand:PSI 0 "register_operand" "=r") 874 (match_operand:PSI 1 "immediate_operand" "i")) 875 (clobber (match_operand:QI 2 "register_operand" "=&d"))] 876 "reload_completed" 877 { 878 return avr_out_reload_inpsi (operands, operands[2], NULL); 879 } 880 [(set_attr "length" "6") 881 (set_attr "adjust_len" "reload_in24") 882 (set_attr "cc" "clobber")]) 883 884(define_insn "*movpsi" 885 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r") 886 (match_operand:PSI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))] 887 "register_operand (operands[0], PSImode) 888 || register_operand (operands[1], PSImode) 889 || const0_rtx == operands[1]" 890 { 891 return avr_out_movpsi (insn, operands, NULL); 892 } 893 [(set_attr "length" "3,3,8,9,4,10") 894 (set_attr "adjust_len" "mov24") 895 (set_attr "cc" "none,none,clobber,clobber,none,clobber")]) 896 897;;========================================================================== 898;; move double word (32 bit) 899 900(define_peephole2 ; *reload_insi 901 [(match_scratch:QI 2 "d") 902 (set (match_operand:ALL4 0 "l_register_operand" "") 903 (match_operand:ALL4 1 "immediate_operand" "")) 904 (match_dup 2)] 905 "operands[1] != CONST0_RTX (<MODE>mode)" 906 [(parallel [(set (match_dup 0) 907 (match_dup 1)) 908 (clobber (match_dup 2))])]) 909 910;; '*' because it is not used in rtl generation. 911;; "*reload_insi" 912;; "*reload_insq" "*reload_inusq" 913;; "*reload_insa" "*reload_inusa" 914(define_insn "*reload_insi" 915 [(set (match_operand:ALL4 0 "register_operand" "=r") 916 (match_operand:ALL4 1 "immediate_operand" "n Ynn")) 917 (clobber (match_operand:QI 2 "register_operand" "=&d"))] 918 "reload_completed" 919 { 920 return output_reload_insisf (operands, operands[2], NULL); 921 } 922 [(set_attr "length" "8") 923 (set_attr "adjust_len" "reload_in32") 924 (set_attr "cc" "clobber")]) 925 926 927;; "*movsi" 928;; "*movsq" "*movusq" 929;; "*movsa" "*movusa" 930(define_insn "*mov<mode>" 931 [(set (match_operand:ALL4 0 "nonimmediate_operand" "=r,r ,r ,Qm ,!d,r") 932 (match_operand:ALL4 1 "nox_general_operand" "r,Y00,Qm,r Y00,i ,i"))] 933 "register_operand (operands[0], <MODE>mode) 934 || reg_or_0_operand (operands[1], <MODE>mode)" 935 { 936 return output_movsisf (insn, operands, NULL); 937 } 938 [(set_attr "length" "4,4,8,9,4,10") 939 (set_attr "adjust_len" "mov32") 940 (set_attr "cc" "none,none,clobber,clobber,none,clobber")]) 941 942;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 943;; move floating point numbers (32 bit) 944 945(define_insn "*movsf" 946 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r") 947 (match_operand:SF 1 "nox_general_operand" "r,G,Qm,rG,F ,F"))] 948 "register_operand (operands[0], SFmode) 949 || reg_or_0_operand (operands[1], SFmode)" 950 { 951 return output_movsisf (insn, operands, NULL); 952 } 953 [(set_attr "length" "4,4,8,9,4,10") 954 (set_attr "adjust_len" "mov32") 955 (set_attr "cc" "none,none,clobber,clobber,none,clobber")]) 956 957(define_peephole2 ; *reload_insf 958 [(match_scratch:QI 2 "d") 959 (set (match_operand:SF 0 "l_register_operand" "") 960 (match_operand:SF 1 "const_double_operand" "")) 961 (match_dup 2)] 962 "operands[1] != CONST0_RTX (SFmode)" 963 [(parallel [(set (match_dup 0) 964 (match_dup 1)) 965 (clobber (match_dup 2))])]) 966 967;; '*' because it is not used in rtl generation. 968(define_insn "*reload_insf" 969 [(set (match_operand:SF 0 "register_operand" "=r") 970 (match_operand:SF 1 "const_double_operand" "F")) 971 (clobber (match_operand:QI 2 "register_operand" "=&d"))] 972 "reload_completed" 973 { 974 return output_reload_insisf (operands, operands[2], NULL); 975 } 976 [(set_attr "length" "8") 977 (set_attr "adjust_len" "reload_in32") 978 (set_attr "cc" "clobber")]) 979 980;;========================================================================= 981;; move string (like memcpy) 982 983(define_expand "movmemhi" 984 [(parallel [(set (match_operand:BLK 0 "memory_operand" "") 985 (match_operand:BLK 1 "memory_operand" "")) 986 (use (match_operand:HI 2 "const_int_operand" "")) 987 (use (match_operand:HI 3 "const_int_operand" ""))])] 988 "" 989 { 990 if (avr_emit_movmemhi (operands)) 991 DONE; 992 993 FAIL; 994 }) 995 996(define_mode_attr MOVMEM_r_d [(QI "r") 997 (HI "wd")]) 998 999;; $0 : Address Space 1000;; $1, $2 : Loop register 1001;; R30 : source address 1002;; R26 : destination address 1003 1004;; "movmem_qi" 1005;; "movmem_hi" 1006(define_insn "movmem_<mode>" 1007 [(set (mem:BLK (reg:HI REG_X)) 1008 (mem:BLK (reg:HI REG_Z))) 1009 (unspec [(match_operand:QI 0 "const_int_operand" "n")] 1010 UNSPEC_MOVMEM) 1011 (use (match_operand:QIHI 1 "register_operand" "<MOVMEM_r_d>")) 1012 (clobber (reg:HI REG_X)) 1013 (clobber (reg:HI REG_Z)) 1014 (clobber (reg:QI LPM_REGNO)) 1015 (clobber (match_operand:QIHI 2 "register_operand" "=1"))] 1016 "" 1017 { 1018 return avr_out_movmem (insn, operands, NULL); 1019 } 1020 [(set_attr "adjust_len" "movmem") 1021 (set_attr "cc" "clobber")]) 1022 1023 1024;; $0 : Address Space 1025;; $1 : RAMPZ RAM address 1026;; R24 : #bytes and loop register 1027;; R23:Z : 24-bit source address 1028;; R26 : 16-bit destination address 1029 1030;; "movmemx_qi" 1031;; "movmemx_hi" 1032(define_insn "movmemx_<mode>" 1033 [(set (mem:BLK (reg:HI REG_X)) 1034 (mem:BLK (lo_sum:PSI (reg:QI 23) 1035 (reg:HI REG_Z)))) 1036 (unspec [(match_operand:QI 0 "const_int_operand" "n")] 1037 UNSPEC_MOVMEM) 1038 (use (reg:QIHI 24)) 1039 (clobber (reg:HI REG_X)) 1040 (clobber (reg:HI REG_Z)) 1041 (clobber (reg:QI LPM_REGNO)) 1042 (clobber (reg:HI 24)) 1043 (clobber (reg:QI 23)) 1044 (clobber (mem:QI (match_operand:QI 1 "io_address_operand" "n")))] 1045 "" 1046 "%~call __movmemx_<mode>" 1047 [(set_attr "type" "xcall") 1048 (set_attr "cc" "clobber")]) 1049 1050 1051;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 1052;; memset (%0, %2, %1) 1053 1054(define_expand "setmemhi" 1055 [(parallel [(set (match_operand:BLK 0 "memory_operand" "") 1056 (match_operand 2 "const_int_operand" "")) 1057 (use (match_operand:HI 1 "const_int_operand" "")) 1058 (use (match_operand:HI 3 "const_int_operand" "")) 1059 (clobber (match_scratch:HI 4 "")) 1060 (clobber (match_dup 5))])] 1061 "" 1062 { 1063 rtx addr0; 1064 machine_mode mode; 1065 1066 /* If value to set is not zero, use the library routine. */ 1067 if (operands[2] != const0_rtx) 1068 FAIL; 1069 1070 if (!CONST_INT_P (operands[1])) 1071 FAIL; 1072 1073 mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode; 1074 operands[5] = gen_rtx_SCRATCH (mode); 1075 operands[1] = copy_to_mode_reg (mode, 1076 gen_int_mode (INTVAL (operands[1]), mode)); 1077 addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 1078 operands[0] = gen_rtx_MEM (BLKmode, addr0); 1079 }) 1080 1081 1082(define_insn "*clrmemqi" 1083 [(set (mem:BLK (match_operand:HI 0 "register_operand" "e")) 1084 (const_int 0)) 1085 (use (match_operand:QI 1 "register_operand" "r")) 1086 (use (match_operand:QI 2 "const_int_operand" "n")) 1087 (clobber (match_scratch:HI 3 "=0")) 1088 (clobber (match_scratch:QI 4 "=&1"))] 1089 "" 1090 "0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b" 1091 [(set_attr "length" "3") 1092 (set_attr "cc" "clobber")]) 1093 1094 1095(define_insn "*clrmemhi" 1096 [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e")) 1097 (const_int 0)) 1098 (use (match_operand:HI 1 "register_operand" "!w,d")) 1099 (use (match_operand:HI 2 "const_int_operand" "n,n")) 1100 (clobber (match_scratch:HI 3 "=0,0")) 1101 (clobber (match_scratch:HI 4 "=&1,&1"))] 1102 "" 1103 "@ 1104 0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b 1105 0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b" 1106 [(set_attr "length" "3,4") 1107 (set_attr "cc" "clobber,clobber")]) 1108 1109(define_expand "strlenhi" 1110 [(set (match_dup 4) 1111 (unspec:HI [(match_operand:BLK 1 "memory_operand" "") 1112 (match_operand:QI 2 "const_int_operand" "") 1113 (match_operand:HI 3 "immediate_operand" "")] 1114 UNSPEC_STRLEN)) 1115 (set (match_dup 4) 1116 (plus:HI (match_dup 4) 1117 (const_int -1))) 1118 (parallel [(set (match_operand:HI 0 "register_operand" "") 1119 (minus:HI (match_dup 4) 1120 (match_dup 5))) 1121 (clobber (scratch:QI))])] 1122 "" 1123 { 1124 rtx addr; 1125 if (operands[2] != const0_rtx) 1126 FAIL; 1127 addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 1128 operands[1] = gen_rtx_MEM (BLKmode, addr); 1129 operands[5] = addr; 1130 operands[4] = gen_reg_rtx (HImode); 1131 }) 1132 1133(define_insn "*strlenhi" 1134 [(set (match_operand:HI 0 "register_operand" "=e") 1135 (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "0")) 1136 (const_int 0) 1137 (match_operand:HI 2 "immediate_operand" "i")] 1138 UNSPEC_STRLEN))] 1139 "" 1140 "0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b" 1141 [(set_attr "length" "3") 1142 (set_attr "cc" "clobber")]) 1143 1144;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1145; add bytes 1146 1147;; "addqi3" 1148;; "addqq3" "adduqq3" 1149(define_insn "add<mode>3" 1150 [(set (match_operand:ALL1 0 "register_operand" "=r,d ,r ,r ,r ,r") 1151 (plus:ALL1 (match_operand:ALL1 1 "register_operand" "%0,0 ,0 ,0 ,0 ,0") 1152 (match_operand:ALL1 2 "nonmemory_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))] 1153 "" 1154 "@ 1155 add %0,%2 1156 subi %0,lo8(-(%2)) 1157 inc %0 1158 dec %0 1159 inc %0\;inc %0 1160 dec %0\;dec %0" 1161 [(set_attr "length" "1,1,1,1,2,2") 1162 (set_attr "cc" "set_czn,set_czn,set_vzn,set_vzn,set_vzn,set_vzn")]) 1163 1164;; "addhi3" 1165;; "addhq3" "adduhq3" 1166;; "addha3" "adduha3" 1167(define_expand "add<mode>3" 1168 [(set (match_operand:ALL2 0 "register_operand" "") 1169 (plus:ALL2 (match_operand:ALL2 1 "register_operand" "") 1170 (match_operand:ALL2 2 "nonmemory_or_const_operand" "")))] 1171 "" 1172 { 1173 if (CONST_INT_P (operands[2])) 1174 { 1175 operands[2] = gen_int_mode (INTVAL (operands[2]), HImode); 1176 1177 if (can_create_pseudo_p() 1178 && !stack_register_operand (operands[0], HImode) 1179 && !stack_register_operand (operands[1], HImode) 1180 && !d_register_operand (operands[0], HImode) 1181 && !d_register_operand (operands[1], HImode)) 1182 { 1183 emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2])); 1184 DONE; 1185 } 1186 } 1187 1188 if (CONST_FIXED_P (operands[2])) 1189 { 1190 emit_insn (gen_add<mode>3_clobber (operands[0], operands[1], operands[2])); 1191 DONE; 1192 } 1193 }) 1194 1195 1196(define_insn "*addhi3_zero_extend" 1197 [(set (match_operand:HI 0 "register_operand" "=r") 1198 (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) 1199 (match_operand:HI 2 "register_operand" "0")))] 1200 "" 1201 "add %A0,%1\;adc %B0,__zero_reg__" 1202 [(set_attr "length" "2") 1203 (set_attr "cc" "set_n")]) 1204 1205(define_insn "*addhi3_zero_extend1" 1206 [(set (match_operand:HI 0 "register_operand" "=r") 1207 (plus:HI (match_operand:HI 1 "register_operand" "0") 1208 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] 1209 "" 1210 "add %A0,%2\;adc %B0,__zero_reg__" 1211 [(set_attr "length" "2") 1212 (set_attr "cc" "set_n")]) 1213 1214(define_insn "*addhi3.sign_extend1" 1215 [(set (match_operand:HI 0 "register_operand" "=r") 1216 (plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r")) 1217 (match_operand:HI 2 "register_operand" "0")))] 1218 "" 1219 { 1220 return reg_overlap_mentioned_p (operands[0], operands[1]) 1221 ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;dec %B0" 1222 : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0"; 1223 } 1224 [(set_attr "length" "5") 1225 (set_attr "cc" "clobber")]) 1226 1227(define_insn "*addhi3_sp" 1228 [(set (match_operand:HI 1 "stack_register_operand" "=q") 1229 (plus:HI (match_operand:HI 2 "stack_register_operand" "q") 1230 (match_operand:HI 0 "avr_sp_immediate_operand" "Csp")))] 1231 "" 1232 { 1233 return avr_out_addto_sp (operands, NULL); 1234 } 1235 [(set_attr "length" "6") 1236 (set_attr "adjust_len" "addto_sp")]) 1237 1238;; "*addhi3" 1239;; "*addhq3" "*adduhq3" 1240;; "*addha3" "*adduha3" 1241(define_insn "*add<mode>3" 1242 [(set (match_operand:ALL2 0 "register_operand" "=??r,d,!w ,d") 1243 (plus:ALL2 (match_operand:ALL2 1 "register_operand" "%0,0,0 ,0") 1244 (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))] 1245 "" 1246 { 1247 return avr_out_plus (insn, operands); 1248 } 1249 [(set_attr "length" "2") 1250 (set_attr "adjust_len" "plus") 1251 (set_attr "cc" "plus")]) 1252 1253;; Adding a constant to NO_LD_REGS might have lead to a reload of 1254;; that constant to LD_REGS. We don't add a scratch to *addhi3 1255;; itself because that insn is special to reload. 1256 1257(define_peephole2 ; addhi3_clobber 1258 [(set (match_operand:ALL2 0 "d_register_operand" "") 1259 (match_operand:ALL2 1 "const_operand" "")) 1260 (set (match_operand:ALL2 2 "l_register_operand" "") 1261 (plus:ALL2 (match_dup 2) 1262 (match_dup 0)))] 1263 "peep2_reg_dead_p (2, operands[0])" 1264 [(parallel [(set (match_dup 2) 1265 (plus:ALL2 (match_dup 2) 1266 (match_dup 1))) 1267 (clobber (match_dup 3))])] 1268 { 1269 operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0); 1270 }) 1271 1272;; Same, but with reload to NO_LD_REGS 1273;; Combine *reload_inhi with *addhi3 1274 1275(define_peephole2 ; addhi3_clobber 1276 [(parallel [(set (match_operand:ALL2 0 "l_register_operand" "") 1277 (match_operand:ALL2 1 "const_operand" "")) 1278 (clobber (match_operand:QI 2 "d_register_operand" ""))]) 1279 (set (match_operand:ALL2 3 "l_register_operand" "") 1280 (plus:ALL2 (match_dup 3) 1281 (match_dup 0)))] 1282 "peep2_reg_dead_p (2, operands[0])" 1283 [(parallel [(set (match_dup 3) 1284 (plus:ALL2 (match_dup 3) 1285 (match_dup 1))) 1286 (clobber (match_dup 2))])]) 1287 1288;; "addhi3_clobber" 1289;; "addhq3_clobber" "adduhq3_clobber" 1290;; "addha3_clobber" "adduha3_clobber" 1291(define_insn "add<mode>3_clobber" 1292 [(set (match_operand:ALL2 0 "register_operand" "=!w ,d ,r") 1293 (plus:ALL2 (match_operand:ALL2 1 "register_operand" "%0 ,0 ,0") 1294 (match_operand:ALL2 2 "const_operand" "IJ YIJ,n Ynn,n Ynn"))) 1295 (clobber (match_scratch:QI 3 "=X ,X ,&d"))] 1296 "" 1297 { 1298 return avr_out_plus (insn, operands); 1299 } 1300 [(set_attr "length" "4") 1301 (set_attr "adjust_len" "plus") 1302 (set_attr "cc" "plus")]) 1303 1304 1305;; "addsi3" 1306;; "addsq3" "addusq3" 1307;; "addsa3" "addusa3" 1308(define_insn "add<mode>3" 1309 [(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r") 1310 (plus:ALL4 (match_operand:ALL4 1 "register_operand" "%0,0 ,0") 1311 (match_operand:ALL4 2 "nonmemory_operand" "r,i ,n Ynn"))) 1312 (clobber (match_scratch:QI 3 "=X,X ,&d"))] 1313 "" 1314 { 1315 return avr_out_plus (insn, operands); 1316 } 1317 [(set_attr "length" "4") 1318 (set_attr "adjust_len" "plus") 1319 (set_attr "cc" "plus")]) 1320 1321(define_insn "*addpsi3_zero_extend.qi" 1322 [(set (match_operand:PSI 0 "register_operand" "=r") 1323 (plus:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r")) 1324 (match_operand:PSI 2 "register_operand" "0")))] 1325 "" 1326 "add %A0,%A1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__" 1327 [(set_attr "length" "3") 1328 (set_attr "cc" "set_n")]) 1329 1330(define_insn "*addpsi3_zero_extend.hi" 1331 [(set (match_operand:PSI 0 "register_operand" "=r") 1332 (plus:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r")) 1333 (match_operand:PSI 2 "register_operand" "0")))] 1334 "" 1335 "add %A0,%A1\;adc %B0,%B1\;adc %C0,__zero_reg__" 1336 [(set_attr "length" "3") 1337 (set_attr "cc" "set_n")]) 1338 1339(define_insn "*addpsi3_sign_extend.hi" 1340 [(set (match_operand:PSI 0 "register_operand" "=r") 1341 (plus:PSI (sign_extend:PSI (match_operand:HI 1 "register_operand" "r")) 1342 (match_operand:PSI 2 "register_operand" "0")))] 1343 "" 1344 "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;sbrc %B1,7\;dec %C0" 1345 [(set_attr "length" "5") 1346 (set_attr "cc" "set_n")]) 1347 1348(define_insn "*addsi3_zero_extend" 1349 [(set (match_operand:SI 0 "register_operand" "=r") 1350 (plus:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) 1351 (match_operand:SI 2 "register_operand" "0")))] 1352 "" 1353 "add %A0,%1\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__" 1354 [(set_attr "length" "4") 1355 (set_attr "cc" "set_n")]) 1356 1357(define_insn "*addsi3_zero_extend.hi" 1358 [(set (match_operand:SI 0 "register_operand" "=r") 1359 (plus:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) 1360 (match_operand:SI 2 "register_operand" "0")))] 1361 "" 1362 "add %A0,%1\;adc %B0,%B1\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__" 1363 [(set_attr "length" "4") 1364 (set_attr "cc" "set_n")]) 1365 1366(define_insn "addpsi3" 1367 [(set (match_operand:PSI 0 "register_operand" "=??r,d ,d,r") 1368 (plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0") 1369 (match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n"))) 1370 (clobber (match_scratch:QI 3 "=X,X ,X,&d"))] 1371 "" 1372 { 1373 return avr_out_plus (insn, operands); 1374 } 1375 [(set_attr "length" "3") 1376 (set_attr "adjust_len" "plus") 1377 (set_attr "cc" "plus")]) 1378 1379(define_insn "subpsi3" 1380 [(set (match_operand:PSI 0 "register_operand" "=r") 1381 (minus:PSI (match_operand:PSI 1 "register_operand" "0") 1382 (match_operand:PSI 2 "register_operand" "r")))] 1383 "" 1384 "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2" 1385 [(set_attr "length" "3") 1386 (set_attr "cc" "set_czn")]) 1387 1388(define_insn "*subpsi3_zero_extend.qi" 1389 [(set (match_operand:PSI 0 "register_operand" "=r") 1390 (minus:PSI (match_operand:SI 1 "register_operand" "0") 1391 (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))] 1392 "" 1393 "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__" 1394 [(set_attr "length" "3") 1395 (set_attr "cc" "set_czn")]) 1396 1397(define_insn "*subpsi3_zero_extend.hi" 1398 [(set (match_operand:PSI 0 "register_operand" "=r") 1399 (minus:PSI (match_operand:PSI 1 "register_operand" "0") 1400 (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))] 1401 "" 1402 "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__" 1403 [(set_attr "length" "3") 1404 (set_attr "cc" "set_czn")]) 1405 1406(define_insn "*subpsi3_sign_extend.hi" 1407 [(set (match_operand:PSI 0 "register_operand" "=r") 1408 (minus:PSI (match_operand:PSI 1 "register_operand" "0") 1409 (sign_extend:PSI (match_operand:HI 2 "register_operand" "r"))))] 1410 "" 1411 "sub %A0,%A2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbrc %B2,7\;inc %C0" 1412 [(set_attr "length" "5") 1413 (set_attr "cc" "set_czn")]) 1414 1415;----------------------------------------------------------------------------- 1416; sub bytes 1417 1418;; "subqi3" 1419;; "subqq3" "subuqq3" 1420(define_insn "sub<mode>3" 1421 [(set (match_operand:ALL1 0 "register_operand" "=??r,d ,r ,r ,r ,r") 1422 (minus:ALL1 (match_operand:ALL1 1 "register_operand" "0,0 ,0 ,0 ,0 ,0") 1423 (match_operand:ALL1 2 "nonmemory_or_const_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))] 1424 "" 1425 "@ 1426 sub %0,%2 1427 subi %0,lo8(%2) 1428 dec %0 1429 inc %0 1430 dec %0\;dec %0 1431 inc %0\;inc %0" 1432 [(set_attr "length" "1,1,1,1,2,2") 1433 (set_attr "cc" "set_czn,set_czn,set_vzn,set_vzn,set_vzn,set_vzn")]) 1434 1435;; "subhi3" 1436;; "subhq3" "subuhq3" 1437;; "subha3" "subuha3" 1438(define_insn "sub<mode>3" 1439 [(set (match_operand:ALL2 0 "register_operand" "=??r,d ,*r") 1440 (minus:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,0") 1441 (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,i Ynn,Ynn"))) 1442 (clobber (match_scratch:QI 3 "=X,X ,&d"))] 1443 "" 1444 { 1445 return avr_out_plus (insn, operands); 1446 } 1447 [(set_attr "adjust_len" "plus") 1448 (set_attr "cc" "plus")]) 1449 1450(define_insn "*subhi3_zero_extend1" 1451 [(set (match_operand:HI 0 "register_operand" "=r") 1452 (minus:HI (match_operand:HI 1 "register_operand" "0") 1453 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] 1454 "" 1455 "sub %A0,%2\;sbc %B0,__zero_reg__" 1456 [(set_attr "length" "2") 1457 (set_attr "cc" "set_czn")]) 1458 1459(define_insn "*subhi3.sign_extend2" 1460 [(set (match_operand:HI 0 "register_operand" "=r") 1461 (minus:HI (match_operand:HI 1 "register_operand" "0") 1462 (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))] 1463 "" 1464 { 1465 return reg_overlap_mentioned_p (operands[0], operands[2]) 1466 ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;inc %B0" 1467 : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0"; 1468 } 1469 [(set_attr "length" "5") 1470 (set_attr "cc" "clobber")]) 1471 1472;; "subsi3" 1473;; "subsq3" "subusq3" 1474;; "subsa3" "subusa3" 1475(define_insn "sub<mode>3" 1476 [(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r") 1477 (minus:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,0") 1478 (match_operand:ALL4 2 "nonmemory_or_const_operand" "r,n Ynn,Ynn"))) 1479 (clobber (match_scratch:QI 3 "=X,X ,&d"))] 1480 "" 1481 { 1482 return avr_out_plus (insn, operands); 1483 } 1484 [(set_attr "adjust_len" "plus") 1485 (set_attr "cc" "plus")]) 1486 1487(define_insn "*subsi3_zero_extend" 1488 [(set (match_operand:SI 0 "register_operand" "=r") 1489 (minus:SI (match_operand:SI 1 "register_operand" "0") 1490 (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))] 1491 "" 1492 "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__" 1493 [(set_attr "length" "4") 1494 (set_attr "cc" "set_czn")]) 1495 1496(define_insn "*subsi3_zero_extend.hi" 1497 [(set (match_operand:SI 0 "register_operand" "=r") 1498 (minus:SI (match_operand:SI 1 "register_operand" "0") 1499 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1500 "" 1501 "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__" 1502 [(set_attr "length" "4") 1503 (set_attr "cc" "set_czn")]) 1504 1505;****************************************************************************** 1506; mul 1507 1508(define_expand "mulqi3" 1509 [(set (match_operand:QI 0 "register_operand" "") 1510 (mult:QI (match_operand:QI 1 "register_operand" "") 1511 (match_operand:QI 2 "register_operand" "")))] 1512 "" 1513 { 1514 if (!AVR_HAVE_MUL) 1515 { 1516 emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2])); 1517 DONE; 1518 } 1519 }) 1520 1521(define_insn "*mulqi3_enh" 1522 [(set (match_operand:QI 0 "register_operand" "=r") 1523 (mult:QI (match_operand:QI 1 "register_operand" "r") 1524 (match_operand:QI 2 "register_operand" "r")))] 1525 "AVR_HAVE_MUL" 1526 "mul %1,%2 1527 mov %0,r0 1528 clr r1" 1529 [(set_attr "length" "3") 1530 (set_attr "cc" "clobber")]) 1531 1532(define_expand "mulqi3_call" 1533 [(set (reg:QI 24) (match_operand:QI 1 "register_operand" "")) 1534 (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) 1535 (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22))) 1536 (clobber (reg:QI 22))]) 1537 (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))] 1538 "" 1539 { 1540 avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); 1541 }) 1542 1543(define_insn "*mulqi3_call" 1544 [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22))) 1545 (clobber (reg:QI 22))] 1546 "!AVR_HAVE_MUL" 1547 "%~call __mulqi3" 1548 [(set_attr "type" "xcall") 1549 (set_attr "cc" "clobber")]) 1550 1551;; "umulqi3_highpart" 1552;; "smulqi3_highpart" 1553(define_insn "<extend_su>mulqi3_highpart" 1554 [(set (match_operand:QI 0 "register_operand" "=r") 1555 (truncate:QI 1556 (lshiftrt:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 1557 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))) 1558 (const_int 8))))] 1559 "AVR_HAVE_MUL" 1560 "mul<extend_s> %1,%2 1561 mov %0,r1 1562 clr __zero_reg__" 1563 [(set_attr "length" "3") 1564 (set_attr "cc" "clobber")]) 1565 1566 1567;; Used when expanding div or mod inline for some special values 1568(define_insn "*subqi3.ashiftrt7" 1569 [(set (match_operand:QI 0 "register_operand" "=r") 1570 (minus:QI (match_operand:QI 1 "register_operand" "0") 1571 (ashiftrt:QI (match_operand:QI 2 "register_operand" "r") 1572 (const_int 7))))] 1573 "" 1574 "sbrc %2,7\;inc %0" 1575 [(set_attr "length" "2") 1576 (set_attr "cc" "clobber")]) 1577 1578(define_insn "*addqi3.lt0" 1579 [(set (match_operand:QI 0 "register_operand" "=r") 1580 (plus:QI (lt:QI (match_operand:QI 1 "register_operand" "r") 1581 (const_int 0)) 1582 (match_operand:QI 2 "register_operand" "0")))] 1583 "" 1584 "sbrc %1,7\;inc %0" 1585 [(set_attr "length" "2") 1586 (set_attr "cc" "clobber")]) 1587 1588(define_insn "*addhi3.lt0" 1589 [(set (match_operand:HI 0 "register_operand" "=w,r") 1590 (plus:HI (lt:HI (match_operand:QI 1 "register_operand" "r,r") 1591 (const_int 0)) 1592 (match_operand:HI 2 "register_operand" "0,0"))) 1593 (clobber (match_scratch:QI 3 "=X,&1"))] 1594 "" 1595 "@ 1596 sbrc %1,7\;adiw %0,1 1597 lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__" 1598 [(set_attr "length" "2,3") 1599 (set_attr "cc" "clobber")]) 1600 1601(define_insn "*addpsi3.lt0" 1602 [(set (match_operand:PSI 0 "register_operand" "=r") 1603 (plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand" "r") 1604 (const_int 23)) 1605 (match_operand:PSI 2 "register_operand" "0")))] 1606 "" 1607 "mov __tmp_reg__,%C1\;lsl __tmp_reg__ 1608 adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__" 1609 [(set_attr "length" "5") 1610 (set_attr "cc" "clobber")]) 1611 1612(define_insn "*addsi3.lt0" 1613 [(set (match_operand:SI 0 "register_operand" "=r") 1614 (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") 1615 (const_int 31)) 1616 (match_operand:SI 2 "register_operand" "0")))] 1617 "" 1618 "mov __tmp_reg__,%D1\;lsl __tmp_reg__ 1619 adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__" 1620 [(set_attr "length" "6") 1621 (set_attr "cc" "clobber")]) 1622 1623(define_insn "*umulqihi3.call" 1624 [(set (reg:HI 24) 1625 (mult:HI (zero_extend:HI (reg:QI 22)) 1626 (zero_extend:HI (reg:QI 24)))) 1627 (clobber (reg:QI 21)) 1628 (clobber (reg:HI 22))] 1629 "!AVR_HAVE_MUL" 1630 "%~call __umulqihi3" 1631 [(set_attr "type" "xcall") 1632 (set_attr "cc" "clobber")]) 1633 1634;; "umulqihi3" 1635;; "mulqihi3" 1636(define_insn "<extend_u>mulqihi3" 1637 [(set (match_operand:HI 0 "register_operand" "=r") 1638 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 1639 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))))] 1640 "AVR_HAVE_MUL" 1641 "mul<extend_s> %1,%2 1642 movw %0,r0 1643 clr __zero_reg__" 1644 [(set_attr "length" "3") 1645 (set_attr "cc" "clobber")]) 1646 1647(define_insn "usmulqihi3" 1648 [(set (match_operand:HI 0 "register_operand" "=r") 1649 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a")) 1650 (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))] 1651 "AVR_HAVE_MUL" 1652 "mulsu %2,%1 1653 movw %0,r0 1654 clr __zero_reg__" 1655 [(set_attr "length" "3") 1656 (set_attr "cc" "clobber")]) 1657 1658;; Above insn is not canonicalized by insn combine, so here is a version with 1659;; operands swapped. 1660 1661(define_insn "*sumulqihi3" 1662 [(set (match_operand:HI 0 "register_operand" "=r") 1663 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 1664 (zero_extend:HI (match_operand:QI 2 "register_operand" "a"))))] 1665 "AVR_HAVE_MUL" 1666 "mulsu %1,%2 1667 movw %0,r0 1668 clr __zero_reg__" 1669 [(set_attr "length" "3") 1670 (set_attr "cc" "clobber")]) 1671 1672;; One-extend operand 1 1673 1674(define_insn "*osmulqihi3" 1675 [(set (match_operand:HI 0 "register_operand" "=&r") 1676 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "a")))) 1677 (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))] 1678 "AVR_HAVE_MUL" 1679 "mulsu %2,%1 1680 movw %0,r0 1681 sub %B0,%2 1682 clr __zero_reg__" 1683 [(set_attr "length" "4") 1684 (set_attr "cc" "clobber")]) 1685 1686(define_insn "*oumulqihi3" 1687 [(set (match_operand:HI 0 "register_operand" "=&r") 1688 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r")))) 1689 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] 1690 "AVR_HAVE_MUL" 1691 "mul %2,%1 1692 movw %0,r0 1693 sub %B0,%2 1694 clr __zero_reg__" 1695 [(set_attr "length" "4") 1696 (set_attr "cc" "clobber")]) 1697 1698;****************************************************************************** 1699; multiply-add/sub QI: $0 = $3 +/- $1*$2 1700;****************************************************************************** 1701 1702(define_insn "*maddqi4" 1703 [(set (match_operand:QI 0 "register_operand" "=r") 1704 (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r") 1705 (match_operand:QI 2 "register_operand" "r")) 1706 (match_operand:QI 3 "register_operand" "0")))] 1707 1708 "AVR_HAVE_MUL" 1709 "mul %1,%2 1710 add %A0,r0 1711 clr __zero_reg__" 1712 [(set_attr "length" "4") 1713 (set_attr "cc" "clobber")]) 1714 1715(define_insn "*msubqi4" 1716 [(set (match_operand:QI 0 "register_operand" "=r") 1717 (minus:QI (match_operand:QI 3 "register_operand" "0") 1718 (mult:QI (match_operand:QI 1 "register_operand" "r") 1719 (match_operand:QI 2 "register_operand" "r"))))] 1720 "AVR_HAVE_MUL" 1721 "mul %1,%2 1722 sub %A0,r0 1723 clr __zero_reg__" 1724 [(set_attr "length" "4") 1725 (set_attr "cc" "clobber")]) 1726 1727(define_insn_and_split "*maddqi4.const" 1728 [(set (match_operand:QI 0 "register_operand" "=r") 1729 (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r") 1730 (match_operand:QI 2 "const_int_operand" "n")) 1731 (match_operand:QI 3 "register_operand" "0"))) 1732 (clobber (match_scratch:QI 4 "=&d"))] 1733 "AVR_HAVE_MUL" 1734 "#" 1735 "&& reload_completed" 1736 [(set (match_dup 4) 1737 (match_dup 2)) 1738 ; *maddqi4 1739 (set (match_dup 0) 1740 (plus:QI (mult:QI (match_dup 1) 1741 (match_dup 4)) 1742 (match_dup 3)))]) 1743 1744(define_insn_and_split "*msubqi4.const" 1745 [(set (match_operand:QI 0 "register_operand" "=r") 1746 (minus:QI (match_operand:QI 3 "register_operand" "0") 1747 (mult:QI (match_operand:QI 1 "register_operand" "r") 1748 (match_operand:QI 2 "const_int_operand" "n")))) 1749 (clobber (match_scratch:QI 4 "=&d"))] 1750 "AVR_HAVE_MUL" 1751 "#" 1752 "&& reload_completed" 1753 [(set (match_dup 4) 1754 (match_dup 2)) 1755 ; *msubqi4 1756 (set (match_dup 0) 1757 (minus:QI (match_dup 3) 1758 (mult:QI (match_dup 1) 1759 (match_dup 4))))]) 1760 1761 1762;****************************************************************************** 1763; multiply-add/sub HI: $0 = $3 +/- $1*$2 with 8-bit values $1, $2 1764;****************************************************************************** 1765 1766;; We don't use standard insns/expanders as they lead to cumbersome code for, 1767;; e.g, 1768;; 1769;; int foo (unsigned char z) 1770;; { 1771;; extern int aInt[]; 1772;; return aInt[3*z+2]; 1773;; } 1774;; 1775;; because the constant +4 then is added explicitely instead of consuming it 1776;; with the aInt symbol. Therefore, we rely on insn combine which takes costs 1777;; into account more accurately and doesn't do burte-force multiply-add/sub. 1778;; The implementational effort is the same so we are fine with that approach. 1779 1780 1781;; "*maddqihi4" 1782;; "*umaddqihi4" 1783(define_insn "*<extend_u>maddqihi4" 1784 [(set (match_operand:HI 0 "register_operand" "=r") 1785 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 1786 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>"))) 1787 (match_operand:HI 3 "register_operand" "0")))] 1788 1789 "AVR_HAVE_MUL" 1790 "mul<extend_s> %1,%2 1791 add %A0,r0 1792 adc %B0,r1 1793 clr __zero_reg__" 1794 [(set_attr "length" "4") 1795 (set_attr "cc" "clobber")]) 1796 1797;; "*msubqihi4" 1798;; "*umsubqihi4" 1799(define_insn "*<extend_u>msubqihi4" 1800 [(set (match_operand:HI 0 "register_operand" "=r") 1801 (minus:HI (match_operand:HI 3 "register_operand" "0") 1802 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 1803 (any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))))] 1804 "AVR_HAVE_MUL" 1805 "mul<extend_s> %1,%2 1806 sub %A0,r0 1807 sbc %B0,r1 1808 clr __zero_reg__" 1809 [(set_attr "length" "4") 1810 (set_attr "cc" "clobber")]) 1811 1812;; "*usmaddqihi4" 1813;; "*sumaddqihi4" 1814(define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4" 1815 [(set (match_operand:HI 0 "register_operand" "=r") 1816 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a")) 1817 (any_extend2:HI (match_operand:QI 2 "register_operand" "a"))) 1818 (match_operand:HI 3 "register_operand" "0")))] 1819 "AVR_HAVE_MUL 1820 && reload_completed 1821 && <any_extend:CODE> != <any_extend2:CODE>" 1822 { 1823 output_asm_insn (<any_extend:CODE> == SIGN_EXTEND 1824 ? "mulsu %1,%2" : "mulsu %2,%1", operands); 1825 1826 return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__"; 1827 } 1828 [(set_attr "length" "4") 1829 (set_attr "cc" "clobber")]) 1830 1831;; "*usmsubqihi4" 1832;; "*sumsubqihi4" 1833(define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4" 1834 [(set (match_operand:HI 0 "register_operand" "=r") 1835 (minus:HI (match_operand:HI 3 "register_operand" "0") 1836 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a")) 1837 (any_extend2:HI (match_operand:QI 2 "register_operand" "a")))))] 1838 "AVR_HAVE_MUL 1839 && reload_completed 1840 && <any_extend:CODE> != <any_extend2:CODE>" 1841 { 1842 output_asm_insn (<any_extend:CODE> == SIGN_EXTEND 1843 ? "mulsu %1,%2" : "mulsu %2,%1", operands); 1844 1845 return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__"; 1846 } 1847 [(set_attr "length" "4") 1848 (set_attr "cc" "clobber")]) 1849 1850;; Handle small constants 1851 1852;; Special case of a += 2*b as frequently seen with accesses to int arrays. 1853;; This is shorter, faster than MUL and has lower register pressure. 1854 1855(define_insn_and_split "*umaddqihi4.2" 1856 [(set (match_operand:HI 0 "register_operand" "=r") 1857 (plus:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) 1858 (const_int 2)) 1859 (match_operand:HI 2 "register_operand" "r")))] 1860 "!reload_completed 1861 && !reg_overlap_mentioned_p (operands[0], operands[1])" 1862 { gcc_unreachable(); } 1863 "&& 1" 1864 [(set (match_dup 0) 1865 (match_dup 2)) 1866 ; *addhi3_zero_extend 1867 (set (match_dup 0) 1868 (plus:HI (zero_extend:HI (match_dup 1)) 1869 (match_dup 0))) 1870 ; *addhi3_zero_extend 1871 (set (match_dup 0) 1872 (plus:HI (zero_extend:HI (match_dup 1)) 1873 (match_dup 0)))]) 1874 1875;; "umaddqihi4.uconst" 1876;; "maddqihi4.sconst" 1877(define_insn_and_split "*<extend_u>maddqihi4.<extend_su>const" 1878 [(set (match_operand:HI 0 "register_operand" "=r") 1879 (plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 1880 (match_operand:HI 2 "<extend_su>8_operand" "n")) 1881 (match_operand:HI 3 "register_operand" "0"))) 1882 (clobber (match_scratch:QI 4 "=&d"))] 1883 "AVR_HAVE_MUL" 1884 "#" 1885 "&& reload_completed" 1886 [(set (match_dup 4) 1887 (match_dup 2)) 1888 ; *umaddqihi4 resp. *maddqihi4 1889 (set (match_dup 0) 1890 (plus:HI (mult:HI (any_extend:HI (match_dup 1)) 1891 (any_extend:HI (match_dup 4))) 1892 (match_dup 3)))] 1893 { 1894 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 1895 }) 1896 1897;; "*umsubqihi4.uconst" 1898;; "*msubqihi4.sconst" 1899(define_insn_and_split "*<extend_u>msubqihi4.<extend_su>const" 1900 [(set (match_operand:HI 0 "register_operand" "=r") 1901 (minus:HI (match_operand:HI 3 "register_operand" "0") 1902 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 1903 (match_operand:HI 2 "<extend_su>8_operand" "n")))) 1904 (clobber (match_scratch:QI 4 "=&d"))] 1905 "AVR_HAVE_MUL" 1906 "#" 1907 "&& reload_completed" 1908 [(set (match_dup 4) 1909 (match_dup 2)) 1910 ; *umsubqihi4 resp. *msubqihi4 1911 (set (match_dup 0) 1912 (minus:HI (match_dup 3) 1913 (mult:HI (any_extend:HI (match_dup 1)) 1914 (any_extend:HI (match_dup 4)))))] 1915 { 1916 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 1917 }) 1918 1919;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT 1920;; for MULT with power of 2 and skips trying MULT insn above. 1921 1922(define_insn_and_split "*umsubqihi4.uconst.ashift" 1923 [(set (match_operand:HI 0 "register_operand" "=r") 1924 (minus:HI (match_operand:HI 3 "register_operand" "0") 1925 (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) 1926 (match_operand:HI 2 "const_2_to_7_operand" "n")))) 1927 (clobber (match_scratch:QI 4 "=&d"))] 1928 "AVR_HAVE_MUL" 1929 "#" 1930 "&& reload_completed" 1931 [(set (match_dup 4) 1932 (match_dup 2)) 1933 ; *umsubqihi4 1934 (set (match_dup 0) 1935 (minus:HI (match_dup 3) 1936 (mult:HI (zero_extend:HI (match_dup 1)) 1937 (zero_extend:HI (match_dup 4)))))] 1938 { 1939 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode); 1940 }) 1941 1942;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT 1943;; for MULT with power of 2 and skips trying MULT insn above. We omit 128 1944;; because this would require an extra pattern for just one value. 1945 1946(define_insn_and_split "*msubqihi4.sconst.ashift" 1947 [(set (match_operand:HI 0 "register_operand" "=r") 1948 (minus:HI (match_operand:HI 3 "register_operand" "0") 1949 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d")) 1950 (match_operand:HI 2 "const_1_to_6_operand" "M")))) 1951 (clobber (match_scratch:QI 4 "=&d"))] 1952 "AVR_HAVE_MUL" 1953 "#" 1954 "&& reload_completed" 1955 [(set (match_dup 4) 1956 (match_dup 2)) 1957 ; *smsubqihi4 1958 (set (match_dup 0) 1959 (minus:HI (match_dup 3) 1960 (mult:HI (sign_extend:HI (match_dup 1)) 1961 (sign_extend:HI (match_dup 4)))))] 1962 { 1963 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode); 1964 }) 1965 1966;; For signed/unsigned combinations that require narrow constraint "a" 1967;; just provide a pattern if signed/unsigned combination is actually needed. 1968 1969(define_insn_and_split "*sumaddqihi4.uconst" 1970 [(set (match_operand:HI 0 "register_operand" "=r") 1971 (plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 1972 (match_operand:HI 2 "u8_operand" "M")) 1973 (match_operand:HI 3 "register_operand" "0"))) 1974 (clobber (match_scratch:QI 4 "=&a"))] 1975 "AVR_HAVE_MUL 1976 && !s8_operand (operands[2], VOIDmode)" 1977 "#" 1978 "&& reload_completed" 1979 [(set (match_dup 4) 1980 (match_dup 2)) 1981 ; *sumaddqihi4 1982 (set (match_dup 0) 1983 (plus:HI (mult:HI (sign_extend:HI (match_dup 1)) 1984 (zero_extend:HI (match_dup 4))) 1985 (match_dup 3)))] 1986 { 1987 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 1988 }) 1989 1990(define_insn_and_split "*sumsubqihi4.uconst" 1991 [(set (match_operand:HI 0 "register_operand" "=r") 1992 (minus:HI (match_operand:HI 3 "register_operand" "0") 1993 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 1994 (match_operand:HI 2 "u8_operand" "M")))) 1995 (clobber (match_scratch:QI 4 "=&a"))] 1996 "AVR_HAVE_MUL 1997 && !s8_operand (operands[2], VOIDmode)" 1998 "#" 1999 "&& reload_completed" 2000 [(set (match_dup 4) 2001 (match_dup 2)) 2002 ; *sumsubqihi4 2003 (set (match_dup 0) 2004 (minus:HI (match_dup 3) 2005 (mult:HI (sign_extend:HI (match_dup 1)) 2006 (zero_extend:HI (match_dup 4)))))] 2007 { 2008 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 2009 }) 2010 2011;****************************************************************************** 2012; mul HI: $1 = sign/zero-extend, $2 = small constant 2013;****************************************************************************** 2014 2015;; "*muluqihi3.uconst" 2016;; "*mulsqihi3.sconst" 2017(define_insn_and_split "*mul<extend_su>qihi3.<extend_su>const" 2018 [(set (match_operand:HI 0 "register_operand" "=r") 2019 (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>")) 2020 (match_operand:HI 2 "<extend_su>8_operand" "n"))) 2021 (clobber (match_scratch:QI 3 "=&d"))] 2022 "AVR_HAVE_MUL" 2023 "#" 2024 "&& reload_completed" 2025 [(set (match_dup 3) 2026 (match_dup 2)) 2027 ; umulqihi3 resp. mulqihi3 2028 (set (match_dup 0) 2029 (mult:HI (any_extend:HI (match_dup 1)) 2030 (any_extend:HI (match_dup 3))))] 2031 { 2032 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 2033 }) 2034 2035(define_insn_and_split "*muluqihi3.sconst" 2036 [(set (match_operand:HI 0 "register_operand" "=r") 2037 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a")) 2038 (match_operand:HI 2 "s8_operand" "n"))) 2039 (clobber (match_scratch:QI 3 "=&a"))] 2040 "AVR_HAVE_MUL" 2041 "#" 2042 "&& reload_completed" 2043 [(set (match_dup 3) 2044 (match_dup 2)) 2045 ; usmulqihi3 2046 (set (match_dup 0) 2047 (mult:HI (zero_extend:HI (match_dup 1)) 2048 (sign_extend:HI (match_dup 3))))] 2049 { 2050 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 2051 }) 2052 2053(define_insn_and_split "*mulsqihi3.uconst" 2054 [(set (match_operand:HI 0 "register_operand" "=r") 2055 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 2056 (match_operand:HI 2 "u8_operand" "M"))) 2057 (clobber (match_scratch:QI 3 "=&a"))] 2058 "AVR_HAVE_MUL" 2059 "#" 2060 "&& reload_completed" 2061 [(set (match_dup 3) 2062 (match_dup 2)) 2063 ; usmulqihi3 2064 (set (match_dup 0) 2065 (mult:HI (zero_extend:HI (match_dup 3)) 2066 (sign_extend:HI (match_dup 1))))] 2067 { 2068 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 2069 }) 2070 2071(define_insn_and_split "*mulsqihi3.oconst" 2072 [(set (match_operand:HI 0 "register_operand" "=&r") 2073 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 2074 (match_operand:HI 2 "o8_operand" "n"))) 2075 (clobber (match_scratch:QI 3 "=&a"))] 2076 "AVR_HAVE_MUL" 2077 "#" 2078 "&& reload_completed" 2079 [(set (match_dup 3) 2080 (match_dup 2)) 2081 ; *osmulqihi3 2082 (set (match_dup 0) 2083 (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 3)))) 2084 (sign_extend:HI (match_dup 1))))] 2085 { 2086 operands[2] = gen_int_mode (INTVAL (operands[2]), QImode); 2087 }) 2088 2089;; The EXTEND of $1 only appears in combine, we don't see it in expand so that 2090;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper 2091;; at that time. Fix that. 2092 2093(define_insn "*ashiftqihi2.signx.1" 2094 [(set (match_operand:HI 0 "register_operand" "=r,*r") 2095 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r")) 2096 (const_int 1)))] 2097 "" 2098 "@ 2099 lsl %A0\;sbc %B0,%B0 2100 mov %A0,%1\;lsl %A0\;sbc %B0,%B0" 2101 [(set_attr "length" "2,3") 2102 (set_attr "cc" "clobber")]) 2103 2104(define_insn_and_split "*ashifthi3.signx.const" 2105 [(set (match_operand:HI 0 "register_operand" "=r") 2106 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d")) 2107 (match_operand:HI 2 "const_2_to_6_operand" "I"))) 2108 (clobber (match_scratch:QI 3 "=&d"))] 2109 "AVR_HAVE_MUL" 2110 "#" 2111 "&& reload_completed" 2112 [(set (match_dup 3) 2113 (match_dup 2)) 2114 ; mulqihi3 2115 (set (match_dup 0) 2116 (mult:HI (sign_extend:HI (match_dup 1)) 2117 (sign_extend:HI (match_dup 3))))] 2118 { 2119 operands[2] = GEN_INT (1 << INTVAL (operands[2])); 2120 }) 2121 2122(define_insn_and_split "*ashifthi3.signx.const7" 2123 [(set (match_operand:HI 0 "register_operand" "=r") 2124 (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 2125 (const_int 7))) 2126 (clobber (match_scratch:QI 2 "=&a"))] 2127 "AVR_HAVE_MUL" 2128 "#" 2129 "&& reload_completed" 2130 [(set (match_dup 2) 2131 (match_dup 3)) 2132 ; usmulqihi3 2133 (set (match_dup 0) 2134 (mult:HI (zero_extend:HI (match_dup 2)) 2135 (sign_extend:HI (match_dup 1))))] 2136 { 2137 operands[3] = gen_int_mode (1 << 7, QImode); 2138 }) 2139 2140(define_insn_and_split "*ashifthi3.zerox.const" 2141 [(set (match_operand:HI 0 "register_operand" "=r") 2142 (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) 2143 (match_operand:HI 2 "const_2_to_7_operand" "I"))) 2144 (clobber (match_scratch:QI 3 "=&d"))] 2145 "AVR_HAVE_MUL" 2146 "#" 2147 "&& reload_completed" 2148 [(set (match_dup 3) 2149 (match_dup 2)) 2150 ; umulqihi3 2151 (set (match_dup 0) 2152 (mult:HI (zero_extend:HI (match_dup 1)) 2153 (zero_extend:HI (match_dup 3))))] 2154 { 2155 operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode); 2156 }) 2157 2158;****************************************************************************** 2159; mul HI: $1 = sign-/zero-/one-extend, $2 = reg 2160;****************************************************************************** 2161 2162(define_insn "mulsqihi3" 2163 [(set (match_operand:HI 0 "register_operand" "=&r") 2164 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a")) 2165 (match_operand:HI 2 "register_operand" "a")))] 2166 "AVR_HAVE_MUL" 2167 "mulsu %1,%A2 2168 movw %0,r0 2169 mul %1,%B2 2170 add %B0,r0 2171 clr __zero_reg__" 2172 [(set_attr "length" "5") 2173 (set_attr "cc" "clobber")]) 2174 2175(define_insn "muluqihi3" 2176 [(set (match_operand:HI 0 "register_operand" "=&r") 2177 (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) 2178 (match_operand:HI 2 "register_operand" "r")))] 2179 "AVR_HAVE_MUL" 2180 "mul %1,%A2 2181 movw %0,r0 2182 mul %1,%B2 2183 add %B0,r0 2184 clr __zero_reg__" 2185 [(set_attr "length" "5") 2186 (set_attr "cc" "clobber")]) 2187 2188;; one-extend operand 1 2189 2190(define_insn "muloqihi3" 2191 [(set (match_operand:HI 0 "register_operand" "=&r") 2192 (mult:HI (not:HI (zero_extend:HI (not:QI (match_operand:QI 1 "register_operand" "r")))) 2193 (match_operand:HI 2 "register_operand" "r")))] 2194 "AVR_HAVE_MUL" 2195 "mul %1,%A2 2196 movw %0,r0 2197 mul %1,%B2 2198 add %B0,r0 2199 sub %B0,%A2 2200 clr __zero_reg__" 2201 [(set_attr "length" "6") 2202 (set_attr "cc" "clobber")]) 2203 2204;****************************************************************************** 2205 2206(define_expand "mulhi3" 2207 [(set (match_operand:HI 0 "register_operand" "") 2208 (mult:HI (match_operand:HI 1 "register_operand" "") 2209 (match_operand:HI 2 "register_or_s9_operand" "")))] 2210 "" 2211 { 2212 if (!AVR_HAVE_MUL) 2213 { 2214 if (!register_operand (operands[2], HImode)) 2215 operands[2] = force_reg (HImode, operands[2]); 2216 2217 emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2])); 2218 DONE; 2219 } 2220 2221 /* ; For small constants we can do better by extending them on the fly. 2222 ; The constant can be loaded in one instruction and the widening 2223 ; multiplication is shorter. First try the unsigned variant because it 2224 ; allows constraint "d" instead of "a" for the signed version. */ 2225 2226 if (s9_operand (operands[2], HImode)) 2227 { 2228 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); 2229 2230 if (u8_operand (operands[2], HImode)) 2231 { 2232 emit_insn (gen_muluqihi3 (operands[0], reg, operands[1])); 2233 } 2234 else if (s8_operand (operands[2], HImode)) 2235 { 2236 emit_insn (gen_mulsqihi3 (operands[0], reg, operands[1])); 2237 } 2238 else 2239 { 2240 emit_insn (gen_muloqihi3 (operands[0], reg, operands[1])); 2241 } 2242 2243 DONE; 2244 } 2245 2246 if (!register_operand (operands[2], HImode)) 2247 operands[2] = force_reg (HImode, operands[2]); 2248 }) 2249 2250(define_insn "*mulhi3_enh" 2251 [(set (match_operand:HI 0 "register_operand" "=&r") 2252 (mult:HI (match_operand:HI 1 "register_operand" "r") 2253 (match_operand:HI 2 "register_operand" "r")))] 2254 "AVR_HAVE_MUL" 2255 { 2256 return REGNO (operands[1]) == REGNO (operands[2]) 2257 ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1" 2258 : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1"; 2259 } 2260 [(set_attr "length" "7") 2261 (set_attr "cc" "clobber")]) 2262 2263(define_expand "mulhi3_call" 2264 [(set (reg:HI 24) (match_operand:HI 1 "register_operand" "")) 2265 (set (reg:HI 22) (match_operand:HI 2 "register_operand" "")) 2266 (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22))) 2267 (clobber (reg:HI 22)) 2268 (clobber (reg:QI 21))]) 2269 (set (match_operand:HI 0 "register_operand" "") 2270 (reg:HI 24))] 2271 "" 2272 { 2273 avr_fix_inputs (operands, (1 << 2), regmask (HImode, 24)); 2274 }) 2275 2276 2277(define_insn "*mulhi3_call" 2278 [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22))) 2279 (clobber (reg:HI 22)) 2280 (clobber (reg:QI 21))] 2281 "!AVR_HAVE_MUL" 2282 "%~call __mulhi3" 2283 [(set_attr "type" "xcall") 2284 (set_attr "cc" "clobber")]) 2285 2286;; To support widening multiplication with constant we postpone 2287;; expanding to the implicit library call until post combine and 2288;; prior to register allocation. Clobber all hard registers that 2289;; might be used by the (widening) multiply until it is split and 2290;; it's final register footprint is worked out. 2291 2292(define_expand "mulsi3" 2293 [(parallel [(set (match_operand:SI 0 "register_operand" "") 2294 (mult:SI (match_operand:SI 1 "register_operand" "") 2295 (match_operand:SI 2 "nonmemory_operand" ""))) 2296 (clobber (reg:HI 26)) 2297 (clobber (reg:DI 18))])] 2298 "AVR_HAVE_MUL" 2299 { 2300 if (u16_operand (operands[2], SImode)) 2301 { 2302 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode)); 2303 emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1])); 2304 DONE; 2305 } 2306 2307 if (o16_operand (operands[2], SImode)) 2308 { 2309 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode)); 2310 emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1])); 2311 DONE; 2312 } 2313 2314 if (avr_emit3_fix_outputs (gen_mulsi3, operands, 1 << 0, 2315 regmask (DImode, 18) | regmask (HImode, 26))) 2316 DONE; 2317 }) 2318 2319(define_insn_and_split "*mulsi3" 2320 [(set (match_operand:SI 0 "pseudo_register_operand" "=r") 2321 (mult:SI (match_operand:SI 1 "pseudo_register_operand" "r") 2322 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn"))) 2323 (clobber (reg:HI 26)) 2324 (clobber (reg:DI 18))] 2325 "AVR_HAVE_MUL && !reload_completed" 2326 { gcc_unreachable(); } 2327 "&& 1" 2328 [(set (reg:SI 18) 2329 (match_dup 1)) 2330 (set (reg:SI 22) 2331 (match_dup 2)) 2332 (parallel [(set (reg:SI 22) 2333 (mult:SI (reg:SI 22) 2334 (reg:SI 18))) 2335 (clobber (reg:HI 26))]) 2336 (set (match_dup 0) 2337 (reg:SI 22))] 2338 { 2339 if (u16_operand (operands[2], SImode)) 2340 { 2341 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode)); 2342 emit_insn (gen_muluhisi3 (operands[0], operands[2], operands[1])); 2343 DONE; 2344 } 2345 2346 if (o16_operand (operands[2], SImode)) 2347 { 2348 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode)); 2349 emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1])); 2350 DONE; 2351 } 2352 }) 2353 2354;; "muluqisi3" 2355;; "muluhisi3" 2356(define_expand "mulu<mode>si3" 2357 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 2358 (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "")) 2359 (match_operand:SI 2 "pseudo_register_or_const_int_operand" ""))) 2360 (clobber (reg:HI 26)) 2361 (clobber (reg:DI 18))])] 2362 "AVR_HAVE_MUL" 2363 { 2364 avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); 2365 if (avr_emit3_fix_outputs (gen_mulu<mode>si3, operands, 1 << 0, 2366 regmask (DImode, 18) | regmask (HImode, 26))) 2367 DONE; 2368 }) 2369 2370;; "*muluqisi3" 2371;; "*muluhisi3" 2372(define_insn_and_split "*mulu<mode>si3" 2373 [(set (match_operand:SI 0 "pseudo_register_operand" "=r") 2374 (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r")) 2375 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn"))) 2376 (clobber (reg:HI 26)) 2377 (clobber (reg:DI 18))] 2378 "AVR_HAVE_MUL && !reload_completed" 2379 { gcc_unreachable(); } 2380 "&& 1" 2381 [(set (reg:HI 26) 2382 (match_dup 1)) 2383 (set (reg:SI 18) 2384 (match_dup 2)) 2385 (set (reg:SI 22) 2386 (mult:SI (zero_extend:SI (reg:HI 26)) 2387 (reg:SI 18))) 2388 (set (match_dup 0) 2389 (reg:SI 22))] 2390 { 2391 /* Do the QI -> HI extension explicitely before the multiplication. */ 2392 /* Do the HI -> SI extension implicitely and after the multiplication. */ 2393 2394 if (QImode == <MODE>mode) 2395 operands[1] = gen_rtx_ZERO_EXTEND (HImode, operands[1]); 2396 2397 if (u16_operand (operands[2], SImode)) 2398 { 2399 operands[1] = force_reg (HImode, operands[1]); 2400 operands[2] = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode)); 2401 emit_insn (gen_umulhisi3 (operands[0], operands[1], operands[2])); 2402 DONE; 2403 } 2404 }) 2405 2406;; "mulsqisi3" 2407;; "mulshisi3" 2408(define_expand "muls<mode>si3" 2409 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 2410 (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "")) 2411 (match_operand:SI 2 "pseudo_register_or_const_int_operand" ""))) 2412 (clobber (reg:HI 26)) 2413 (clobber (reg:DI 18))])] 2414 "AVR_HAVE_MUL" 2415 { 2416 avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); 2417 if (avr_emit3_fix_outputs (gen_muls<mode>si3, operands, 1 << 0, 2418 regmask (DImode, 18) | regmask (HImode, 26))) 2419 DONE; 2420 }) 2421 2422;; "*mulsqisi3" 2423;; "*mulshisi3" 2424(define_insn_and_split "*muls<mode>si3" 2425 [(set (match_operand:SI 0 "pseudo_register_operand" "=r") 2426 (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r")) 2427 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn"))) 2428 (clobber (reg:HI 26)) 2429 (clobber (reg:DI 18))] 2430 "AVR_HAVE_MUL && !reload_completed" 2431 { gcc_unreachable(); } 2432 "&& 1" 2433 [(set (reg:HI 26) 2434 (match_dup 1)) 2435 (set (reg:SI 18) 2436 (match_dup 2)) 2437 (set (reg:SI 22) 2438 (mult:SI (sign_extend:SI (reg:HI 26)) 2439 (reg:SI 18))) 2440 (set (match_dup 0) 2441 (reg:SI 22))] 2442 { 2443 /* Do the QI -> HI extension explicitely before the multiplication. */ 2444 /* Do the HI -> SI extension implicitely and after the multiplication. */ 2445 2446 if (QImode == <MODE>mode) 2447 operands[1] = gen_rtx_SIGN_EXTEND (HImode, operands[1]); 2448 2449 if (u16_operand (operands[2], SImode) 2450 || s16_operand (operands[2], SImode)) 2451 { 2452 rtx xop2 = force_reg (HImode, gen_int_mode (INTVAL (operands[2]), HImode)); 2453 2454 operands[1] = force_reg (HImode, operands[1]); 2455 2456 if (u16_operand (operands[2], SImode)) 2457 emit_insn (gen_usmulhisi3 (operands[0], xop2, operands[1])); 2458 else 2459 emit_insn (gen_mulhisi3 (operands[0], operands[1], xop2)); 2460 2461 DONE; 2462 } 2463 }) 2464 2465;; One-extend operand 1 2466 2467(define_expand "mulohisi3" 2468 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 2469 (mult:SI (not:SI (zero_extend:SI 2470 (not:HI (match_operand:HI 1 "pseudo_register_operand" "")))) 2471 (match_operand:SI 2 "pseudo_register_or_const_int_operand" ""))) 2472 (clobber (reg:HI 26)) 2473 (clobber (reg:DI 18))])] 2474 "AVR_HAVE_MUL" 2475 { 2476 avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); 2477 if (avr_emit3_fix_outputs (gen_mulohisi3, operands, 1 << 0, 2478 regmask (DImode, 18) | regmask (HImode, 26))) 2479 DONE; 2480 }) 2481 2482(define_insn_and_split "*mulohisi3" 2483 [(set (match_operand:SI 0 "pseudo_register_operand" "=r") 2484 (mult:SI (not:SI (zero_extend:SI 2485 (not:HI (match_operand:HI 1 "pseudo_register_operand" "r")))) 2486 (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn"))) 2487 (clobber (reg:HI 26)) 2488 (clobber (reg:DI 18))] 2489 "AVR_HAVE_MUL && !reload_completed" 2490 { gcc_unreachable(); } 2491 "&& 1" 2492 [(set (reg:HI 26) 2493 (match_dup 1)) 2494 (set (reg:SI 18) 2495 (match_dup 2)) 2496 (set (reg:SI 22) 2497 (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26)))) 2498 (reg:SI 18))) 2499 (set (match_dup 0) 2500 (reg:SI 22))]) 2501 2502;; "mulhisi3" 2503;; "umulhisi3" 2504(define_expand "<extend_u>mulhisi3" 2505 [(parallel [(set (match_operand:SI 0 "register_operand" "") 2506 (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" "")) 2507 (any_extend:SI (match_operand:HI 2 "register_operand" "")))) 2508 (clobber (reg:HI 26)) 2509 (clobber (reg:DI 18))])] 2510 "AVR_HAVE_MUL" 2511 { 2512 if (avr_emit3_fix_outputs (gen_<extend_u>mulhisi3, operands, 1 << 0, 2513 regmask (DImode, 18) | regmask (HImode, 26))) 2514 DONE; 2515 }) 2516 2517(define_expand "usmulhisi3" 2518 [(parallel [(set (match_operand:SI 0 "register_operand" "") 2519 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "")) 2520 (sign_extend:SI (match_operand:HI 2 "register_operand" "")))) 2521 (clobber (reg:HI 26)) 2522 (clobber (reg:DI 18))])] 2523 "AVR_HAVE_MUL" 2524 { 2525 if (avr_emit3_fix_outputs (gen_usmulhisi3, operands, 1 << 0, 2526 regmask (DImode, 18) | regmask (HImode, 26))) 2527 DONE; 2528 }) 2529 2530;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3" 2531;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3" 2532;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3" 2533;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3" 2534(define_insn_and_split 2535 "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3" 2536 [(set (match_operand:SI 0 "pseudo_register_operand" "=r") 2537 (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r")) 2538 (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r")))) 2539 (clobber (reg:HI 26)) 2540 (clobber (reg:DI 18))] 2541 "AVR_HAVE_MUL && !reload_completed" 2542 { gcc_unreachable(); } 2543 "&& 1" 2544 [(set (reg:HI 18) 2545 (match_dup 1)) 2546 (set (reg:HI 26) 2547 (match_dup 2)) 2548 (set (reg:SI 22) 2549 (mult:SI (match_dup 3) 2550 (match_dup 4))) 2551 (set (match_dup 0) 2552 (reg:SI 22))] 2553 { 2554 rtx xop1 = operands[1]; 2555 rtx xop2 = operands[2]; 2556 2557 /* Do the QI -> HI extension explicitely before the multiplication. */ 2558 /* Do the HI -> SI extension implicitely and after the multiplication. */ 2559 2560 if (QImode == <QIHI:MODE>mode) 2561 xop1 = gen_rtx_fmt_e (<any_extend:CODE>, HImode, xop1); 2562 2563 if (QImode == <QIHI2:MODE>mode) 2564 xop2 = gen_rtx_fmt_e (<any_extend2:CODE>, HImode, xop2); 2565 2566 if (<any_extend:CODE> == <any_extend2:CODE> 2567 || <any_extend:CODE> == ZERO_EXTEND) 2568 { 2569 operands[1] = xop1; 2570 operands[2] = xop2; 2571 operands[3] = gen_rtx_fmt_e (<any_extend:CODE>, SImode, gen_rtx_REG (HImode, 18)); 2572 operands[4] = gen_rtx_fmt_e (<any_extend2:CODE>, SImode, gen_rtx_REG (HImode, 26)); 2573 } 2574 else 2575 { 2576 /* <any_extend:CODE> = SIGN_EXTEND */ 2577 /* <any_extend2:CODE> = ZERO_EXTEND */ 2578 2579 operands[1] = xop2; 2580 operands[2] = xop1; 2581 operands[3] = gen_rtx_ZERO_EXTEND (SImode, gen_rtx_REG (HImode, 18)); 2582 operands[4] = gen_rtx_SIGN_EXTEND (SImode, gen_rtx_REG (HImode, 26)); 2583 } 2584 }) 2585 2586;; "smulhi3_highpart" 2587;; "umulhi3_highpart" 2588(define_expand "<extend_su>mulhi3_highpart" 2589 [(set (reg:HI 18) 2590 (match_operand:HI 1 "nonmemory_operand" "")) 2591 (set (reg:HI 26) 2592 (match_operand:HI 2 "nonmemory_operand" "")) 2593 (parallel [(set (reg:HI 24) 2594 (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18)) 2595 (any_extend:SI (reg:HI 26))) 2596 (const_int 16)))) 2597 (clobber (reg:HI 22))]) 2598 (set (match_operand:HI 0 "register_operand" "") 2599 (reg:HI 24))] 2600 "AVR_HAVE_MUL" 2601 { 2602 avr_fix_inputs (operands, 1 << 2, regmask (HImode, 18)); 2603 }) 2604 2605 2606(define_insn "*mulsi3_call" 2607 [(set (reg:SI 22) 2608 (mult:SI (reg:SI 22) 2609 (reg:SI 18))) 2610 (clobber (reg:HI 26))] 2611 "AVR_HAVE_MUL" 2612 "%~call __mulsi3" 2613 [(set_attr "type" "xcall") 2614 (set_attr "cc" "clobber")]) 2615 2616;; "*mulhisi3_call" 2617;; "*umulhisi3_call" 2618(define_insn "*<extend_u>mulhisi3_call" 2619 [(set (reg:SI 22) 2620 (mult:SI (any_extend:SI (reg:HI 18)) 2621 (any_extend:SI (reg:HI 26))))] 2622 "AVR_HAVE_MUL" 2623 "%~call __<extend_u>mulhisi3" 2624 [(set_attr "type" "xcall") 2625 (set_attr "cc" "clobber")]) 2626 2627;; "*umulhi3_highpart_call" 2628;; "*smulhi3_highpart_call" 2629(define_insn "*<extend_su>mulhi3_highpart_call" 2630 [(set (reg:HI 24) 2631 (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18)) 2632 (any_extend:SI (reg:HI 26))) 2633 (const_int 16)))) 2634 (clobber (reg:HI 22))] 2635 "AVR_HAVE_MUL" 2636 "%~call __<extend_u>mulhisi3" 2637 [(set_attr "type" "xcall") 2638 (set_attr "cc" "clobber")]) 2639 2640(define_insn "*usmulhisi3_call" 2641 [(set (reg:SI 22) 2642 (mult:SI (zero_extend:SI (reg:HI 18)) 2643 (sign_extend:SI (reg:HI 26))))] 2644 "AVR_HAVE_MUL" 2645 "%~call __usmulhisi3" 2646 [(set_attr "type" "xcall") 2647 (set_attr "cc" "clobber")]) 2648 2649(define_insn "*mul<extend_su>hisi3_call" 2650 [(set (reg:SI 22) 2651 (mult:SI (any_extend:SI (reg:HI 26)) 2652 (reg:SI 18)))] 2653 "AVR_HAVE_MUL" 2654 "%~call __mul<extend_su>hisi3" 2655 [(set_attr "type" "xcall") 2656 (set_attr "cc" "clobber")]) 2657 2658(define_insn "*mulohisi3_call" 2659 [(set (reg:SI 22) 2660 (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26)))) 2661 (reg:SI 18)))] 2662 "AVR_HAVE_MUL" 2663 "%~call __mulohisi3" 2664 [(set_attr "type" "xcall") 2665 (set_attr "cc" "clobber")]) 2666 2667; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % 2668; divmod 2669 2670;; Generate lib1funcs.S calls ourselves, because: 2671;; - we know exactly which registers are clobbered (for QI and HI 2672;; modes, some of the call-used registers are preserved) 2673;; - we get both the quotient and the remainder at no extra cost 2674;; - we split the patterns only after the first CSE passes because 2675;; CSE has problems to operate on hard regs. 2676;; 2677(define_insn_and_split "divmodqi4" 2678 [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 2679 (div:QI (match_operand:QI 1 "pseudo_register_operand" "") 2680 (match_operand:QI 2 "pseudo_register_operand" ""))) 2681 (set (match_operand:QI 3 "pseudo_register_operand" "") 2682 (mod:QI (match_dup 1) (match_dup 2))) 2683 (clobber (reg:QI 22)) 2684 (clobber (reg:QI 23)) 2685 (clobber (reg:QI 24)) 2686 (clobber (reg:QI 25))])] 2687 "" 2688 "this divmodqi4 pattern should have been splitted;" 2689 "" 2690 [(set (reg:QI 24) (match_dup 1)) 2691 (set (reg:QI 22) (match_dup 2)) 2692 (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22))) 2693 (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22))) 2694 (clobber (reg:QI 22)) 2695 (clobber (reg:QI 23))]) 2696 (set (match_dup 0) (reg:QI 24)) 2697 (set (match_dup 3) (reg:QI 25))]) 2698 2699(define_insn "*divmodqi4_call" 2700 [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22))) 2701 (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22))) 2702 (clobber (reg:QI 22)) 2703 (clobber (reg:QI 23))] 2704 "" 2705 "%~call __divmodqi4" 2706 [(set_attr "type" "xcall") 2707 (set_attr "cc" "clobber")]) 2708 2709(define_insn_and_split "udivmodqi4" 2710 [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") 2711 (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "") 2712 (match_operand:QI 2 "pseudo_register_operand" ""))) 2713 (set (match_operand:QI 3 "pseudo_register_operand" "") 2714 (umod:QI (match_dup 1) (match_dup 2))) 2715 (clobber (reg:QI 22)) 2716 (clobber (reg:QI 23)) 2717 (clobber (reg:QI 24)) 2718 (clobber (reg:QI 25))])] 2719 "" 2720 "this udivmodqi4 pattern should have been splitted;" 2721 "" 2722 [(set (reg:QI 24) (match_dup 1)) 2723 (set (reg:QI 22) (match_dup 2)) 2724 (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22))) 2725 (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22))) 2726 (clobber (reg:QI 23))]) 2727 (set (match_dup 0) (reg:QI 24)) 2728 (set (match_dup 3) (reg:QI 25))]) 2729 2730(define_insn "*udivmodqi4_call" 2731 [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22))) 2732 (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22))) 2733 (clobber (reg:QI 23))] 2734 "" 2735 "%~call __udivmodqi4" 2736 [(set_attr "type" "xcall") 2737 (set_attr "cc" "clobber")]) 2738 2739(define_insn_and_split "divmodhi4" 2740 [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 2741 (div:HI (match_operand:HI 1 "pseudo_register_operand" "") 2742 (match_operand:HI 2 "pseudo_register_operand" ""))) 2743 (set (match_operand:HI 3 "pseudo_register_operand" "") 2744 (mod:HI (match_dup 1) (match_dup 2))) 2745 (clobber (reg:QI 21)) 2746 (clobber (reg:HI 22)) 2747 (clobber (reg:HI 24)) 2748 (clobber (reg:HI 26))])] 2749 "" 2750 "this should have been splitted;" 2751 "" 2752 [(set (reg:HI 24) (match_dup 1)) 2753 (set (reg:HI 22) (match_dup 2)) 2754 (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) 2755 (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) 2756 (clobber (reg:HI 26)) 2757 (clobber (reg:QI 21))]) 2758 (set (match_dup 0) (reg:HI 22)) 2759 (set (match_dup 3) (reg:HI 24))]) 2760 2761(define_insn "*divmodhi4_call" 2762 [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) 2763 (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) 2764 (clobber (reg:HI 26)) 2765 (clobber (reg:QI 21))] 2766 "" 2767 "%~call __divmodhi4" 2768 [(set_attr "type" "xcall") 2769 (set_attr "cc" "clobber")]) 2770 2771(define_insn_and_split "udivmodhi4" 2772 [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") 2773 (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "") 2774 (match_operand:HI 2 "pseudo_register_operand" ""))) 2775 (set (match_operand:HI 3 "pseudo_register_operand" "") 2776 (umod:HI (match_dup 1) (match_dup 2))) 2777 (clobber (reg:QI 21)) 2778 (clobber (reg:HI 22)) 2779 (clobber (reg:HI 24)) 2780 (clobber (reg:HI 26))])] 2781 "" 2782 "this udivmodhi4 pattern should have been splitted.;" 2783 "" 2784 [(set (reg:HI 24) (match_dup 1)) 2785 (set (reg:HI 22) (match_dup 2)) 2786 (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) 2787 (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) 2788 (clobber (reg:HI 26)) 2789 (clobber (reg:QI 21))]) 2790 (set (match_dup 0) (reg:HI 22)) 2791 (set (match_dup 3) (reg:HI 24))]) 2792 2793(define_insn "*udivmodhi4_call" 2794 [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) 2795 (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) 2796 (clobber (reg:HI 26)) 2797 (clobber (reg:QI 21))] 2798 "" 2799 "%~call __udivmodhi4" 2800 [(set_attr "type" "xcall") 2801 (set_attr "cc" "clobber")]) 2802 2803;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2804;; 24-bit multiply 2805 2806;; To support widening multiplication with constant we postpone 2807;; expanding to the implicit library call until post combine and 2808;; prior to register allocation. Clobber all hard registers that 2809;; might be used by the (widening) multiply until it is split and 2810;; it's final register footprint is worked out. 2811 2812(define_expand "mulpsi3" 2813 [(parallel [(set (match_operand:PSI 0 "register_operand" "") 2814 (mult:PSI (match_operand:PSI 1 "register_operand" "") 2815 (match_operand:PSI 2 "nonmemory_operand" ""))) 2816 (clobber (reg:HI 26)) 2817 (clobber (reg:DI 18))])] 2818 "AVR_HAVE_MUL" 2819 { 2820 if (s8_operand (operands[2], PSImode)) 2821 { 2822 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); 2823 emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); 2824 DONE; 2825 } 2826 2827 if (avr_emit3_fix_outputs (gen_mulpsi3, operands, 1u << 0, 2828 regmask (DImode, 18) | regmask (HImode, 26))) 2829 DONE; 2830 }) 2831 2832(define_insn "*umulqihipsi3" 2833 [(set (match_operand:PSI 0 "register_operand" "=&r") 2834 (mult:PSI (zero_extend:PSI (match_operand:QI 1 "register_operand" "r")) 2835 (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))] 2836 "AVR_HAVE_MUL" 2837 "mul %1,%A2 2838 movw %A0,r0 2839 mul %1,%B2 2840 clr %C0 2841 add %B0,r0 2842 adc %C0,r1 2843 clr __zero_reg__" 2844 [(set_attr "length" "7") 2845 (set_attr "cc" "clobber")]) 2846 2847(define_insn "*umulhiqipsi3" 2848 [(set (match_operand:PSI 0 "register_operand" "=&r") 2849 (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r")) 2850 (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))] 2851 "AVR_HAVE_MUL" 2852 "mul %1,%A2 2853 movw %A0,r0 2854 mul %1,%B2 2855 add %B0,r0 2856 mov %C0,r1 2857 clr __zero_reg__ 2858 adc %C0,__zero_reg__" 2859 [(set_attr "length" "7") 2860 (set_attr "cc" "clobber")]) 2861 2862(define_expand "mulsqipsi3" 2863 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "") 2864 (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "")) 2865 (match_operand:PSI 2 "pseudo_register_or_const_int_operand"""))) 2866 (clobber (reg:HI 26)) 2867 (clobber (reg:DI 18))])] 2868 "AVR_HAVE_MUL" 2869 { 2870 avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); 2871 if (avr_emit3_fix_outputs (gen_mulsqipsi3, operands, 1 << 0, 2872 regmask (DImode, 18) | regmask (HImode, 26))) 2873 DONE; 2874 }) 2875 2876(define_insn_and_split "*mulsqipsi3" 2877 [(set (match_operand:PSI 0 "pseudo_register_operand" "=r") 2878 (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "r")) 2879 (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn"))) 2880 (clobber (reg:HI 26)) 2881 (clobber (reg:DI 18))] 2882 "AVR_HAVE_MUL && !reload_completed" 2883 { gcc_unreachable(); } 2884 "&& 1" 2885 [(set (reg:QI 25) 2886 (match_dup 1)) 2887 (set (reg:PSI 22) 2888 (match_dup 2)) 2889 (set (reg:PSI 18) 2890 (mult:PSI (sign_extend:PSI (reg:QI 25)) 2891 (reg:PSI 22))) 2892 (set (match_dup 0) 2893 (reg:PSI 18))]) 2894 2895(define_insn_and_split "*mulpsi3" 2896 [(set (match_operand:PSI 0 "pseudo_register_operand" "=r") 2897 (mult:PSI (match_operand:PSI 1 "pseudo_register_operand" "r") 2898 (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn"))) 2899 (clobber (reg:HI 26)) 2900 (clobber (reg:DI 18))] 2901 "AVR_HAVE_MUL && !reload_completed" 2902 { gcc_unreachable(); } 2903 "&& 1" 2904 [(set (reg:PSI 18) 2905 (match_dup 1)) 2906 (set (reg:PSI 22) 2907 (match_dup 2)) 2908 (parallel [(set (reg:PSI 22) 2909 (mult:PSI (reg:PSI 22) 2910 (reg:PSI 18))) 2911 (clobber (reg:QI 21)) 2912 (clobber (reg:QI 25)) 2913 (clobber (reg:HI 26))]) 2914 (set (match_dup 0) 2915 (reg:PSI 22))] 2916 { 2917 if (s8_operand (operands[2], PSImode)) 2918 { 2919 rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); 2920 emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); 2921 DONE; 2922 } 2923 }) 2924 2925(define_insn "*mulsqipsi3.libgcc" 2926 [(set (reg:PSI 18) 2927 (mult:PSI (sign_extend:PSI (reg:QI 25)) 2928 (reg:PSI 22)))] 2929 "AVR_HAVE_MUL" 2930 "%~call __mulsqipsi3" 2931 [(set_attr "type" "xcall") 2932 (set_attr "cc" "clobber")]) 2933 2934(define_insn "*mulpsi3.libgcc" 2935 [(set (reg:PSI 22) 2936 (mult:PSI (reg:PSI 22) 2937 (reg:PSI 18))) 2938 (clobber (reg:QI 21)) 2939 (clobber (reg:QI 25)) 2940 (clobber (reg:HI 26))] 2941 "AVR_HAVE_MUL" 2942 "%~call __mulpsi3" 2943 [(set_attr "type" "xcall") 2944 (set_attr "cc" "clobber")]) 2945 2946 2947;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2948;; 24-bit signed/unsigned division and modulo. 2949;; Notice that the libgcc implementation return the quotient in R22 2950;; and the remainder in R18 whereas the 32-bit [u]divmodsi4 2951;; implementation works the other way round. 2952 2953(define_insn_and_split "divmodpsi4" 2954 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "") 2955 (div:PSI (match_operand:PSI 1 "pseudo_register_operand" "") 2956 (match_operand:PSI 2 "pseudo_register_operand" ""))) 2957 (set (match_operand:PSI 3 "pseudo_register_operand" "") 2958 (mod:PSI (match_dup 1) 2959 (match_dup 2))) 2960 (clobber (reg:DI 18)) 2961 (clobber (reg:QI 26))])] 2962 "" 2963 { gcc_unreachable(); } 2964 "" 2965 [(set (reg:PSI 22) (match_dup 1)) 2966 (set (reg:PSI 18) (match_dup 2)) 2967 (parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18))) 2968 (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18))) 2969 (clobber (reg:QI 21)) 2970 (clobber (reg:QI 25)) 2971 (clobber (reg:QI 26))]) 2972 (set (match_dup 0) (reg:PSI 22)) 2973 (set (match_dup 3) (reg:PSI 18))]) 2974 2975(define_insn "*divmodpsi4_call" 2976 [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18))) 2977 (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18))) 2978 (clobber (reg:QI 21)) 2979 (clobber (reg:QI 25)) 2980 (clobber (reg:QI 26))] 2981 "" 2982 "%~call __divmodpsi4" 2983 [(set_attr "type" "xcall") 2984 (set_attr "cc" "clobber")]) 2985 2986(define_insn_and_split "udivmodpsi4" 2987 [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "") 2988 (udiv:PSI (match_operand:PSI 1 "pseudo_register_operand" "") 2989 (match_operand:PSI 2 "pseudo_register_operand" ""))) 2990 (set (match_operand:PSI 3 "pseudo_register_operand" "") 2991 (umod:PSI (match_dup 1) 2992 (match_dup 2))) 2993 (clobber (reg:DI 18)) 2994 (clobber (reg:QI 26))])] 2995 "" 2996 { gcc_unreachable(); } 2997 "" 2998 [(set (reg:PSI 22) (match_dup 1)) 2999 (set (reg:PSI 18) (match_dup 2)) 3000 (parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18))) 3001 (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18))) 3002 (clobber (reg:QI 21)) 3003 (clobber (reg:QI 25)) 3004 (clobber (reg:QI 26))]) 3005 (set (match_dup 0) (reg:PSI 22)) 3006 (set (match_dup 3) (reg:PSI 18))]) 3007 3008(define_insn "*udivmodpsi4_call" 3009 [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18))) 3010 (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18))) 3011 (clobber (reg:QI 21)) 3012 (clobber (reg:QI 25)) 3013 (clobber (reg:QI 26))] 3014 "" 3015 "%~call __udivmodpsi4" 3016 [(set_attr "type" "xcall") 3017 (set_attr "cc" "clobber")]) 3018 3019;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3020 3021(define_insn_and_split "divmodsi4" 3022 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 3023 (div:SI (match_operand:SI 1 "pseudo_register_operand" "") 3024 (match_operand:SI 2 "pseudo_register_operand" ""))) 3025 (set (match_operand:SI 3 "pseudo_register_operand" "") 3026 (mod:SI (match_dup 1) (match_dup 2))) 3027 (clobber (reg:SI 18)) 3028 (clobber (reg:SI 22)) 3029 (clobber (reg:HI 26)) 3030 (clobber (reg:HI 30))])] 3031 "" 3032 "this divmodsi4 pattern should have been splitted;" 3033 "" 3034 [(set (reg:SI 22) (match_dup 1)) 3035 (set (reg:SI 18) (match_dup 2)) 3036 (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18))) 3037 (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18))) 3038 (clobber (reg:HI 26)) 3039 (clobber (reg:HI 30))]) 3040 (set (match_dup 0) (reg:SI 18)) 3041 (set (match_dup 3) (reg:SI 22))]) 3042 3043(define_insn "*divmodsi4_call" 3044 [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18))) 3045 (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18))) 3046 (clobber (reg:HI 26)) 3047 (clobber (reg:HI 30))] 3048 "" 3049 "%~call __divmodsi4" 3050 [(set_attr "type" "xcall") 3051 (set_attr "cc" "clobber")]) 3052 3053(define_insn_and_split "udivmodsi4" 3054 [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") 3055 (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "") 3056 (match_operand:SI 2 "pseudo_register_operand" ""))) 3057 (set (match_operand:SI 3 "pseudo_register_operand" "") 3058 (umod:SI (match_dup 1) (match_dup 2))) 3059 (clobber (reg:SI 18)) 3060 (clobber (reg:SI 22)) 3061 (clobber (reg:HI 26)) 3062 (clobber (reg:HI 30))])] 3063 "" 3064 "this udivmodsi4 pattern should have been splitted;" 3065 "" 3066 [(set (reg:SI 22) (match_dup 1)) 3067 (set (reg:SI 18) (match_dup 2)) 3068 (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18))) 3069 (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18))) 3070 (clobber (reg:HI 26)) 3071 (clobber (reg:HI 30))]) 3072 (set (match_dup 0) (reg:SI 18)) 3073 (set (match_dup 3) (reg:SI 22))]) 3074 3075(define_insn "*udivmodsi4_call" 3076 [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18))) 3077 (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18))) 3078 (clobber (reg:HI 26)) 3079 (clobber (reg:HI 30))] 3080 "" 3081 "%~call __udivmodsi4" 3082 [(set_attr "type" "xcall") 3083 (set_attr "cc" "clobber")]) 3084 3085;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 3086; and 3087 3088(define_insn "andqi3" 3089 [(set (match_operand:QI 0 "register_operand" "=??r,d") 3090 (and:QI (match_operand:QI 1 "register_operand" "%0,0") 3091 (match_operand:QI 2 "nonmemory_operand" "r,i")))] 3092 "" 3093 "@ 3094 and %0,%2 3095 andi %0,lo8(%2)" 3096 [(set_attr "length" "1,1") 3097 (set_attr "cc" "set_zn,set_zn")]) 3098 3099(define_insn "andhi3" 3100 [(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r") 3101 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0") 3102 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n"))) 3103 (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] 3104 "" 3105 { 3106 if (which_alternative == 0) 3107 return "and %A0,%A2\;and %B0,%B2"; 3108 else if (which_alternative == 1) 3109 return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)"; 3110 3111 return avr_out_bitop (insn, operands, NULL); 3112 } 3113 [(set_attr "length" "2,2,2,4,4") 3114 (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop") 3115 (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")]) 3116 3117(define_insn "andpsi3" 3118 [(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r") 3119 (and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0") 3120 (match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n"))) 3121 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] 3122 "" 3123 { 3124 if (which_alternative == 0) 3125 return "and %A0,%A2" CR_TAB 3126 "and %B0,%B2" CR_TAB 3127 "and %C0,%C2"; 3128 3129 return avr_out_bitop (insn, operands, NULL); 3130 } 3131 [(set_attr "length" "3,3,6,6") 3132 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop") 3133 (set_attr "cc" "set_n,clobber,clobber,clobber")]) 3134 3135(define_insn "andsi3" 3136 [(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r") 3137 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0") 3138 (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n"))) 3139 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] 3140 "" 3141 { 3142 if (which_alternative == 0) 3143 return "and %0,%2" CR_TAB 3144 "and %B0,%B2" CR_TAB 3145 "and %C0,%C2" CR_TAB 3146 "and %D0,%D2"; 3147 3148 return avr_out_bitop (insn, operands, NULL); 3149 } 3150 [(set_attr "length" "4,4,8,8") 3151 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop") 3152 (set_attr "cc" "set_n,clobber,clobber,clobber")]) 3153 3154(define_peephole2 ; andi 3155 [(set (match_operand:QI 0 "d_register_operand" "") 3156 (and:QI (match_dup 0) 3157 (match_operand:QI 1 "const_int_operand" ""))) 3158 (set (match_dup 0) 3159 (and:QI (match_dup 0) 3160 (match_operand:QI 2 "const_int_operand" "")))] 3161 "" 3162 [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))] 3163 { 3164 operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2])); 3165 }) 3166 3167;;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 3168;; ior 3169 3170(define_insn "iorqi3" 3171 [(set (match_operand:QI 0 "register_operand" "=??r,d") 3172 (ior:QI (match_operand:QI 1 "register_operand" "%0,0") 3173 (match_operand:QI 2 "nonmemory_operand" "r,i")))] 3174 "" 3175 "@ 3176 or %0,%2 3177 ori %0,lo8(%2)" 3178 [(set_attr "length" "1,1") 3179 (set_attr "cc" "set_zn,set_zn")]) 3180 3181(define_insn "iorhi3" 3182 [(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r") 3183 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0") 3184 (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n"))) 3185 (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] 3186 "" 3187 { 3188 if (which_alternative == 0) 3189 return "or %A0,%A2\;or %B0,%B2"; 3190 else if (which_alternative == 1) 3191 return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)"; 3192 3193 return avr_out_bitop (insn, operands, NULL); 3194 } 3195 [(set_attr "length" "2,2,2,4,4") 3196 (set_attr "adjust_len" "*,*,out_bitop,out_bitop,out_bitop") 3197 (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")]) 3198 3199(define_insn "iorpsi3" 3200 [(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r") 3201 (ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0") 3202 (match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n"))) 3203 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] 3204 "" 3205 { 3206 if (which_alternative == 0) 3207 return "or %A0,%A2" CR_TAB 3208 "or %B0,%B2" CR_TAB 3209 "or %C0,%C2"; 3210 3211 return avr_out_bitop (insn, operands, NULL); 3212 } 3213 [(set_attr "length" "3,3,6,6") 3214 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop") 3215 (set_attr "cc" "set_n,clobber,clobber,clobber")]) 3216 3217(define_insn "iorsi3" 3218 [(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r") 3219 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0") 3220 (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n"))) 3221 (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] 3222 "" 3223 { 3224 if (which_alternative == 0) 3225 return "or %0,%2" CR_TAB 3226 "or %B0,%B2" CR_TAB 3227 "or %C0,%C2" CR_TAB 3228 "or %D0,%D2"; 3229 3230 return avr_out_bitop (insn, operands, NULL); 3231 } 3232 [(set_attr "length" "4,4,8,8") 3233 (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop") 3234 (set_attr "cc" "set_n,clobber,clobber,clobber")]) 3235 3236;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 3237;; xor 3238 3239(define_insn "xorqi3" 3240 [(set (match_operand:QI 0 "register_operand" "=r") 3241 (xor:QI (match_operand:QI 1 "register_operand" "%0") 3242 (match_operand:QI 2 "register_operand" "r")))] 3243 "" 3244 "eor %0,%2" 3245 [(set_attr "length" "1") 3246 (set_attr "cc" "set_zn")]) 3247 3248(define_insn "xorhi3" 3249 [(set (match_operand:HI 0 "register_operand" "=??r,r ,r") 3250 (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0") 3251 (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n"))) 3252 (clobber (match_scratch:QI 3 "=X,X ,&d"))] 3253 "" 3254 { 3255 if (which_alternative == 0) 3256 return "eor %A0,%A2\;eor %B0,%B2"; 3257 3258 return avr_out_bitop (insn, operands, NULL); 3259 } 3260 [(set_attr "length" "2,2,4") 3261 (set_attr "adjust_len" "*,out_bitop,out_bitop") 3262 (set_attr "cc" "set_n,clobber,clobber")]) 3263 3264(define_insn "xorpsi3" 3265 [(set (match_operand:PSI 0 "register_operand" "=??r,r ,r") 3266 (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0") 3267 (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n"))) 3268 (clobber (match_scratch:QI 3 "=X,X ,&d"))] 3269 "" 3270 { 3271 if (which_alternative == 0) 3272 return "eor %A0,%A2" CR_TAB 3273 "eor %B0,%B2" CR_TAB 3274 "eor %C0,%C2"; 3275 3276 return avr_out_bitop (insn, operands, NULL); 3277 } 3278 [(set_attr "length" "3,6,6") 3279 (set_attr "adjust_len" "*,out_bitop,out_bitop") 3280 (set_attr "cc" "set_n,clobber,clobber")]) 3281 3282(define_insn "xorsi3" 3283 [(set (match_operand:SI 0 "register_operand" "=??r,r ,r") 3284 (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0") 3285 (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n"))) 3286 (clobber (match_scratch:QI 3 "=X,X ,&d"))] 3287 "" 3288 { 3289 if (which_alternative == 0) 3290 return "eor %0,%2" CR_TAB 3291 "eor %B0,%B2" CR_TAB 3292 "eor %C0,%C2" CR_TAB 3293 "eor %D0,%D2"; 3294 3295 return avr_out_bitop (insn, operands, NULL); 3296 } 3297 [(set_attr "length" "4,8,8") 3298 (set_attr "adjust_len" "*,out_bitop,out_bitop") 3299 (set_attr "cc" "set_n,clobber,clobber")]) 3300 3301;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap 3302;; swap 3303 3304(define_expand "rotlqi3" 3305 [(set (match_operand:QI 0 "register_operand" "") 3306 (rotate:QI (match_operand:QI 1 "register_operand" "") 3307 (match_operand:QI 2 "const_0_to_7_operand" "")))] 3308 "" 3309 { 3310 if (!CONST_INT_P (operands[2])) 3311 FAIL; 3312 3313 operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode); 3314 }) 3315 3316;; Expander used by __builtin_avr_swap 3317(define_expand "rotlqi3_4" 3318 [(set (match_operand:QI 0 "register_operand" "") 3319 (rotate:QI (match_operand:QI 1 "register_operand" "") 3320 (const_int 4)))]) 3321 3322(define_insn "*rotlqi3" 3323 [(set (match_operand:QI 0 "register_operand" "=r,r,r ,r ,r ,r ,r ,r") 3324 (rotate:QI (match_operand:QI 1 "register_operand" "0,0,0 ,0 ,0 ,0 ,0 ,0") 3325 (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))] 3326 "" 3327 "@ 3328 lsl %0\;adc %0,__zero_reg__ 3329 lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__ 3330 swap %0\;bst %0,0\;ror %0\;bld %0,7 3331 swap %0 3332 swap %0\;lsl %0\;adc %0,__zero_reg__ 3333 swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__ 3334 bst %0,0\;ror %0\;bld %0,7 3335 " ; empty 3336 [(set_attr "length" "2,4,4,1,3,5,3,0") 3337 (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")]) 3338 3339;; Split all rotates of HI,SI and PSImode registers where rotation is by 3340;; a whole number of bytes. The split creates the appropriate moves and 3341;; considers all overlap situations. 3342 3343;; HImode does not need scratch. Use attribute for this constraint. 3344 3345(define_mode_attr rotx [(SI "&r,&r,X") (PSI "&r,&r,X") (HI "X,X,X")]) 3346(define_mode_attr rotsmode [(SI "HI") (PSI "QI") (HI "QI")]) 3347 3348;; "rotlhi3" 3349;; "rotlpsi3" 3350;; "rotlsi3" 3351(define_expand "rotl<mode>3" 3352 [(parallel [(set (match_operand:HISI 0 "register_operand" "") 3353 (rotate:HISI (match_operand:HISI 1 "register_operand" "") 3354 (match_operand:VOID 2 "const_int_operand" ""))) 3355 (clobber (match_dup 3))])] 3356 "" 3357 { 3358 int offset; 3359 3360 if (!CONST_INT_P (operands[2])) 3361 FAIL; 3362 3363 offset = INTVAL (operands[2]); 3364 3365 if (0 == offset % 8) 3366 { 3367 if (AVR_HAVE_MOVW && 0 == offset % 16) 3368 operands[3] = gen_rtx_SCRATCH (<rotsmode>mode); 3369 else 3370 operands[3] = gen_rtx_SCRATCH (QImode); 3371 } 3372 else if (offset == 1 3373 || offset == GET_MODE_BITSIZE (<MODE>mode) -1) 3374 { 3375 /*; Support rotate left/right by 1 */ 3376 3377 emit_move_insn (operands[0], 3378 gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2])); 3379 DONE; 3380 } 3381 else 3382 FAIL; 3383 }) 3384 3385(define_insn "*rotlhi2.1" 3386 [(set (match_operand:HI 0 "register_operand" "=r") 3387 (rotate:HI (match_operand:HI 1 "register_operand" "0") 3388 (const_int 1)))] 3389 "" 3390 "lsl %A0\;rol %B0\;adc %A0,__zero_reg__" 3391 [(set_attr "length" "3") 3392 (set_attr "cc" "clobber")]) 3393 3394(define_insn "*rotlhi2.15" 3395 [(set (match_operand:HI 0 "register_operand" "=r") 3396 (rotate:HI (match_operand:HI 1 "register_operand" "0") 3397 (const_int 15)))] 3398 "" 3399 "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7" 3400 [(set_attr "length" "4") 3401 (set_attr "cc" "clobber")]) 3402 3403(define_insn "*rotlpsi2.1" 3404 [(set (match_operand:PSI 0 "register_operand" "=r") 3405 (rotate:PSI (match_operand:PSI 1 "register_operand" "0") 3406 (const_int 1)))] 3407 "" 3408 "lsl %A0\;rol %B0\;rol %C0\;adc %A0,__zero_reg__" 3409 [(set_attr "length" "4") 3410 (set_attr "cc" "clobber")]) 3411 3412(define_insn "*rotlpsi2.23" 3413 [(set (match_operand:PSI 0 "register_operand" "=r") 3414 (rotate:PSI (match_operand:PSI 1 "register_operand" "0") 3415 (const_int 23)))] 3416 "" 3417 "bst %A0,0\;ror %C0\;ror %B0\;ror %A0\;bld %C0,7" 3418 [(set_attr "length" "5") 3419 (set_attr "cc" "clobber")]) 3420 3421(define_insn "*rotlsi2.1" 3422 [(set (match_operand:SI 0 "register_operand" "=r") 3423 (rotate:SI (match_operand:SI 1 "register_operand" "0") 3424 (const_int 1)))] 3425 "" 3426 "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__" 3427 [(set_attr "length" "5") 3428 (set_attr "cc" "clobber")]) 3429 3430(define_insn "*rotlsi2.31" 3431 [(set (match_operand:SI 0 "register_operand" "=r") 3432 (rotate:SI (match_operand:SI 1 "register_operand" "0") 3433 (const_int 31)))] 3434 "" 3435 "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7" 3436 [(set_attr "length" "6") 3437 (set_attr "cc" "clobber")]) 3438 3439;; Overlapping non-HImode registers often (but not always) need a scratch. 3440;; The best we can do is use early clobber alternative "#&r" so that 3441;; completely non-overlapping operands dont get a scratch but # so register 3442;; allocation does not prefer non-overlapping. 3443 3444 3445;; Split word aligned rotates using scratch that is mode dependent. 3446 3447;; "*rotwhi" 3448;; "*rotwsi" 3449(define_insn_and_split "*rotw<mode>" 3450 [(set (match_operand:HISI 0 "register_operand" "=r,r,#&r") 3451 (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r") 3452 (match_operand 2 "const_int_operand" "n,n,n"))) 3453 (clobber (match_scratch:<rotsmode> 3 "=<rotx>"))] 3454 "AVR_HAVE_MOVW 3455 && CONST_INT_P (operands[2]) 3456 && GET_MODE_SIZE (<MODE>mode) % 2 == 0 3457 && 0 == INTVAL (operands[2]) % 16" 3458 "#" 3459 "&& reload_completed" 3460 [(const_int 0)] 3461 { 3462 avr_rotate_bytes (operands); 3463 DONE; 3464 }) 3465 3466 3467;; Split byte aligned rotates using scratch that is always QI mode. 3468 3469;; "*rotbhi" 3470;; "*rotbpsi" 3471;; "*rotbsi" 3472(define_insn_and_split "*rotb<mode>" 3473 [(set (match_operand:HISI 0 "register_operand" "=r,r,#&r") 3474 (rotate:HISI (match_operand:HISI 1 "register_operand" "0,r,r") 3475 (match_operand 2 "const_int_operand" "n,n,n"))) 3476 (clobber (match_scratch:QI 3 "=<rotx>"))] 3477 "CONST_INT_P (operands[2]) 3478 && (8 == INTVAL (operands[2]) % 16 3479 || ((!AVR_HAVE_MOVW 3480 || GET_MODE_SIZE (<MODE>mode) % 2 != 0) 3481 && 0 == INTVAL (operands[2]) % 16))" 3482 "#" 3483 "&& reload_completed" 3484 [(const_int 0)] 3485 { 3486 avr_rotate_bytes (operands); 3487 DONE; 3488 }) 3489 3490 3491;;<< << << << << << << << << << << << << << << << << << << << << << << << << << 3492;; arithmetic shift left 3493 3494;; "ashlqi3" 3495;; "ashlqq3" "ashluqq3" 3496(define_expand "ashl<mode>3" 3497 [(set (match_operand:ALL1 0 "register_operand" "") 3498 (ashift:ALL1 (match_operand:ALL1 1 "register_operand" "") 3499 (match_operand:QI 2 "nop_general_operand" "")))]) 3500 3501(define_split ; ashlqi3_const4 3502 [(set (match_operand:ALL1 0 "d_register_operand" "") 3503 (ashift:ALL1 (match_dup 0) 3504 (const_int 4)))] 3505 "" 3506 [(set (match_dup 1) 3507 (rotate:QI (match_dup 1) 3508 (const_int 4))) 3509 (set (match_dup 1) 3510 (and:QI (match_dup 1) 3511 (const_int -16)))] 3512 { 3513 operands[1] = avr_to_int_mode (operands[0]); 3514 }) 3515 3516(define_split ; ashlqi3_const5 3517 [(set (match_operand:ALL1 0 "d_register_operand" "") 3518 (ashift:ALL1 (match_dup 0) 3519 (const_int 5)))] 3520 "" 3521 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4))) 3522 (set (match_dup 1) (ashift:QI (match_dup 1) (const_int 1))) 3523 (set (match_dup 1) (and:QI (match_dup 1) (const_int -32)))] 3524 { 3525 operands[1] = avr_to_int_mode (operands[0]); 3526 }) 3527 3528(define_split ; ashlqi3_const6 3529 [(set (match_operand:ALL1 0 "d_register_operand" "") 3530 (ashift:ALL1 (match_dup 0) 3531 (const_int 6)))] 3532 "" 3533 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4))) 3534 (set (match_dup 1) (ashift:QI (match_dup 1) (const_int 2))) 3535 (set (match_dup 1) (and:QI (match_dup 1) (const_int -64)))] 3536 { 3537 operands[1] = avr_to_int_mode (operands[0]); 3538 }) 3539 3540;; "*ashlqi3" 3541;; "*ashlqq3" "*ashluqq3" 3542(define_insn "*ashl<mode>3" 3543 [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,!d,r,r") 3544 (ashift:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0,0") 3545 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))] 3546 "" 3547 { 3548 return ashlqi3_out (insn, operands, NULL); 3549 } 3550 [(set_attr "length" "5,0,1,2,4,6,9") 3551 (set_attr "adjust_len" "ashlqi") 3552 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")]) 3553 3554(define_insn "ashl<mode>3" 3555 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") 3556 (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") 3557 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] 3558 "" 3559 { 3560 return ashlhi3_out (insn, operands, NULL); 3561 } 3562 [(set_attr "length" "6,0,2,2,4,10,10") 3563 (set_attr "adjust_len" "ashlhi") 3564 (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")]) 3565 3566 3567;; Insns like the following are generated when (implicitly) extending 8-bit shifts 3568;; like char1 = char2 << char3. Only the low-byte is needed in that situation. 3569 3570;; "*ashluqihiqi3" 3571;; "*ashlsqihiqi3" 3572(define_insn_and_split "*ashl<extend_su>qihiqi3" 3573 [(set (match_operand:QI 0 "register_operand" "=r") 3574 (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0")) 3575 (match_operand:QI 2 "register_operand" "r")) 3576 0))] 3577 "" 3578 "#" 3579 "" 3580 [(set (match_dup 0) 3581 (ashift:QI (match_dup 1) 3582 (match_dup 2)))]) 3583 3584;; ??? Combiner does not recognize that it could split the following insn; 3585;; presumably because he has no register handy? 3586 3587;; "*ashluqihiqi3.mem" 3588;; "*ashlsqihiqi3.mem" 3589(define_insn_and_split "*ashl<extend_su>qihiqi3.mem" 3590 [(set (match_operand:QI 0 "memory_operand" "=m") 3591 (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r")) 3592 (match_operand:QI 2 "register_operand" "r")) 3593 0))] 3594 "!reload_completed" 3595 { gcc_unreachable(); } 3596 "&& 1" 3597 [(set (match_dup 3) 3598 (ashift:QI (match_dup 1) 3599 (match_dup 2))) 3600 (set (match_dup 0) 3601 (match_dup 3))] 3602 { 3603 operands[3] = gen_reg_rtx (QImode); 3604 }) 3605 3606;; Similar. 3607 3608(define_insn_and_split "*ashlhiqi3" 3609 [(set (match_operand:QI 0 "nonimmediate_operand" "=r") 3610 (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0") 3611 (match_operand:QI 2 "register_operand" "r")) 0))] 3612 "!reload_completed" 3613 { gcc_unreachable(); } 3614 "&& 1" 3615 [(set (match_dup 4) 3616 (ashift:QI (match_dup 3) 3617 (match_dup 2))) 3618 (set (match_dup 0) 3619 (match_dup 4))] 3620 { 3621 operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0); 3622 operands[4] = gen_reg_rtx (QImode); 3623 }) 3624 3625;; High part of 16-bit shift is unused after the instruction: 3626;; No need to compute it, map to 8-bit shift. 3627 3628(define_peephole2 3629 [(set (match_operand:HI 0 "register_operand" "") 3630 (ashift:HI (match_dup 0) 3631 (match_operand:QI 1 "register_operand" "")))] 3632 "" 3633 [(set (match_dup 2) 3634 (ashift:QI (match_dup 2) 3635 (match_dup 1))) 3636 (clobber (match_dup 3))] 3637 { 3638 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1); 3639 3640 if (!peep2_reg_dead_p (1, operands[3])) 3641 FAIL; 3642 3643 operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0); 3644 }) 3645 3646 3647;; "ashlsi3" 3648;; "ashlsq3" "ashlusq3" 3649;; "ashlsa3" "ashlusa3" 3650(define_insn "ashl<mode>3" 3651 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") 3652 (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") 3653 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] 3654 "" 3655 { 3656 return ashlsi3_out (insn, operands, NULL); 3657 } 3658 [(set_attr "length" "8,0,4,4,8,10,12") 3659 (set_attr "adjust_len" "ashlsi") 3660 (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")]) 3661 3662;; Optimize if a scratch register from LD_REGS happens to be available. 3663 3664(define_peephole2 ; ashlqi3_l_const4 3665 [(set (match_operand:ALL1 0 "l_register_operand" "") 3666 (ashift:ALL1 (match_dup 0) 3667 (const_int 4))) 3668 (match_scratch:QI 1 "d")] 3669 "" 3670 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4))) 3671 (set (match_dup 1) (const_int -16)) 3672 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))] 3673 { 3674 operands[2] = avr_to_int_mode (operands[0]); 3675 }) 3676 3677(define_peephole2 ; ashlqi3_l_const5 3678 [(set (match_operand:ALL1 0 "l_register_operand" "") 3679 (ashift:ALL1 (match_dup 0) 3680 (const_int 5))) 3681 (match_scratch:QI 1 "d")] 3682 "" 3683 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4))) 3684 (set (match_dup 2) (ashift:QI (match_dup 2) (const_int 1))) 3685 (set (match_dup 1) (const_int -32)) 3686 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))] 3687 { 3688 operands[2] = avr_to_int_mode (operands[0]); 3689 }) 3690 3691(define_peephole2 ; ashlqi3_l_const6 3692 [(set (match_operand:ALL1 0 "l_register_operand" "") 3693 (ashift:ALL1 (match_dup 0) 3694 (const_int 6))) 3695 (match_scratch:QI 1 "d")] 3696 "" 3697 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4))) 3698 (set (match_dup 2) (ashift:QI (match_dup 2) (const_int 2))) 3699 (set (match_dup 1) (const_int -64)) 3700 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))] 3701 { 3702 operands[2] = avr_to_int_mode (operands[0]); 3703 }) 3704 3705(define_peephole2 3706 [(match_scratch:QI 3 "d") 3707 (set (match_operand:ALL2 0 "register_operand" "") 3708 (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "") 3709 (match_operand:QI 2 "const_int_operand" "")))] 3710 "" 3711 [(parallel [(set (match_dup 0) 3712 (ashift:ALL2 (match_dup 1) 3713 (match_dup 2))) 3714 (clobber (match_dup 3))])]) 3715 3716;; "*ashlhi3_const" 3717;; "*ashlhq3_const" "*ashluhq3_const" 3718;; "*ashlha3_const" "*ashluha3_const" 3719(define_insn "*ashl<mode>3_const" 3720 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") 3721 (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") 3722 (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) 3723 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] 3724 "reload_completed" 3725 { 3726 return ashlhi3_out (insn, operands, NULL); 3727 } 3728 [(set_attr "length" "0,2,2,4,10") 3729 (set_attr "adjust_len" "ashlhi") 3730 (set_attr "cc" "none,set_n,clobber,set_n,clobber")]) 3731 3732(define_peephole2 3733 [(match_scratch:QI 3 "d") 3734 (set (match_operand:ALL4 0 "register_operand" "") 3735 (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "") 3736 (match_operand:QI 2 "const_int_operand" "")))] 3737 "" 3738 [(parallel [(set (match_dup 0) 3739 (ashift:ALL4 (match_dup 1) 3740 (match_dup 2))) 3741 (clobber (match_dup 3))])]) 3742 3743;; "*ashlsi3_const" 3744;; "*ashlsq3_const" "*ashlusq3_const" 3745;; "*ashlsa3_const" "*ashlusa3_const" 3746(define_insn "*ashl<mode>3_const" 3747 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") 3748 (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") 3749 (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) 3750 (clobber (match_scratch:QI 3 "=X,X,X,&d"))] 3751 "reload_completed" 3752 { 3753 return ashlsi3_out (insn, operands, NULL); 3754 } 3755 [(set_attr "length" "0,4,4,10") 3756 (set_attr "adjust_len" "ashlsi") 3757 (set_attr "cc" "none,set_n,clobber,clobber")]) 3758 3759(define_expand "ashlpsi3" 3760 [(parallel [(set (match_operand:PSI 0 "register_operand" "") 3761 (ashift:PSI (match_operand:PSI 1 "register_operand" "") 3762 (match_operand:QI 2 "nonmemory_operand" ""))) 3763 (clobber (scratch:QI))])] 3764 "" 3765 { 3766 if (AVR_HAVE_MUL 3767 && CONST_INT_P (operands[2])) 3768 { 3769 if (IN_RANGE (INTVAL (operands[2]), 3, 6)) 3770 { 3771 rtx xoffset = force_reg (QImode, gen_int_mode (1 << INTVAL (operands[2]), QImode)); 3772 emit_insn (gen_mulsqipsi3 (operands[0], xoffset, operands[1])); 3773 DONE; 3774 } 3775 else if (optimize_insn_for_speed_p () 3776 && INTVAL (operands[2]) != 16 3777 && IN_RANGE (INTVAL (operands[2]), 9, 22)) 3778 { 3779 rtx xoffset = force_reg (PSImode, gen_int_mode (1 << INTVAL (operands[2]), PSImode)); 3780 emit_insn (gen_mulpsi3 (operands[0], operands[1], xoffset)); 3781 DONE; 3782 } 3783 } 3784 }) 3785 3786(define_insn "*ashlpsi3" 3787 [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r") 3788 (ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0") 3789 (match_operand:QI 2 "nonmemory_operand" "r,P,O,n"))) 3790 (clobber (match_scratch:QI 3 "=X,X,X,&d"))] 3791 "" 3792 { 3793 return avr_out_ashlpsi3 (insn, operands, NULL); 3794 } 3795 [(set_attr "adjust_len" "ashlpsi") 3796 (set_attr "cc" "clobber")]) 3797 3798;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> 3799;; arithmetic shift right 3800 3801;; "ashrqi3" 3802;; "ashrqq3" "ashruqq3" 3803(define_insn "ashr<mode>3" 3804 [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,r ,r ,r") 3805 (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0 ,0") 3806 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,C03 C04 C05,C06 C07,Qm")))] 3807 "" 3808 { 3809 return ashrqi3_out (insn, operands, NULL); 3810 } 3811 [(set_attr "length" "5,0,1,2,5,4,9") 3812 (set_attr "adjust_len" "ashrqi") 3813 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,clobber,clobber")]) 3814 3815;; "ashrhi3" 3816;; "ashrhq3" "ashruhq3" 3817;; "ashrha3" "ashruha3" 3818(define_insn "ashr<mode>3" 3819 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") 3820 (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") 3821 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] 3822 "" 3823 { 3824 return ashrhi3_out (insn, operands, NULL); 3825 } 3826 [(set_attr "length" "6,0,2,4,4,10,10") 3827 (set_attr "adjust_len" "ashrhi") 3828 (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")]) 3829 3830(define_insn "ashrpsi3" 3831 [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r") 3832 (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r,0") 3833 (match_operand:QI 2 "nonmemory_operand" "r,P,K,O,n"))) 3834 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] 3835 "" 3836 { 3837 return avr_out_ashrpsi3 (insn, operands, NULL); 3838 } 3839 [(set_attr "adjust_len" "ashrpsi") 3840 (set_attr "cc" "clobber")]) 3841 3842;; "ashrsi3" 3843;; "ashrsq3" "ashrusq3" 3844;; "ashrsa3" "ashrusa3" 3845(define_insn "ashr<mode>3" 3846 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") 3847 (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") 3848 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] 3849 "" 3850 { 3851 return ashrsi3_out (insn, operands, NULL); 3852 } 3853 [(set_attr "length" "8,0,4,6,8,10,12") 3854 (set_attr "adjust_len" "ashrsi") 3855 (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")]) 3856 3857;; Optimize if a scratch register from LD_REGS happens to be available. 3858 3859(define_peephole2 3860 [(match_scratch:QI 3 "d") 3861 (set (match_operand:ALL2 0 "register_operand" "") 3862 (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "") 3863 (match_operand:QI 2 "const_int_operand" "")))] 3864 "" 3865 [(parallel [(set (match_dup 0) 3866 (ashiftrt:ALL2 (match_dup 1) 3867 (match_dup 2))) 3868 (clobber (match_dup 3))])]) 3869 3870;; "*ashrhi3_const" 3871;; "*ashrhq3_const" "*ashruhq3_const" 3872;; "*ashrha3_const" "*ashruha3_const" 3873(define_insn "*ashr<mode>3_const" 3874 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") 3875 (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") 3876 (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) 3877 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] 3878 "reload_completed" 3879 { 3880 return ashrhi3_out (insn, operands, NULL); 3881 } 3882 [(set_attr "length" "0,2,4,4,10") 3883 (set_attr "adjust_len" "ashrhi") 3884 (set_attr "cc" "none,clobber,set_n,clobber,clobber")]) 3885 3886(define_peephole2 3887 [(match_scratch:QI 3 "d") 3888 (set (match_operand:ALL4 0 "register_operand" "") 3889 (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "") 3890 (match_operand:QI 2 "const_int_operand" "")))] 3891 "" 3892 [(parallel [(set (match_dup 0) 3893 (ashiftrt:ALL4 (match_dup 1) 3894 (match_dup 2))) 3895 (clobber (match_dup 3))])]) 3896 3897;; "*ashrsi3_const" 3898;; "*ashrsq3_const" "*ashrusq3_const" 3899;; "*ashrsa3_const" "*ashrusa3_const" 3900(define_insn "*ashr<mode>3_const" 3901 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") 3902 (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") 3903 (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) 3904 (clobber (match_scratch:QI 3 "=X,X,X,&d"))] 3905 "reload_completed" 3906 { 3907 return ashrsi3_out (insn, operands, NULL); 3908 } 3909 [(set_attr "length" "0,4,4,10") 3910 (set_attr "adjust_len" "ashrsi") 3911 (set_attr "cc" "none,clobber,set_n,clobber")]) 3912 3913;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> 3914;; logical shift right 3915 3916;; "lshrqi3" 3917;; "lshrqq3 "lshruqq3" 3918(define_expand "lshr<mode>3" 3919 [(set (match_operand:ALL1 0 "register_operand" "") 3920 (lshiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "") 3921 (match_operand:QI 2 "nop_general_operand" "")))]) 3922 3923(define_split ; lshrqi3_const4 3924 [(set (match_operand:ALL1 0 "d_register_operand" "") 3925 (lshiftrt:ALL1 (match_dup 0) 3926 (const_int 4)))] 3927 "" 3928 [(set (match_dup 1) 3929 (rotate:QI (match_dup 1) 3930 (const_int 4))) 3931 (set (match_dup 1) 3932 (and:QI (match_dup 1) 3933 (const_int 15)))] 3934 { 3935 operands[1] = avr_to_int_mode (operands[0]); 3936 }) 3937 3938(define_split ; lshrqi3_const5 3939 [(set (match_operand:ALL1 0 "d_register_operand" "") 3940 (lshiftrt:ALL1 (match_dup 0) 3941 (const_int 5)))] 3942 "" 3943 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4))) 3944 (set (match_dup 1) (lshiftrt:QI (match_dup 1) (const_int 1))) 3945 (set (match_dup 1) (and:QI (match_dup 1) (const_int 7)))] 3946 { 3947 operands[1] = avr_to_int_mode (operands[0]); 3948 }) 3949 3950(define_split ; lshrqi3_const6 3951 [(set (match_operand:QI 0 "d_register_operand" "") 3952 (lshiftrt:QI (match_dup 0) 3953 (const_int 6)))] 3954 "" 3955 [(set (match_dup 1) (rotate:QI (match_dup 1) (const_int 4))) 3956 (set (match_dup 1) (lshiftrt:QI (match_dup 1) (const_int 2))) 3957 (set (match_dup 1) (and:QI (match_dup 1) (const_int 3)))] 3958 { 3959 operands[1] = avr_to_int_mode (operands[0]); 3960 }) 3961 3962;; "*lshrqi3" 3963;; "*lshrqq3" 3964;; "*lshruqq3" 3965(define_insn "*lshr<mode>3" 3966 [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,!d,r,r") 3967 (lshiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0,0") 3968 (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))] 3969 "" 3970 { 3971 return lshrqi3_out (insn, operands, NULL); 3972 } 3973 [(set_attr "length" "5,0,1,2,4,6,9") 3974 (set_attr "adjust_len" "lshrqi") 3975 (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")]) 3976 3977;; "lshrhi3" 3978;; "lshrhq3" "lshruhq3" 3979;; "lshrha3" "lshruha3" 3980(define_insn "lshr<mode>3" 3981 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") 3982 (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") 3983 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] 3984 "" 3985 { 3986 return lshrhi3_out (insn, operands, NULL); 3987 } 3988 [(set_attr "length" "6,0,2,2,4,10,10") 3989 (set_attr "adjust_len" "lshrhi") 3990 (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")]) 3991 3992(define_insn "lshrpsi3" 3993 [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r") 3994 (lshiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0,0") 3995 (match_operand:QI 2 "nonmemory_operand" "r,P,O,K,n"))) 3996 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] 3997 "" 3998 { 3999 return avr_out_lshrpsi3 (insn, operands, NULL); 4000 } 4001 [(set_attr "adjust_len" "lshrpsi") 4002 (set_attr "cc" "clobber")]) 4003 4004;; "lshrsi3" 4005;; "lshrsq3" "lshrusq3" 4006;; "lshrsa3" "lshrusa3" 4007(define_insn "lshr<mode>3" 4008 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") 4009 (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") 4010 (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] 4011 "" 4012 { 4013 return lshrsi3_out (insn, operands, NULL); 4014 } 4015 [(set_attr "length" "8,0,4,4,8,10,12") 4016 (set_attr "adjust_len" "lshrsi") 4017 (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")]) 4018 4019;; Optimize if a scratch register from LD_REGS happens to be available. 4020 4021(define_peephole2 ; lshrqi3_l_const4 4022 [(set (match_operand:ALL1 0 "l_register_operand" "") 4023 (lshiftrt:ALL1 (match_dup 0) 4024 (const_int 4))) 4025 (match_scratch:QI 1 "d")] 4026 "" 4027 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4))) 4028 (set (match_dup 1) (const_int 15)) 4029 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))] 4030 { 4031 operands[2] = avr_to_int_mode (operands[0]); 4032 }) 4033 4034(define_peephole2 ; lshrqi3_l_const5 4035 [(set (match_operand:ALL1 0 "l_register_operand" "") 4036 (lshiftrt:ALL1 (match_dup 0) 4037 (const_int 5))) 4038 (match_scratch:QI 1 "d")] 4039 "" 4040 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4))) 4041 (set (match_dup 2) (lshiftrt:QI (match_dup 2) (const_int 1))) 4042 (set (match_dup 1) (const_int 7)) 4043 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))] 4044 { 4045 operands[2] = avr_to_int_mode (operands[0]); 4046 }) 4047 4048(define_peephole2 ; lshrqi3_l_const6 4049 [(set (match_operand:ALL1 0 "l_register_operand" "") 4050 (lshiftrt:ALL1 (match_dup 0) 4051 (const_int 6))) 4052 (match_scratch:QI 1 "d")] 4053 "" 4054 [(set (match_dup 2) (rotate:QI (match_dup 2) (const_int 4))) 4055 (set (match_dup 2) (lshiftrt:QI (match_dup 2) (const_int 2))) 4056 (set (match_dup 1) (const_int 3)) 4057 (set (match_dup 2) (and:QI (match_dup 2) (match_dup 1)))] 4058 { 4059 operands[2] = avr_to_int_mode (operands[0]); 4060 }) 4061 4062(define_peephole2 4063 [(match_scratch:QI 3 "d") 4064 (set (match_operand:ALL2 0 "register_operand" "") 4065 (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "") 4066 (match_operand:QI 2 "const_int_operand" "")))] 4067 "" 4068 [(parallel [(set (match_dup 0) 4069 (lshiftrt:ALL2 (match_dup 1) 4070 (match_dup 2))) 4071 (clobber (match_dup 3))])]) 4072 4073;; "*lshrhi3_const" 4074;; "*lshrhq3_const" "*lshruhq3_const" 4075;; "*lshrha3_const" "*lshruha3_const" 4076(define_insn "*lshr<mode>3_const" 4077 [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") 4078 (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") 4079 (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) 4080 (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] 4081 "reload_completed" 4082 { 4083 return lshrhi3_out (insn, operands, NULL); 4084 } 4085 [(set_attr "length" "0,2,2,4,10") 4086 (set_attr "adjust_len" "lshrhi") 4087 (set_attr "cc" "none,clobber,clobber,clobber,clobber")]) 4088 4089(define_peephole2 4090 [(match_scratch:QI 3 "d") 4091 (set (match_operand:ALL4 0 "register_operand" "") 4092 (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "") 4093 (match_operand:QI 2 "const_int_operand" "")))] 4094 "" 4095 [(parallel [(set (match_dup 0) 4096 (lshiftrt:ALL4 (match_dup 1) 4097 (match_dup 2))) 4098 (clobber (match_dup 3))])]) 4099 4100;; "*lshrsi3_const" 4101;; "*lshrsq3_const" "*lshrusq3_const" 4102;; "*lshrsa3_const" "*lshrusa3_const" 4103(define_insn "*lshr<mode>3_const" 4104 [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") 4105 (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") 4106 (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) 4107 (clobber (match_scratch:QI 3 "=X,X,X,&d"))] 4108 "reload_completed" 4109 { 4110 return lshrsi3_out (insn, operands, NULL); 4111 } 4112 [(set_attr "length" "0,4,4,10") 4113 (set_attr "adjust_len" "lshrsi") 4114 (set_attr "cc" "none,clobber,clobber,clobber")]) 4115 4116;; abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) 4117;; abs 4118 4119(define_insn "absqi2" 4120 [(set (match_operand:QI 0 "register_operand" "=r") 4121 (abs:QI (match_operand:QI 1 "register_operand" "0")))] 4122 "" 4123 "sbrc %0,7 4124 neg %0" 4125 [(set_attr "length" "2") 4126 (set_attr "cc" "clobber")]) 4127 4128 4129(define_insn "abssf2" 4130 [(set (match_operand:SF 0 "register_operand" "=d,r") 4131 (abs:SF (match_operand:SF 1 "register_operand" "0,0")))] 4132 "" 4133 "@ 4134 andi %D0,0x7f 4135 clt\;bld %D0,7" 4136 [(set_attr "length" "1,2") 4137 (set_attr "cc" "set_n,clobber")]) 4138 4139;; 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 0 - x 4140;; neg 4141 4142(define_insn "negqi2" 4143 [(set (match_operand:QI 0 "register_operand" "=r") 4144 (neg:QI (match_operand:QI 1 "register_operand" "0")))] 4145 "" 4146 "neg %0" 4147 [(set_attr "length" "1") 4148 (set_attr "cc" "set_vzn")]) 4149 4150(define_insn "*negqihi2" 4151 [(set (match_operand:HI 0 "register_operand" "=r") 4152 (neg:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0"))))] 4153 "" 4154 "clr %B0\;neg %A0\;brge .+2\;com %B0" 4155 [(set_attr "length" "4") 4156 (set_attr "cc" "set_n")]) 4157 4158(define_insn "neghi2" 4159 [(set (match_operand:HI 0 "register_operand" "=r,&r") 4160 (neg:HI (match_operand:HI 1 "register_operand" "0,r")))] 4161 "" 4162 "@ 4163 neg %B0\;neg %A0\;sbc %B0,__zero_reg__ 4164 clr %A0\;clr %B0\;sub %A0,%A1\;sbc %B0,%B1" 4165 [(set_attr "length" "3,4") 4166 (set_attr "cc" "set_czn")]) 4167 4168(define_insn "negpsi2" 4169 [(set (match_operand:PSI 0 "register_operand" "=!d,r,&r") 4170 (neg:PSI (match_operand:PSI 1 "register_operand" "0,0,r")))] 4171 "" 4172 "@ 4173 com %C0\;com %B0\;neg %A0\;sbci %B0,-1\;sbci %C0,-1 4174 com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__ 4175 clr %A0\;clr %B0\;clr %C0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1" 4176 [(set_attr "length" "5,6,6") 4177 (set_attr "cc" "set_czn,set_n,set_czn")]) 4178 4179(define_insn "negsi2" 4180 [(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r") 4181 (neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))] 4182 "" 4183 "@ 4184 com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1) 4185 com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__ 4186 clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1 4187 clr %A0\;clr %B0\;movw %C0,%A0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1" 4188 [(set_attr "length" "7,8,8,7") 4189 (set_attr "isa" "*,*,mov,movw") 4190 (set_attr "cc" "set_czn,set_n,set_czn,set_czn")]) 4191 4192(define_insn "negsf2" 4193 [(set (match_operand:SF 0 "register_operand" "=d,r") 4194 (neg:SF (match_operand:SF 1 "register_operand" "0,0")))] 4195 "" 4196 "@ 4197 subi %D0,0x80 4198 bst %D0,7\;com %D0\;bld %D0,7\;com %D0" 4199 [(set_attr "length" "1,4") 4200 (set_attr "cc" "set_n,set_n")]) 4201 4202;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4203;; not 4204 4205(define_insn "one_cmplqi2" 4206 [(set (match_operand:QI 0 "register_operand" "=r") 4207 (not:QI (match_operand:QI 1 "register_operand" "0")))] 4208 "" 4209 "com %0" 4210 [(set_attr "length" "1") 4211 (set_attr "cc" "set_czn")]) 4212 4213(define_insn "one_cmplhi2" 4214 [(set (match_operand:HI 0 "register_operand" "=r") 4215 (not:HI (match_operand:HI 1 "register_operand" "0")))] 4216 "" 4217 "com %0 4218 com %B0" 4219 [(set_attr "length" "2") 4220 (set_attr "cc" "set_n")]) 4221 4222(define_insn "one_cmplpsi2" 4223 [(set (match_operand:PSI 0 "register_operand" "=r") 4224 (not:PSI (match_operand:PSI 1 "register_operand" "0")))] 4225 "" 4226 "com %0\;com %B0\;com %C0" 4227 [(set_attr "length" "3") 4228 (set_attr "cc" "set_n")]) 4229 4230(define_insn "one_cmplsi2" 4231 [(set (match_operand:SI 0 "register_operand" "=r") 4232 (not:SI (match_operand:SI 1 "register_operand" "0")))] 4233 "" 4234 "com %0 4235 com %B0 4236 com %C0 4237 com %D0" 4238 [(set_attr "length" "4") 4239 (set_attr "cc" "set_n")]) 4240 4241;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x 4242;; sign extend 4243 4244;; We keep combiner from inserting hard registers into the input of sign- and 4245;; zero-extends. A hard register in the input operand is not wanted because 4246;; 32-bit multiply patterns clobber some hard registers and extends with a 4247;; hard register that overlaps these clobbers won't be combined to a widening 4248;; multiplication. There is no need for combine to propagate hard registers, 4249;; register allocation can do it just as well. 4250 4251(define_insn "extendqihi2" 4252 [(set (match_operand:HI 0 "register_operand" "=r,r") 4253 (sign_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))] 4254 "" 4255 { 4256 return avr_out_sign_extend (insn, operands, NULL); 4257 } 4258 [(set_attr "length" "3,4") 4259 (set_attr "adjust_len" "sext") 4260 (set_attr "cc" "set_n")]) 4261 4262(define_insn "extendqipsi2" 4263 [(set (match_operand:PSI 0 "register_operand" "=r,r") 4264 (sign_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))] 4265 "" 4266 { 4267 return avr_out_sign_extend (insn, operands, NULL); 4268 } 4269 [(set_attr "length" "4,5") 4270 (set_attr "adjust_len" "sext") 4271 (set_attr "cc" "set_n")]) 4272 4273(define_insn "extendqisi2" 4274 [(set (match_operand:SI 0 "register_operand" "=r,r") 4275 (sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))] 4276 "" 4277 { 4278 return avr_out_sign_extend (insn, operands, NULL); 4279 } 4280 [(set_attr "length" "5,6") 4281 (set_attr "adjust_len" "sext") 4282 (set_attr "cc" "set_n")]) 4283 4284(define_insn "extendhipsi2" 4285 [(set (match_operand:PSI 0 "register_operand" "=r,r") 4286 (sign_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))] 4287 "" 4288 { 4289 return avr_out_sign_extend (insn, operands, NULL); 4290 } 4291 [(set_attr "length" "3,5") 4292 (set_attr "adjust_len" "sext") 4293 (set_attr "cc" "set_n")]) 4294 4295(define_insn "extendhisi2" 4296 [(set (match_operand:SI 0 "register_operand" "=r,r") 4297 (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))] 4298 "" 4299 { 4300 return avr_out_sign_extend (insn, operands, NULL); 4301 } 4302 [(set_attr "length" "4,6") 4303 (set_attr "adjust_len" "sext") 4304 (set_attr "cc" "set_n")]) 4305 4306(define_insn "extendpsisi2" 4307 [(set (match_operand:SI 0 "register_operand" "=r") 4308 (sign_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "0")))] 4309 "" 4310 { 4311 return avr_out_sign_extend (insn, operands, NULL); 4312 } 4313 [(set_attr "length" "3") 4314 (set_attr "adjust_len" "sext") 4315 (set_attr "cc" "set_n")]) 4316 4317;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x 4318;; zero extend 4319 4320(define_insn_and_split "zero_extendqihi2" 4321 [(set (match_operand:HI 0 "register_operand" "=r") 4322 (zero_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))] 4323 "" 4324 "#" 4325 "reload_completed" 4326 [(set (match_dup 2) (match_dup 1)) 4327 (set (match_dup 3) (const_int 0))] 4328 { 4329 unsigned int low_off = subreg_lowpart_offset (QImode, HImode); 4330 unsigned int high_off = subreg_highpart_offset (QImode, HImode); 4331 4332 operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, low_off); 4333 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off); 4334 }) 4335 4336(define_insn_and_split "zero_extendqipsi2" 4337 [(set (match_operand:PSI 0 "register_operand" "=r") 4338 (zero_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))] 4339 "" 4340 "#" 4341 "reload_completed" 4342 [(set (match_dup 2) (match_dup 1)) 4343 (set (match_dup 3) (const_int 0)) 4344 (set (match_dup 4) (const_int 0))] 4345 { 4346 operands[2] = simplify_gen_subreg (QImode, operands[0], PSImode, 0); 4347 operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 1); 4348 operands[4] = simplify_gen_subreg (QImode, operands[0], PSImode, 2); 4349 }) 4350 4351(define_insn_and_split "zero_extendqisi2" 4352 [(set (match_operand:SI 0 "register_operand" "=r") 4353 (zero_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "r")))] 4354 "" 4355 "#" 4356 "reload_completed" 4357 [(set (match_dup 2) (zero_extend:HI (match_dup 1))) 4358 (set (match_dup 3) (const_int 0))] 4359 { 4360 unsigned int low_off = subreg_lowpart_offset (HImode, SImode); 4361 unsigned int high_off = subreg_highpart_offset (HImode, SImode); 4362 4363 operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off); 4364 operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off); 4365 }) 4366 4367(define_insn_and_split "zero_extendhipsi2" 4368 [(set (match_operand:PSI 0 "register_operand" "=r") 4369 (zero_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))] 4370 "" 4371 "#" 4372 "reload_completed" 4373 [(set (match_dup 2) (match_dup 1)) 4374 (set (match_dup 3) (const_int 0))] 4375 { 4376 operands[2] = simplify_gen_subreg (HImode, operands[0], PSImode, 0); 4377 operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 2); 4378 }) 4379 4380(define_insn_and_split "n_extendhipsi2" 4381 [(set (match_operand:PSI 0 "register_operand" "=r,r,d,r") 4382 (lo_sum:PSI (match_operand:QI 1 "const_int_operand" "L,P,n,n") 4383 (match_operand:HI 2 "register_operand" "r,r,r,r"))) 4384 (clobber (match_scratch:QI 3 "=X,X,X,&d"))] 4385 "" 4386 "#" 4387 "reload_completed" 4388 [(set (match_dup 4) (match_dup 2)) 4389 (set (match_dup 3) (match_dup 6)) 4390 ; no-op move in the case where no scratch is needed 4391 (set (match_dup 5) (match_dup 3))] 4392 { 4393 operands[4] = simplify_gen_subreg (HImode, operands[0], PSImode, 0); 4394 operands[5] = simplify_gen_subreg (QImode, operands[0], PSImode, 2); 4395 operands[6] = operands[1]; 4396 4397 if (GET_CODE (operands[3]) == SCRATCH) 4398 operands[3] = operands[5]; 4399 }) 4400 4401(define_insn_and_split "zero_extendhisi2" 4402 [(set (match_operand:SI 0 "register_operand" "=r") 4403 (zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))] 4404 "" 4405 "#" 4406 "reload_completed" 4407 [(set (match_dup 2) (match_dup 1)) 4408 (set (match_dup 3) (const_int 0))] 4409 { 4410 unsigned int low_off = subreg_lowpart_offset (HImode, SImode); 4411 unsigned int high_off = subreg_highpart_offset (HImode, SImode); 4412 4413 operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off); 4414 operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off); 4415 }) 4416 4417(define_insn_and_split "zero_extendpsisi2" 4418 [(set (match_operand:SI 0 "register_operand" "=r") 4419 (zero_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "r")))] 4420 "" 4421 "#" 4422 "reload_completed" 4423 [(set (match_dup 2) (match_dup 1)) 4424 (set (match_dup 3) (const_int 0))] 4425 { 4426 operands[2] = simplify_gen_subreg (PSImode, operands[0], SImode, 0); 4427 operands[3] = simplify_gen_subreg (QImode, operands[0], SImode, 3); 4428 }) 4429 4430(define_insn_and_split "zero_extendqidi2" 4431 [(set (match_operand:DI 0 "register_operand" "=r") 4432 (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))] 4433 "" 4434 "#" 4435 "reload_completed" 4436 [(set (match_dup 2) (zero_extend:SI (match_dup 1))) 4437 (set (match_dup 3) (const_int 0))] 4438 { 4439 unsigned int low_off = subreg_lowpart_offset (SImode, DImode); 4440 unsigned int high_off = subreg_highpart_offset (SImode, DImode); 4441 4442 operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); 4443 operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); 4444 }) 4445 4446(define_insn_and_split "zero_extendhidi2" 4447 [(set (match_operand:DI 0 "register_operand" "=r") 4448 (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))] 4449 "" 4450 "#" 4451 "reload_completed" 4452 [(set (match_dup 2) (zero_extend:SI (match_dup 1))) 4453 (set (match_dup 3) (const_int 0))] 4454 { 4455 unsigned int low_off = subreg_lowpart_offset (SImode, DImode); 4456 unsigned int high_off = subreg_highpart_offset (SImode, DImode); 4457 4458 operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); 4459 operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); 4460 }) 4461 4462(define_insn_and_split "zero_extendsidi2" 4463 [(set (match_operand:DI 0 "register_operand" "=r") 4464 (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))] 4465 "" 4466 "#" 4467 "reload_completed" 4468 [(set (match_dup 2) (match_dup 1)) 4469 (set (match_dup 3) (const_int 0))] 4470 { 4471 unsigned int low_off = subreg_lowpart_offset (SImode, DImode); 4472 unsigned int high_off = subreg_highpart_offset (SImode, DImode); 4473 4474 operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); 4475 operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); 4476 }) 4477 4478;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=> 4479;; compare 4480 4481; Optimize negated tests into reverse compare if overflow is undefined. 4482(define_insn "*negated_tstqi" 4483 [(set (cc0) 4484 (compare (neg:QI (match_operand:QI 0 "register_operand" "r")) 4485 (const_int 0)))] 4486 "!flag_wrapv && !flag_trapv && flag_strict_overflow" 4487 "cp __zero_reg__,%0" 4488 [(set_attr "cc" "compare") 4489 (set_attr "length" "1")]) 4490 4491(define_insn "*reversed_tstqi" 4492 [(set (cc0) 4493 (compare (const_int 0) 4494 (match_operand:QI 0 "register_operand" "r")))] 4495 "" 4496 "cp __zero_reg__,%0" 4497[(set_attr "cc" "compare") 4498 (set_attr "length" "2")]) 4499 4500(define_insn "*negated_tsthi" 4501 [(set (cc0) 4502 (compare (neg:HI (match_operand:HI 0 "register_operand" "r")) 4503 (const_int 0)))] 4504 "!flag_wrapv && !flag_trapv && flag_strict_overflow" 4505 "cp __zero_reg__,%A0 4506 cpc __zero_reg__,%B0" 4507[(set_attr "cc" "compare") 4508 (set_attr "length" "2")]) 4509 4510;; Leave here the clobber used by the cmphi pattern for simplicity, even 4511;; though it is unused, because this pattern is synthesized by avr_reorg. 4512(define_insn "*reversed_tsthi" 4513 [(set (cc0) 4514 (compare (const_int 0) 4515 (match_operand:HI 0 "register_operand" "r"))) 4516 (clobber (match_scratch:QI 1 "=X"))] 4517 "" 4518 "cp __zero_reg__,%A0 4519 cpc __zero_reg__,%B0" 4520[(set_attr "cc" "compare") 4521 (set_attr "length" "2")]) 4522 4523(define_insn "*negated_tstpsi" 4524 [(set (cc0) 4525 (compare (neg:PSI (match_operand:PSI 0 "register_operand" "r")) 4526 (const_int 0)))] 4527 "!flag_wrapv && !flag_trapv && flag_strict_overflow" 4528 "cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0" 4529 [(set_attr "cc" "compare") 4530 (set_attr "length" "3")]) 4531 4532(define_insn "*reversed_tstpsi" 4533 [(set (cc0) 4534 (compare (const_int 0) 4535 (match_operand:PSI 0 "register_operand" "r"))) 4536 (clobber (match_scratch:QI 1 "=X"))] 4537 "" 4538 "cp __zero_reg__,%A0\;cpc __zero_reg__,%B0\;cpc __zero_reg__,%C0" 4539 [(set_attr "cc" "compare") 4540 (set_attr "length" "3")]) 4541 4542(define_insn "*negated_tstsi" 4543 [(set (cc0) 4544 (compare (neg:SI (match_operand:SI 0 "register_operand" "r")) 4545 (const_int 0)))] 4546 "!flag_wrapv && !flag_trapv && flag_strict_overflow" 4547 "cp __zero_reg__,%A0 4548 cpc __zero_reg__,%B0 4549 cpc __zero_reg__,%C0 4550 cpc __zero_reg__,%D0" 4551 [(set_attr "cc" "compare") 4552 (set_attr "length" "4")]) 4553 4554;; "*reversed_tstsi" 4555;; "*reversed_tstsq" "*reversed_tstusq" 4556;; "*reversed_tstsa" "*reversed_tstusa" 4557(define_insn "*reversed_tst<mode>" 4558 [(set (cc0) 4559 (compare (match_operand:ALL4 0 "const0_operand" "Y00") 4560 (match_operand:ALL4 1 "register_operand" "r"))) 4561 (clobber (match_scratch:QI 2 "=X"))] 4562 "" 4563 "cp __zero_reg__,%A1 4564 cpc __zero_reg__,%B1 4565 cpc __zero_reg__,%C1 4566 cpc __zero_reg__,%D1" 4567 [(set_attr "cc" "compare") 4568 (set_attr "length" "4")]) 4569 4570 4571;; "*cmpqi" 4572;; "*cmpqq" "*cmpuqq" 4573(define_insn "*cmp<mode>" 4574 [(set (cc0) 4575 (compare (match_operand:ALL1 0 "register_operand" "r ,r,d") 4576 (match_operand:ALL1 1 "nonmemory_operand" "Y00,r,i")))] 4577 "" 4578 "@ 4579 tst %0 4580 cp %0,%1 4581 cpi %0,lo8(%1)" 4582 [(set_attr "cc" "compare,compare,compare") 4583 (set_attr "length" "1,1,1")]) 4584 4585(define_insn "*cmpqi_sign_extend" 4586 [(set (cc0) 4587 (compare (sign_extend:HI (match_operand:QI 0 "register_operand" "d")) 4588 (match_operand:HI 1 "s8_operand" "n")))] 4589 "" 4590 "cpi %0,lo8(%1)" 4591 [(set_attr "cc" "compare") 4592 (set_attr "length" "1")]) 4593 4594;; "*cmphi" 4595;; "*cmphq" "*cmpuhq" 4596;; "*cmpha" "*cmpuha" 4597(define_insn "*cmp<mode>" 4598 [(set (cc0) 4599 (compare (match_operand:ALL2 0 "register_operand" "!w ,r ,r,d ,r ,d,r") 4600 (match_operand:ALL2 1 "nonmemory_operand" "Y00,Y00,r,s ,s ,M,n Ynn"))) 4601 (clobber (match_scratch:QI 2 "=X ,X ,X,&d,&d ,X,&d"))] 4602 "" 4603 { 4604 switch (which_alternative) 4605 { 4606 case 0: 4607 case 1: 4608 return avr_out_tsthi (insn, operands, NULL); 4609 4610 case 2: 4611 return "cp %A0,%A1\;cpc %B0,%B1"; 4612 4613 case 3: 4614 if (<MODE>mode != HImode) 4615 break; 4616 return reg_unused_after (insn, operands[0]) 4617 ? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)" 4618 : "ldi %2,hi8(%1)\;cpi %A0,lo8(%1)\;cpc %B0,%2"; 4619 4620 case 4: 4621 if (<MODE>mode != HImode) 4622 break; 4623 return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2"; 4624 } 4625 4626 return avr_out_compare (insn, operands, NULL); 4627 } 4628 [(set_attr "cc" "compare") 4629 (set_attr "length" "1,2,2,3,4,2,4") 4630 (set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")]) 4631 4632(define_insn "*cmppsi" 4633 [(set (cc0) 4634 (compare (match_operand:PSI 0 "register_operand" "r,r,d ,r ,d,r") 4635 (match_operand:PSI 1 "nonmemory_operand" "L,r,s ,s ,M,n"))) 4636 (clobber (match_scratch:QI 2 "=X,X,&d,&d ,X,&d"))] 4637 "" 4638 { 4639 switch (which_alternative) 4640 { 4641 case 0: 4642 return avr_out_tstpsi (insn, operands, NULL); 4643 4644 case 1: 4645 return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1"; 4646 4647 case 2: 4648 return reg_unused_after (insn, operands[0]) 4649 ? "subi %A0,lo8(%1)\;sbci %B0,hi8(%1)\;sbci %C0,hh8(%1)" 4650 : "cpi %A0,lo8(%1)\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2"; 4651 4652 case 3: 4653 return "ldi %2,lo8(%1)\;cp %A0,%2\;ldi %2,hi8(%1)\;cpc %B0,%2\;ldi %2,hh8(%1)\;cpc %C0,%2"; 4654 } 4655 4656 return avr_out_compare (insn, operands, NULL); 4657 } 4658 [(set_attr "cc" "compare") 4659 (set_attr "length" "3,3,5,6,3,7") 4660 (set_attr "adjust_len" "tstpsi,*,*,*,compare,compare")]) 4661 4662;; "*cmpsi" 4663;; "*cmpsq" "*cmpusq" 4664;; "*cmpsa" "*cmpusa" 4665(define_insn "*cmp<mode>" 4666 [(set (cc0) 4667 (compare (match_operand:ALL4 0 "register_operand" "r ,r ,d,r ,r") 4668 (match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M,M ,n Ynn"))) 4669 (clobber (match_scratch:QI 2 "=X ,X ,X,&d,&d"))] 4670 "" 4671 { 4672 if (0 == which_alternative) 4673 return avr_out_tstsi (insn, operands, NULL); 4674 else if (1 == which_alternative) 4675 return "cp %A0,%A1\;cpc %B0,%B1\;cpc %C0,%C1\;cpc %D0,%D1"; 4676 4677 return avr_out_compare (insn, operands, NULL); 4678 } 4679 [(set_attr "cc" "compare") 4680 (set_attr "length" "4,4,4,5,8") 4681 (set_attr "adjust_len" "tstsi,*,compare,compare,compare")]) 4682 4683 4684;; ---------------------------------------------------------------------- 4685;; JUMP INSTRUCTIONS 4686;; ---------------------------------------------------------------------- 4687;; Conditional jump instructions 4688 4689;; "cbranchqi4" 4690;; "cbranchqq4" "cbranchuqq4" 4691(define_expand "cbranch<mode>4" 4692 [(set (cc0) 4693 (compare (match_operand:ALL1 1 "register_operand" "") 4694 (match_operand:ALL1 2 "nonmemory_operand" ""))) 4695 (set (pc) 4696 (if_then_else 4697 (match_operator 0 "ordered_comparison_operator" [(cc0) 4698 (const_int 0)]) 4699 (label_ref (match_operand 3 "" "")) 4700 (pc)))]) 4701 4702;; "cbranchhi4" "cbranchhq4" "cbranchuhq4" "cbranchha4" "cbranchuha4" 4703;; "cbranchsi4" "cbranchsq4" "cbranchusq4" "cbranchsa4" "cbranchusa4" 4704;; "cbranchpsi4" 4705(define_expand "cbranch<mode>4" 4706 [(parallel [(set (cc0) 4707 (compare (match_operand:ORDERED234 1 "register_operand" "") 4708 (match_operand:ORDERED234 2 "nonmemory_operand" ""))) 4709 (clobber (match_scratch:QI 4 ""))]) 4710 (set (pc) 4711 (if_then_else 4712 (match_operator 0 "ordered_comparison_operator" [(cc0) 4713 (const_int 0)]) 4714 (label_ref (match_operand 3 "" "")) 4715 (pc)))]) 4716 4717 4718;; Test a single bit in a QI/HI/SImode register. 4719;; Combine will create zero extract patterns for single bit tests. 4720;; permit any mode in source pattern by using VOIDmode. 4721 4722(define_insn "*sbrx_branch<mode>" 4723 [(set (pc) 4724 (if_then_else 4725 (match_operator 0 "eqne_operator" 4726 [(zero_extract:QIDI 4727 (match_operand:VOID 1 "register_operand" "r") 4728 (const_int 1) 4729 (match_operand 2 "const_int_operand" "n")) 4730 (const_int 0)]) 4731 (label_ref (match_operand 3 "" "")) 4732 (pc)))] 4733 "" 4734 { 4735 return avr_out_sbxx_branch (insn, operands); 4736 } 4737 [(set (attr "length") 4738 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) 4739 (le (minus (pc) (match_dup 3)) (const_int 2046))) 4740 (const_int 2) 4741 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 4742 (const_int 2) 4743 (const_int 4)))) 4744 (set_attr "cc" "clobber")]) 4745 4746;; Same test based on bitwise AND. Keep this in case gcc changes patterns. 4747;; or for old peepholes. 4748;; Fixme - bitwise Mask will not work for DImode 4749 4750(define_insn "*sbrx_and_branch<mode>" 4751 [(set (pc) 4752 (if_then_else 4753 (match_operator 0 "eqne_operator" 4754 [(and:QISI 4755 (match_operand:QISI 1 "register_operand" "r") 4756 (match_operand:QISI 2 "single_one_operand" "n")) 4757 (const_int 0)]) 4758 (label_ref (match_operand 3 "" "")) 4759 (pc)))] 4760 "" 4761 { 4762 HOST_WIDE_INT bitnumber; 4763 bitnumber = exact_log2 (GET_MODE_MASK (<MODE>mode) & INTVAL (operands[2])); 4764 operands[2] = GEN_INT (bitnumber); 4765 return avr_out_sbxx_branch (insn, operands); 4766 } 4767 [(set (attr "length") 4768 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) 4769 (le (minus (pc) (match_dup 3)) (const_int 2046))) 4770 (const_int 2) 4771 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 4772 (const_int 2) 4773 (const_int 4)))) 4774 (set_attr "cc" "clobber")]) 4775 4776;; Convert sign tests to bit 7/15/31 tests that match the above insns. 4777(define_peephole2 4778 [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") 4779 (const_int 0))) 4780 (set (pc) (if_then_else (ge (cc0) (const_int 0)) 4781 (label_ref (match_operand 1 "" "")) 4782 (pc)))] 4783 "" 4784 [(set (pc) (if_then_else (eq (zero_extract:HI (match_dup 0) 4785 (const_int 1) 4786 (const_int 7)) 4787 (const_int 0)) 4788 (label_ref (match_dup 1)) 4789 (pc)))]) 4790 4791(define_peephole2 4792 [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") 4793 (const_int 0))) 4794 (set (pc) (if_then_else (lt (cc0) (const_int 0)) 4795 (label_ref (match_operand 1 "" "")) 4796 (pc)))] 4797 "" 4798 [(set (pc) (if_then_else (ne (zero_extract:HI (match_dup 0) 4799 (const_int 1) 4800 (const_int 7)) 4801 (const_int 0)) 4802 (label_ref (match_dup 1)) 4803 (pc)))]) 4804 4805(define_peephole2 4806 [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") 4807 (const_int 0))) 4808 (clobber (match_operand:HI 2 ""))]) 4809 (set (pc) (if_then_else (ge (cc0) (const_int 0)) 4810 (label_ref (match_operand 1 "" "")) 4811 (pc)))] 4812 "" 4813 [(set (pc) (if_then_else (eq (and:HI (match_dup 0) (const_int -32768)) 4814 (const_int 0)) 4815 (label_ref (match_dup 1)) 4816 (pc)))]) 4817 4818(define_peephole2 4819 [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") 4820 (const_int 0))) 4821 (clobber (match_operand:HI 2 ""))]) 4822 (set (pc) (if_then_else (lt (cc0) (const_int 0)) 4823 (label_ref (match_operand 1 "" "")) 4824 (pc)))] 4825 "" 4826 [(set (pc) (if_then_else (ne (and:HI (match_dup 0) (const_int -32768)) 4827 (const_int 0)) 4828 (label_ref (match_dup 1)) 4829 (pc)))]) 4830 4831(define_peephole2 4832 [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") 4833 (const_int 0))) 4834 (clobber (match_operand:SI 2 ""))]) 4835 (set (pc) (if_then_else (ge (cc0) (const_int 0)) 4836 (label_ref (match_operand 1 "" "")) 4837 (pc)))] 4838 "" 4839 [(set (pc) (if_then_else (eq (and:SI (match_dup 0) (match_dup 2)) 4840 (const_int 0)) 4841 (label_ref (match_dup 1)) 4842 (pc)))] 4843 "operands[2] = gen_int_mode (-2147483647 - 1, SImode);") 4844 4845(define_peephole2 4846 [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") 4847 (const_int 0))) 4848 (clobber (match_operand:SI 2 ""))]) 4849 (set (pc) (if_then_else (lt (cc0) (const_int 0)) 4850 (label_ref (match_operand 1 "" "")) 4851 (pc)))] 4852 "" 4853 [(set (pc) (if_then_else (ne (and:SI (match_dup 0) (match_dup 2)) 4854 (const_int 0)) 4855 (label_ref (match_dup 1)) 4856 (pc)))] 4857 "operands[2] = gen_int_mode (-2147483647 - 1, SImode);") 4858 4859;; ************************************************************************ 4860;; Implementation of conditional jumps here. 4861;; Compare with 0 (test) jumps 4862;; ************************************************************************ 4863 4864(define_insn "branch" 4865 [(set (pc) 4866 (if_then_else (match_operator 1 "simple_comparison_operator" 4867 [(cc0) 4868 (const_int 0)]) 4869 (label_ref (match_operand 0 "" "")) 4870 (pc)))] 4871 "" 4872 { 4873 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0); 4874 } 4875 [(set_attr "type" "branch") 4876 (set_attr "cc" "clobber")]) 4877 4878 4879;; Same as above but wrap SET_SRC so that this branch won't be transformed 4880;; or optimized in the remainder. 4881 4882(define_insn "branch_unspec" 4883 [(set (pc) 4884 (unspec [(if_then_else (match_operator 1 "simple_comparison_operator" 4885 [(cc0) 4886 (const_int 0)]) 4887 (label_ref (match_operand 0 "" "")) 4888 (pc)) 4889 ] UNSPEC_IDENTITY))] 4890 "" 4891 { 4892 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0); 4893 } 4894 [(set_attr "type" "branch") 4895 (set_attr "cc" "none")]) 4896 4897;; **************************************************************** 4898;; AVR does not have following conditional jumps: LE,LEU,GT,GTU. 4899;; Convert them all to proper jumps. 4900;; ****************************************************************/ 4901 4902(define_insn "difficult_branch" 4903 [(set (pc) 4904 (if_then_else (match_operator 1 "difficult_comparison_operator" 4905 [(cc0) 4906 (const_int 0)]) 4907 (label_ref (match_operand 0 "" "")) 4908 (pc)))] 4909 "" 4910 { 4911 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 0); 4912 } 4913 [(set_attr "type" "branch1") 4914 (set_attr "cc" "clobber")]) 4915 4916;; revers branch 4917 4918(define_insn "rvbranch" 4919 [(set (pc) 4920 (if_then_else (match_operator 1 "simple_comparison_operator" 4921 [(cc0) 4922 (const_int 0)]) 4923 (pc) 4924 (label_ref (match_operand 0 "" ""))))] 4925 "" 4926 { 4927 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1); 4928 } 4929 [(set_attr "type" "branch1") 4930 (set_attr "cc" "clobber")]) 4931 4932(define_insn "difficult_rvbranch" 4933 [(set (pc) 4934 (if_then_else (match_operator 1 "difficult_comparison_operator" 4935 [(cc0) 4936 (const_int 0)]) 4937 (pc) 4938 (label_ref (match_operand 0 "" ""))))] 4939 "" 4940 { 4941 return ret_cond_branch (operands[1], avr_jump_mode (operands[0], insn), 1); 4942 } 4943 [(set_attr "type" "branch") 4944 (set_attr "cc" "clobber")]) 4945 4946;; ************************************************************************** 4947;; Unconditional and other jump instructions. 4948 4949(define_insn "jump" 4950 [(set (pc) 4951 (label_ref (match_operand 0 "" "")))] 4952 "" 4953 { 4954 return AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1 4955 ? "jmp %x0" 4956 : "rjmp %x0"; 4957 } 4958 [(set (attr "length") 4959 (if_then_else (match_operand 0 "symbol_ref_operand" "") 4960 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 4961 (const_int 1) 4962 (const_int 2)) 4963 (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047)) 4964 (le (minus (pc) (match_dup 0)) (const_int 2047))) 4965 (const_int 1) 4966 (const_int 2)))) 4967 (set_attr "cc" "none")]) 4968 4969;; call 4970 4971;; Operand 1 not used on the AVR. 4972;; Operand 2 is 1 for tail-call, 0 otherwise. 4973(define_expand "call" 4974 [(parallel[(call (match_operand:HI 0 "call_insn_operand" "") 4975 (match_operand:HI 1 "general_operand" "")) 4976 (use (const_int 0))])]) 4977 4978;; Operand 1 not used on the AVR. 4979;; Operand 2 is 1 for tail-call, 0 otherwise. 4980(define_expand "sibcall" 4981 [(parallel[(call (match_operand:HI 0 "call_insn_operand" "") 4982 (match_operand:HI 1 "general_operand" "")) 4983 (use (const_int 1))])]) 4984 4985;; call value 4986 4987;; Operand 2 not used on the AVR. 4988;; Operand 3 is 1 for tail-call, 0 otherwise. 4989(define_expand "call_value" 4990 [(parallel[(set (match_operand 0 "register_operand" "") 4991 (call (match_operand:HI 1 "call_insn_operand" "") 4992 (match_operand:HI 2 "general_operand" ""))) 4993 (use (const_int 0))])]) 4994 4995;; Operand 2 not used on the AVR. 4996;; Operand 3 is 1 for tail-call, 0 otherwise. 4997(define_expand "sibcall_value" 4998 [(parallel[(set (match_operand 0 "register_operand" "") 4999 (call (match_operand:HI 1 "call_insn_operand" "") 5000 (match_operand:HI 2 "general_operand" ""))) 5001 (use (const_int 1))])]) 5002 5003(define_insn "call_insn" 5004 [(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s")) 5005 (match_operand:HI 1 "general_operand" "X,X,X,X")) 5006 (use (match_operand:HI 2 "const_int_operand" "L,L,P,P"))])] 5007 ;; Operand 1 not used on the AVR. 5008 ;; Operand 2 is 1 for tail-call, 0 otherwise. 5009 "" 5010 "@ 5011 %!icall 5012 %~call %x0 5013 %!ijmp 5014 %~jmp %x0" 5015 [(set_attr "cc" "clobber") 5016 (set_attr "length" "1,*,1,*") 5017 (set_attr "adjust_len" "*,call,*,call")]) 5018 5019(define_insn "call_value_insn" 5020 [(parallel[(set (match_operand 0 "register_operand" "=r,r,r,r") 5021 (call (mem:HI (match_operand:HI 1 "nonmemory_operand" "z,s,z,s")) 5022 (match_operand:HI 2 "general_operand" "X,X,X,X"))) 5023 (use (match_operand:HI 3 "const_int_operand" "L,L,P,P"))])] 5024 ;; Operand 2 not used on the AVR. 5025 ;; Operand 3 is 1 for tail-call, 0 otherwise. 5026 "" 5027 "@ 5028 %!icall 5029 %~call %x1 5030 %!ijmp 5031 %~jmp %x1" 5032 [(set_attr "cc" "clobber") 5033 (set_attr "length" "1,*,1,*") 5034 (set_attr "adjust_len" "*,call,*,call")]) 5035 5036(define_insn "nop" 5037 [(const_int 0)] 5038 "" 5039 "nop" 5040 [(set_attr "cc" "none") 5041 (set_attr "length" "1")]) 5042 5043; indirect jump 5044 5045(define_expand "indirect_jump" 5046 [(set (pc) 5047 (match_operand:HI 0 "nonmemory_operand" ""))] 5048 "" 5049 { 5050 if (!AVR_HAVE_JMP_CALL && !register_operand (operands[0], HImode)) 5051 { 5052 operands[0] = copy_to_mode_reg (HImode, operands[0]); 5053 } 5054 }) 5055 5056; indirect jump 5057(define_insn "*indirect_jump" 5058 [(set (pc) 5059 (match_operand:HI 0 "nonmemory_operand" "i,i,!z,*r,z"))] 5060 "" 5061 "@ 5062 rjmp %x0 5063 jmp %x0 5064 ijmp 5065 push %A0\;push %B0\;ret 5066 eijmp" 5067 [(set_attr "length" "1,2,1,3,1") 5068 (set_attr "isa" "rjmp,jmp,ijmp,ijmp,eijmp") 5069 (set_attr "cc" "none")]) 5070 5071;; table jump 5072;; For entries in jump table see avr_output_addr_vec_elt. 5073 5074;; Table made from 5075;; "rjmp .L<n>" instructions for <= 8K devices 5076;; ".word gs(.L<n>)" addresses for > 8K devices 5077(define_insn "*tablejump" 5078 [(set (pc) 5079 (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")] 5080 UNSPEC_INDEX_JMP)) 5081 (use (label_ref (match_operand 1 "" ""))) 5082 (clobber (match_dup 0)) 5083 (clobber (const_int 0))] 5084 "!AVR_HAVE_EIJMP_EICALL" 5085 "@ 5086 ijmp 5087 push %A0\;push %B0\;ret 5088 jmp __tablejump2__" 5089 [(set_attr "length" "1,3,2") 5090 (set_attr "isa" "rjmp,rjmp,jmp") 5091 (set_attr "cc" "none,none,clobber")]) 5092 5093(define_insn "*tablejump.3byte-pc" 5094 [(set (pc) 5095 (unspec:HI [(reg:HI REG_Z)] 5096 UNSPEC_INDEX_JMP)) 5097 (use (label_ref (match_operand 0 "" ""))) 5098 (clobber (reg:HI REG_Z)) 5099 (clobber (reg:QI 24))] 5100 "AVR_HAVE_EIJMP_EICALL" 5101 "clr r24\;subi r30,pm_lo8(-(%0))\;sbci r31,pm_hi8(-(%0))\;sbci r24,pm_hh8(-(%0))\;jmp __tablejump2__" 5102 [(set_attr "length" "6") 5103 (set_attr "isa" "eijmp") 5104 (set_attr "cc" "clobber")]) 5105 5106 5107(define_expand "casesi" 5108 [(parallel [(set (match_dup 6) 5109 (minus:HI (subreg:HI (match_operand:SI 0 "register_operand" "") 0) 5110 (match_operand:HI 1 "register_operand" ""))) 5111 (clobber (scratch:QI))]) 5112 (parallel [(set (cc0) 5113 (compare (match_dup 6) 5114 (match_operand:HI 2 "register_operand" ""))) 5115 (clobber (match_scratch:QI 9 ""))]) 5116 5117 (set (pc) 5118 (if_then_else (gtu (cc0) 5119 (const_int 0)) 5120 (label_ref (match_operand 4 "" "")) 5121 (pc))) 5122 5123 (set (match_dup 10) 5124 (match_dup 7)) 5125 5126 (parallel [(set (pc) 5127 (unspec:HI [(match_dup 10)] UNSPEC_INDEX_JMP)) 5128 (use (label_ref (match_dup 3))) 5129 (clobber (match_dup 10)) 5130 (clobber (match_dup 8))])] 5131 "" 5132 { 5133 operands[6] = gen_reg_rtx (HImode); 5134 5135 if (AVR_HAVE_EIJMP_EICALL) 5136 { 5137 operands[7] = operands[6]; 5138 operands[8] = all_regs_rtx[24]; 5139 operands[10] = gen_rtx_REG (HImode, REG_Z); 5140 } 5141 else 5142 { 5143 operands[7] = gen_rtx_PLUS (HImode, operands[6], 5144 gen_rtx_LABEL_REF (VOIDmode, operands[3])); 5145 operands[8] = const0_rtx; 5146 operands[10] = operands[6]; 5147 } 5148 }) 5149 5150 5151;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 5152;; This instruction sets Z flag 5153 5154(define_insn "sez" 5155 [(set (cc0) (const_int 0))] 5156 "" 5157 "sez" 5158 [(set_attr "length" "1") 5159 (set_attr "cc" "compare")]) 5160 5161;; Clear/set/test a single bit in I/O address space. 5162 5163(define_insn "*cbi" 5164 [(set (mem:QI (match_operand 0 "low_io_address_operand" "i")) 5165 (and:QI (mem:QI (match_dup 0)) 5166 (match_operand:QI 1 "single_zero_operand" "n")))] 5167 "" 5168 { 5169 operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff)); 5170 return "cbi %i0,%2"; 5171 } 5172 [(set_attr "length" "1") 5173 (set_attr "cc" "none")]) 5174 5175(define_insn "*sbi" 5176 [(set (mem:QI (match_operand 0 "low_io_address_operand" "i")) 5177 (ior:QI (mem:QI (match_dup 0)) 5178 (match_operand:QI 1 "single_one_operand" "n")))] 5179 "" 5180 { 5181 operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff)); 5182 return "sbi %i0,%2"; 5183 } 5184 [(set_attr "length" "1") 5185 (set_attr "cc" "none")]) 5186 5187;; Lower half of the I/O space - use sbic/sbis directly. 5188(define_insn "*sbix_branch" 5189 [(set (pc) 5190 (if_then_else 5191 (match_operator 0 "eqne_operator" 5192 [(zero_extract:QIHI 5193 (mem:QI (match_operand 1 "low_io_address_operand" "i")) 5194 (const_int 1) 5195 (match_operand 2 "const_int_operand" "n")) 5196 (const_int 0)]) 5197 (label_ref (match_operand 3 "" "")) 5198 (pc)))] 5199 "" 5200 { 5201 return avr_out_sbxx_branch (insn, operands); 5202 } 5203 [(set (attr "length") 5204 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) 5205 (le (minus (pc) (match_dup 3)) (const_int 2046))) 5206 (const_int 2) 5207 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 5208 (const_int 2) 5209 (const_int 4)))) 5210 (set_attr "cc" "clobber")]) 5211 5212;; Tests of bit 7 are pessimized to sign tests, so we need this too... 5213(define_insn "*sbix_branch_bit7" 5214 [(set (pc) 5215 (if_then_else 5216 (match_operator 0 "gelt_operator" 5217 [(mem:QI (match_operand 1 "low_io_address_operand" "i")) 5218 (const_int 0)]) 5219 (label_ref (match_operand 2 "" "")) 5220 (pc)))] 5221 "" 5222 { 5223 operands[3] = operands[2]; 5224 operands[2] = GEN_INT (7); 5225 return avr_out_sbxx_branch (insn, operands); 5226 } 5227 [(set (attr "length") 5228 (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046)) 5229 (le (minus (pc) (match_dup 2)) (const_int 2046))) 5230 (const_int 2) 5231 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 5232 (const_int 2) 5233 (const_int 4)))) 5234 (set_attr "cc" "clobber")]) 5235 5236;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs. 5237(define_insn "*sbix_branch_tmp" 5238 [(set (pc) 5239 (if_then_else 5240 (match_operator 0 "eqne_operator" 5241 [(zero_extract:QIHI 5242 (mem:QI (match_operand 1 "high_io_address_operand" "n")) 5243 (const_int 1) 5244 (match_operand 2 "const_int_operand" "n")) 5245 (const_int 0)]) 5246 (label_ref (match_operand 3 "" "")) 5247 (pc)))] 5248 "" 5249 { 5250 return avr_out_sbxx_branch (insn, operands); 5251 } 5252 [(set (attr "length") 5253 (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) 5254 (le (minus (pc) (match_dup 3)) (const_int 2045))) 5255 (const_int 3) 5256 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 5257 (const_int 3) 5258 (const_int 5)))) 5259 (set_attr "cc" "clobber")]) 5260 5261(define_insn "*sbix_branch_tmp_bit7" 5262 [(set (pc) 5263 (if_then_else 5264 (match_operator 0 "gelt_operator" 5265 [(mem:QI (match_operand 1 "high_io_address_operand" "n")) 5266 (const_int 0)]) 5267 (label_ref (match_operand 2 "" "")) 5268 (pc)))] 5269 "" 5270 { 5271 operands[3] = operands[2]; 5272 operands[2] = GEN_INT (7); 5273 return avr_out_sbxx_branch (insn, operands); 5274 } 5275 [(set (attr "length") 5276 (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046)) 5277 (le (minus (pc) (match_dup 2)) (const_int 2045))) 5278 (const_int 3) 5279 (if_then_else (match_test "!AVR_HAVE_JMP_CALL") 5280 (const_int 3) 5281 (const_int 5)))) 5282 (set_attr "cc" "clobber")]) 5283 5284;; ************************* Peepholes ******************************** 5285 5286(define_peephole ; "*dec-and-branchsi!=-1.d.clobber" 5287 [(parallel [(set (match_operand:SI 0 "d_register_operand" "") 5288 (plus:SI (match_dup 0) 5289 (const_int -1))) 5290 (clobber (scratch:QI))]) 5291 (parallel [(set (cc0) 5292 (compare (match_dup 0) 5293 (const_int -1))) 5294 (clobber (match_operand:QI 1 "d_register_operand" ""))]) 5295 (set (pc) 5296 (if_then_else (eqne (cc0) 5297 (const_int 0)) 5298 (label_ref (match_operand 2 "" "")) 5299 (pc)))] 5300 "" 5301 { 5302 const char *op; 5303 int jump_mode; 5304 CC_STATUS_INIT; 5305 if (test_hard_reg_class (ADDW_REGS, operands[0])) 5306 output_asm_insn ("sbiw %0,1" CR_TAB 5307 "sbc %C0,__zero_reg__" CR_TAB 5308 "sbc %D0,__zero_reg__", operands); 5309 else 5310 output_asm_insn ("subi %A0,1" CR_TAB 5311 "sbc %B0,__zero_reg__" CR_TAB 5312 "sbc %C0,__zero_reg__" CR_TAB 5313 "sbc %D0,__zero_reg__", operands); 5314 5315 jump_mode = avr_jump_mode (operands[2], insn); 5316 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs"; 5317 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op); 5318 5319 switch (jump_mode) 5320 { 5321 case 1: return "%1 %2"; 5322 case 2: return "%1 .+2\;rjmp %2"; 5323 case 3: return "%1 .+4\;jmp %2"; 5324 } 5325 5326 gcc_unreachable(); 5327 return ""; 5328 }) 5329 5330(define_peephole ; "*dec-and-branchhi!=-1" 5331 [(set (match_operand:HI 0 "d_register_operand" "") 5332 (plus:HI (match_dup 0) 5333 (const_int -1))) 5334 (parallel [(set (cc0) 5335 (compare (match_dup 0) 5336 (const_int -1))) 5337 (clobber (match_operand:QI 1 "d_register_operand" ""))]) 5338 (set (pc) 5339 (if_then_else (eqne (cc0) 5340 (const_int 0)) 5341 (label_ref (match_operand 2 "" "")) 5342 (pc)))] 5343 "" 5344 { 5345 const char *op; 5346 int jump_mode; 5347 CC_STATUS_INIT; 5348 if (test_hard_reg_class (ADDW_REGS, operands[0])) 5349 output_asm_insn ("sbiw %0,1", operands); 5350 else 5351 output_asm_insn ("subi %A0,1" CR_TAB 5352 "sbc %B0,__zero_reg__", operands); 5353 5354 jump_mode = avr_jump_mode (operands[2], insn); 5355 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs"; 5356 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op); 5357 5358 switch (jump_mode) 5359 { 5360 case 1: return "%1 %2"; 5361 case 2: return "%1 .+2\;rjmp %2"; 5362 case 3: return "%1 .+4\;jmp %2"; 5363 } 5364 5365 gcc_unreachable(); 5366 return ""; 5367 }) 5368 5369;; Same as above but with clobber flavour of addhi3 5370(define_peephole ; "*dec-and-branchhi!=-1.d.clobber" 5371 [(parallel [(set (match_operand:HI 0 "d_register_operand" "") 5372 (plus:HI (match_dup 0) 5373 (const_int -1))) 5374 (clobber (scratch:QI))]) 5375 (parallel [(set (cc0) 5376 (compare (match_dup 0) 5377 (const_int -1))) 5378 (clobber (match_operand:QI 1 "d_register_operand" ""))]) 5379 (set (pc) 5380 (if_then_else (eqne (cc0) 5381 (const_int 0)) 5382 (label_ref (match_operand 2 "" "")) 5383 (pc)))] 5384 "" 5385 { 5386 const char *op; 5387 int jump_mode; 5388 CC_STATUS_INIT; 5389 if (test_hard_reg_class (ADDW_REGS, operands[0])) 5390 output_asm_insn ("sbiw %0,1", operands); 5391 else 5392 output_asm_insn ("subi %A0,1" CR_TAB 5393 "sbc %B0,__zero_reg__", operands); 5394 5395 jump_mode = avr_jump_mode (operands[2], insn); 5396 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs"; 5397 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op); 5398 5399 switch (jump_mode) 5400 { 5401 case 1: return "%1 %2"; 5402 case 2: return "%1 .+2\;rjmp %2"; 5403 case 3: return "%1 .+4\;jmp %2"; 5404 } 5405 5406 gcc_unreachable(); 5407 return ""; 5408 }) 5409 5410;; Same as above but with clobber flavour of addhi3 5411(define_peephole ; "*dec-and-branchhi!=-1.l.clobber" 5412 [(parallel [(set (match_operand:HI 0 "l_register_operand" "") 5413 (plus:HI (match_dup 0) 5414 (const_int -1))) 5415 (clobber (match_operand:QI 3 "d_register_operand" ""))]) 5416 (parallel [(set (cc0) 5417 (compare (match_dup 0) 5418 (const_int -1))) 5419 (clobber (match_operand:QI 1 "d_register_operand" ""))]) 5420 (set (pc) 5421 (if_then_else (eqne (cc0) 5422 (const_int 0)) 5423 (label_ref (match_operand 2 "" "")) 5424 (pc)))] 5425 "" 5426 { 5427 const char *op; 5428 int jump_mode; 5429 CC_STATUS_INIT; 5430 output_asm_insn ("ldi %3,1" CR_TAB 5431 "sub %A0,%3" CR_TAB 5432 "sbc %B0,__zero_reg__", operands); 5433 5434 jump_mode = avr_jump_mode (operands[2], insn); 5435 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs"; 5436 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op); 5437 5438 switch (jump_mode) 5439 { 5440 case 1: return "%1 %2"; 5441 case 2: return "%1 .+2\;rjmp %2"; 5442 case 3: return "%1 .+4\;jmp %2"; 5443 } 5444 5445 gcc_unreachable(); 5446 return ""; 5447 }) 5448 5449(define_peephole ; "*dec-and-branchqi!=-1" 5450 [(set (match_operand:QI 0 "d_register_operand" "") 5451 (plus:QI (match_dup 0) 5452 (const_int -1))) 5453 (set (cc0) 5454 (compare (match_dup 0) 5455 (const_int -1))) 5456 (set (pc) 5457 (if_then_else (eqne (cc0) 5458 (const_int 0)) 5459 (label_ref (match_operand 1 "" "")) 5460 (pc)))] 5461 "" 5462 { 5463 const char *op; 5464 int jump_mode; 5465 CC_STATUS_INIT; 5466 cc_status.value1 = operands[0]; 5467 cc_status.flags |= CC_OVERFLOW_UNUSABLE; 5468 5469 output_asm_insn ("subi %A0,1", operands); 5470 5471 jump_mode = avr_jump_mode (operands[1], insn); 5472 op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs"; 5473 operands[0] = gen_rtx_CONST_STRING (VOIDmode, op); 5474 5475 switch (jump_mode) 5476 { 5477 case 1: return "%0 %1"; 5478 case 2: return "%0 .+2\;rjmp %1"; 5479 case 3: return "%0 .+4\;jmp %1"; 5480 } 5481 5482 gcc_unreachable(); 5483 return ""; 5484 }) 5485 5486 5487(define_peephole ; "*cpse.eq" 5488 [(set (cc0) 5489 (compare (match_operand:ALL1 1 "register_operand" "r,r") 5490 (match_operand:ALL1 2 "reg_or_0_operand" "r,Y00"))) 5491 (set (pc) 5492 (if_then_else (eq (cc0) 5493 (const_int 0)) 5494 (label_ref (match_operand 0 "" "")) 5495 (pc)))] 5496 "jump_over_one_insn_p (insn, operands[0])" 5497 "@ 5498 cpse %1,%2 5499 cpse %1,__zero_reg__") 5500 5501;; This peephole avoids code like 5502;; 5503;; TST Rn ; *cmpqi 5504;; BREQ .+2 ; branch 5505;; RJMP .Lm 5506;; 5507;; Notice that the peephole is always shorter than cmpqi + branch. 5508;; The reason to write it as peephole is that sequences like 5509;; 5510;; AND Rm, Rn 5511;; BRNE .La 5512;; 5513;; shall not be superseeded. With a respective combine pattern 5514;; the latter sequence would be 5515;; 5516;; AND Rm, Rn 5517;; CPSE Rm, __zero_reg__ 5518;; RJMP .La 5519;; 5520;; and thus longer and slower and not easy to be rolled back. 5521 5522(define_peephole ; "*cpse.ne" 5523 [(set (cc0) 5524 (compare (match_operand:ALL1 1 "register_operand" "") 5525 (match_operand:ALL1 2 "reg_or_0_operand" ""))) 5526 (set (pc) 5527 (if_then_else (ne (cc0) 5528 (const_int 0)) 5529 (label_ref (match_operand 0 "" "")) 5530 (pc)))] 5531 "!AVR_HAVE_JMP_CALL 5532 || !TARGET_SKIP_BUG" 5533 { 5534 if (operands[2] == CONST0_RTX (<MODE>mode)) 5535 operands[2] = zero_reg_rtx; 5536 5537 return 3 == avr_jump_mode (operands[0], insn) 5538 ? "cpse %1,%2\;jmp %0" 5539 : "cpse %1,%2\;rjmp %0"; 5540 }) 5541 5542;;pppppppppppppppppppppppppppppppppppppppppppppppppppp 5543;;prologue/epilogue support instructions 5544 5545(define_insn "popqi" 5546 [(set (match_operand:QI 0 "register_operand" "=r") 5547 (mem:QI (pre_inc:HI (reg:HI REG_SP))))] 5548 "" 5549 "pop %0" 5550 [(set_attr "cc" "none") 5551 (set_attr "length" "1")]) 5552 5553;; Enable Interrupts 5554(define_expand "enable_interrupt" 5555 [(clobber (const_int 0))] 5556 "" 5557 { 5558 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 5559 MEM_VOLATILE_P (mem) = 1; 5560 emit_insn (gen_cli_sei (const1_rtx, mem)); 5561 DONE; 5562 }) 5563 5564;; Disable Interrupts 5565(define_expand "disable_interrupt" 5566 [(clobber (const_int 0))] 5567 "" 5568 { 5569 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 5570 MEM_VOLATILE_P (mem) = 1; 5571 emit_insn (gen_cli_sei (const0_rtx, mem)); 5572 DONE; 5573 }) 5574 5575(define_insn "cli_sei" 5576 [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "L,P")] 5577 UNSPECV_ENABLE_IRQS) 5578 (set (match_operand:BLK 1 "" "") 5579 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))] 5580 "" 5581 "@ 5582 cli 5583 sei" 5584 [(set_attr "length" "1") 5585 (set_attr "cc" "none")]) 5586 5587;; Library prologue saves 5588(define_insn "call_prologue_saves" 5589 [(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES) 5590 (match_operand:HI 0 "immediate_operand" "i,i") 5591 (set (reg:HI REG_SP) 5592 (minus:HI (reg:HI REG_SP) 5593 (match_operand:HI 1 "immediate_operand" "i,i"))) 5594 (use (reg:HI REG_X)) 5595 (clobber (reg:HI REG_Z))] 5596 "" 5597 "ldi r30,lo8(gs(1f)) 5598 ldi r31,hi8(gs(1f)) 5599 %~jmp __prologue_saves__+((18 - %0) * 2) 56001:" 5601 [(set_attr "length" "5,6") 5602 (set_attr "cc" "clobber") 5603 (set_attr "isa" "rjmp,jmp")]) 5604 5605; epilogue restores using library 5606(define_insn "epilogue_restores" 5607 [(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES) 5608 (set (reg:HI REG_Y) 5609 (plus:HI (reg:HI REG_Y) 5610 (match_operand:HI 0 "immediate_operand" "i,i"))) 5611 (set (reg:HI REG_SP) 5612 (plus:HI (reg:HI REG_Y) 5613 (match_dup 0))) 5614 (clobber (reg:QI REG_Z))] 5615 "" 5616 "ldi r30, lo8(%0) 5617 %~jmp __epilogue_restores__ + ((18 - %0) * 2)" 5618 [(set_attr "length" "2,3") 5619 (set_attr "cc" "clobber") 5620 (set_attr "isa" "rjmp,jmp")]) 5621 5622; return 5623(define_insn "return" 5624 [(return)] 5625 "reload_completed && avr_simple_epilogue ()" 5626 "ret" 5627 [(set_attr "cc" "none") 5628 (set_attr "length" "1")]) 5629 5630(define_insn "return_from_epilogue" 5631 [(return)] 5632 "reload_completed 5633 && cfun->machine 5634 && !(cfun->machine->is_interrupt || cfun->machine->is_signal) 5635 && !cfun->machine->is_naked" 5636 "ret" 5637 [(set_attr "cc" "none") 5638 (set_attr "length" "1")]) 5639 5640(define_insn "return_from_interrupt_epilogue" 5641 [(return)] 5642 "reload_completed 5643 && cfun->machine 5644 && (cfun->machine->is_interrupt || cfun->machine->is_signal) 5645 && !cfun->machine->is_naked" 5646 "reti" 5647 [(set_attr "cc" "none") 5648 (set_attr "length" "1")]) 5649 5650(define_insn "return_from_naked_epilogue" 5651 [(return)] 5652 "reload_completed 5653 && cfun->machine 5654 && cfun->machine->is_naked" 5655 "" 5656 [(set_attr "cc" "none") 5657 (set_attr "length" "0")]) 5658 5659(define_expand "prologue" 5660 [(const_int 0)] 5661 "" 5662 { 5663 avr_expand_prologue (); 5664 DONE; 5665 }) 5666 5667(define_expand "epilogue" 5668 [(const_int 0)] 5669 "" 5670 { 5671 avr_expand_epilogue (false /* sibcall_p */); 5672 DONE; 5673 }) 5674 5675(define_expand "sibcall_epilogue" 5676 [(const_int 0)] 5677 "" 5678 { 5679 avr_expand_epilogue (true /* sibcall_p */); 5680 DONE; 5681 }) 5682 5683;; Some instructions resp. instruction sequences available 5684;; via builtins. 5685 5686(define_insn "delay_cycles_1" 5687 [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n") 5688 (const_int 1)] 5689 UNSPECV_DELAY_CYCLES) 5690 (set (match_operand:BLK 1 "" "") 5691 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER)) 5692 (clobber (match_scratch:QI 2 "=&d"))] 5693 "" 5694 "ldi %2,lo8(%0) 56951: dec %2 5696 brne 1b" 5697 [(set_attr "length" "3") 5698 (set_attr "cc" "clobber")]) 5699 5700(define_insn "delay_cycles_2" 5701 [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n,n") 5702 (const_int 2)] 5703 UNSPECV_DELAY_CYCLES) 5704 (set (match_operand:BLK 1 "" "") 5705 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER)) 5706 (clobber (match_scratch:HI 2 "=&w,&d"))] 5707 "" 5708 "@ 5709 ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\n1: sbiw %A2,1\;brne 1b 5710 ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\n1: subi %A2,1\;sbci %B2,0\;brne 1b" 5711 [(set_attr "length" "4,5") 5712 (set_attr "isa" "no_tiny,tiny") 5713 (set_attr "cc" "clobber")]) 5714 5715(define_insn "delay_cycles_3" 5716 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n") 5717 (const_int 3)] 5718 UNSPECV_DELAY_CYCLES) 5719 (set (match_operand:BLK 1 "" "") 5720 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER)) 5721 (clobber (match_scratch:QI 2 "=&d")) 5722 (clobber (match_scratch:QI 3 "=&d")) 5723 (clobber (match_scratch:QI 4 "=&d"))] 5724 "" 5725 "ldi %2,lo8(%0) 5726 ldi %3,hi8(%0) 5727 ldi %4,hlo8(%0) 57281: subi %2,1 5729 sbci %3,0 5730 sbci %4,0 5731 brne 1b" 5732 [(set_attr "length" "7") 5733 (set_attr "cc" "clobber")]) 5734 5735(define_insn "delay_cycles_4" 5736 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n") 5737 (const_int 4)] 5738 UNSPECV_DELAY_CYCLES) 5739 (set (match_operand:BLK 1 "" "") 5740 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER)) 5741 (clobber (match_scratch:QI 2 "=&d")) 5742 (clobber (match_scratch:QI 3 "=&d")) 5743 (clobber (match_scratch:QI 4 "=&d")) 5744 (clobber (match_scratch:QI 5 "=&d"))] 5745 "" 5746 "ldi %2,lo8(%0) 5747 ldi %3,hi8(%0) 5748 ldi %4,hlo8(%0) 5749 ldi %5,hhi8(%0) 57501: subi %2,1 5751 sbci %3,0 5752 sbci %4,0 5753 sbci %5,0 5754 brne 1b" 5755 [(set_attr "length" "9") 5756 (set_attr "cc" "clobber")]) 5757 5758 5759;; __builtin_avr_insert_bits 5760 5761(define_insn "insert_bits" 5762 [(set (match_operand:QI 0 "register_operand" "=r ,d ,r") 5763 (unspec:QI [(match_operand:SI 1 "const_int_operand" "C0f,Cxf,C0f") 5764 (match_operand:QI 2 "register_operand" "r ,r ,r") 5765 (match_operand:QI 3 "nonmemory_operand" "n ,0 ,0")] 5766 UNSPEC_INSERT_BITS))] 5767 "" 5768 { 5769 return avr_out_insert_bits (operands, NULL); 5770 } 5771 [(set_attr "adjust_len" "insert_bits") 5772 (set_attr "cc" "clobber")]) 5773 5774 5775;; __builtin_avr_flash_segment 5776 5777;; Just a helper for the next "official" expander. 5778 5779(define_expand "flash_segment1" 5780 [(set (match_operand:QI 0 "register_operand" "") 5781 (subreg:QI (match_operand:PSI 1 "register_operand" "") 5782 2)) 5783 (set (cc0) 5784 (compare (match_dup 0) 5785 (const_int 0))) 5786 (set (pc) 5787 (if_then_else (ge (cc0) 5788 (const_int 0)) 5789 (label_ref (match_operand 2 "" "")) 5790 (pc))) 5791 (set (match_dup 0) 5792 (const_int -1))]) 5793 5794(define_expand "flash_segment" 5795 [(parallel [(match_operand:QI 0 "register_operand" "") 5796 (match_operand:PSI 1 "register_operand" "")])] 5797 "" 5798 { 5799 rtx label = gen_label_rtx (); 5800 emit (gen_flash_segment1 (operands[0], operands[1], label)); 5801 emit_label (label); 5802 DONE; 5803 }) 5804 5805;; Actually, it's too late now to work out address spaces known at compiletime. 5806;; Best place would be to fold ADDR_SPACE_CONVERT_EXPR in avr_fold_builtin. 5807;; However, avr_addr_space_convert can add some built-in knowledge for PSTR 5808;; so that ADDR_SPACE_CONVERT_EXPR in the built-in must not be resolved. 5809 5810(define_insn_and_split "*split.flash_segment" 5811 [(set (match_operand:QI 0 "register_operand" "=d") 5812 (subreg:QI (lo_sum:PSI (match_operand:QI 1 "nonmemory_operand" "ri") 5813 (match_operand:HI 2 "register_operand" "r")) 5814 2))] 5815 "" 5816 { gcc_unreachable(); } 5817 "" 5818 [(set (match_dup 0) 5819 (match_dup 1))]) 5820 5821 5822;; Parity 5823 5824;; Postpone expansion of 16-bit parity to libgcc call until after combine for 5825;; better 8-bit parity recognition. 5826 5827(define_expand "parityhi2" 5828 [(parallel [(set (match_operand:HI 0 "register_operand" "") 5829 (parity:HI (match_operand:HI 1 "register_operand" ""))) 5830 (clobber (reg:HI 24))])]) 5831 5832(define_insn_and_split "*parityhi2" 5833 [(set (match_operand:HI 0 "register_operand" "=r") 5834 (parity:HI (match_operand:HI 1 "register_operand" "r"))) 5835 (clobber (reg:HI 24))] 5836 "!reload_completed" 5837 { gcc_unreachable(); } 5838 "&& 1" 5839 [(set (reg:HI 24) 5840 (match_dup 1)) 5841 (set (reg:HI 24) 5842 (parity:HI (reg:HI 24))) 5843 (set (match_dup 0) 5844 (reg:HI 24))]) 5845 5846(define_insn_and_split "*parityqihi2" 5847 [(set (match_operand:HI 0 "register_operand" "=r") 5848 (parity:HI (match_operand:QI 1 "register_operand" "r"))) 5849 (clobber (reg:HI 24))] 5850 "!reload_completed" 5851 { gcc_unreachable(); } 5852 "&& 1" 5853 [(set (reg:QI 24) 5854 (match_dup 1)) 5855 (set (reg:HI 24) 5856 (zero_extend:HI (parity:QI (reg:QI 24)))) 5857 (set (match_dup 0) 5858 (reg:HI 24))]) 5859 5860(define_expand "paritysi2" 5861 [(set (reg:SI 22) 5862 (match_operand:SI 1 "register_operand" "")) 5863 (set (reg:HI 24) 5864 (truncate:HI (parity:SI (reg:SI 22)))) 5865 (set (match_dup 2) 5866 (reg:HI 24)) 5867 (set (match_operand:SI 0 "register_operand" "") 5868 (zero_extend:SI (match_dup 2)))] 5869 "" 5870 { 5871 operands[2] = gen_reg_rtx (HImode); 5872 }) 5873 5874(define_insn "*parityhi2.libgcc" 5875 [(set (reg:HI 24) 5876 (parity:HI (reg:HI 24)))] 5877 "" 5878 "%~call __parityhi2" 5879 [(set_attr "type" "xcall") 5880 (set_attr "cc" "clobber")]) 5881 5882(define_insn "*parityqihi2.libgcc" 5883 [(set (reg:HI 24) 5884 (zero_extend:HI (parity:QI (reg:QI 24))))] 5885 "" 5886 "%~call __parityqi2" 5887 [(set_attr "type" "xcall") 5888 (set_attr "cc" "clobber")]) 5889 5890(define_insn "*paritysihi2.libgcc" 5891 [(set (reg:HI 24) 5892 (truncate:HI (parity:SI (reg:SI 22))))] 5893 "" 5894 "%~call __paritysi2" 5895 [(set_attr "type" "xcall") 5896 (set_attr "cc" "clobber")]) 5897 5898 5899;; Popcount 5900 5901(define_expand "popcounthi2" 5902 [(set (reg:HI 24) 5903 (match_operand:HI 1 "register_operand" "")) 5904 (set (reg:HI 24) 5905 (popcount:HI (reg:HI 24))) 5906 (set (match_operand:HI 0 "register_operand" "") 5907 (reg:HI 24))] 5908 "" 5909 "") 5910 5911(define_expand "popcountsi2" 5912 [(set (reg:SI 22) 5913 (match_operand:SI 1 "register_operand" "")) 5914 (set (reg:HI 24) 5915 (truncate:HI (popcount:SI (reg:SI 22)))) 5916 (set (match_dup 2) 5917 (reg:HI 24)) 5918 (set (match_operand:SI 0 "register_operand" "") 5919 (zero_extend:SI (match_dup 2)))] 5920 "" 5921 { 5922 operands[2] = gen_reg_rtx (HImode); 5923 }) 5924 5925(define_insn "*popcounthi2.libgcc" 5926 [(set (reg:HI 24) 5927 (popcount:HI (reg:HI 24)))] 5928 "" 5929 "%~call __popcounthi2" 5930 [(set_attr "type" "xcall") 5931 (set_attr "cc" "clobber")]) 5932 5933(define_insn "*popcountsi2.libgcc" 5934 [(set (reg:HI 24) 5935 (truncate:HI (popcount:SI (reg:SI 22))))] 5936 "" 5937 "%~call __popcountsi2" 5938 [(set_attr "type" "xcall") 5939 (set_attr "cc" "clobber")]) 5940 5941(define_insn "*popcountqi2.libgcc" 5942 [(set (reg:QI 24) 5943 (popcount:QI (reg:QI 24)))] 5944 "" 5945 "%~call __popcountqi2" 5946 [(set_attr "type" "xcall") 5947 (set_attr "cc" "clobber")]) 5948 5949(define_insn_and_split "*popcountqihi2.libgcc" 5950 [(set (reg:HI 24) 5951 (zero_extend:HI (popcount:QI (reg:QI 24))))] 5952 "" 5953 "#" 5954 "" 5955 [(set (reg:QI 24) 5956 (popcount:QI (reg:QI 24))) 5957 (set (reg:QI 25) 5958 (const_int 0))]) 5959 5960;; Count Leading Zeros 5961 5962(define_expand "clzhi2" 5963 [(set (reg:HI 24) 5964 (match_operand:HI 1 "register_operand" "")) 5965 (parallel [(set (reg:HI 24) 5966 (clz:HI (reg:HI 24))) 5967 (clobber (reg:QI 26))]) 5968 (set (match_operand:HI 0 "register_operand" "") 5969 (reg:HI 24))]) 5970 5971(define_expand "clzsi2" 5972 [(set (reg:SI 22) 5973 (match_operand:SI 1 "register_operand" "")) 5974 (parallel [(set (reg:HI 24) 5975 (truncate:HI (clz:SI (reg:SI 22)))) 5976 (clobber (reg:QI 26))]) 5977 (set (match_dup 2) 5978 (reg:HI 24)) 5979 (set (match_operand:SI 0 "register_operand" "") 5980 (zero_extend:SI (match_dup 2)))] 5981 "" 5982 { 5983 operands[2] = gen_reg_rtx (HImode); 5984 }) 5985 5986(define_insn "*clzhi2.libgcc" 5987 [(set (reg:HI 24) 5988 (clz:HI (reg:HI 24))) 5989 (clobber (reg:QI 26))] 5990 "" 5991 "%~call __clzhi2" 5992 [(set_attr "type" "xcall") 5993 (set_attr "cc" "clobber")]) 5994 5995(define_insn "*clzsihi2.libgcc" 5996 [(set (reg:HI 24) 5997 (truncate:HI (clz:SI (reg:SI 22)))) 5998 (clobber (reg:QI 26))] 5999 "" 6000 "%~call __clzsi2" 6001 [(set_attr "type" "xcall") 6002 (set_attr "cc" "clobber")]) 6003 6004;; Count Trailing Zeros 6005 6006(define_expand "ctzhi2" 6007 [(set (reg:HI 24) 6008 (match_operand:HI 1 "register_operand" "")) 6009 (parallel [(set (reg:HI 24) 6010 (ctz:HI (reg:HI 24))) 6011 (clobber (reg:QI 26))]) 6012 (set (match_operand:HI 0 "register_operand" "") 6013 (reg:HI 24))]) 6014 6015(define_expand "ctzsi2" 6016 [(set (reg:SI 22) 6017 (match_operand:SI 1 "register_operand" "")) 6018 (parallel [(set (reg:HI 24) 6019 (truncate:HI (ctz:SI (reg:SI 22)))) 6020 (clobber (reg:QI 22)) 6021 (clobber (reg:QI 26))]) 6022 (set (match_dup 2) 6023 (reg:HI 24)) 6024 (set (match_operand:SI 0 "register_operand" "") 6025 (zero_extend:SI (match_dup 2)))] 6026 "" 6027 { 6028 operands[2] = gen_reg_rtx (HImode); 6029 }) 6030 6031(define_insn "*ctzhi2.libgcc" 6032 [(set (reg:HI 24) 6033 (ctz:HI (reg:HI 24))) 6034 (clobber (reg:QI 26))] 6035 "" 6036 "%~call __ctzhi2" 6037 [(set_attr "type" "xcall") 6038 (set_attr "cc" "clobber")]) 6039 6040(define_insn "*ctzsihi2.libgcc" 6041 [(set (reg:HI 24) 6042 (truncate:HI (ctz:SI (reg:SI 22)))) 6043 (clobber (reg:QI 22)) 6044 (clobber (reg:QI 26))] 6045 "" 6046 "%~call __ctzsi2" 6047 [(set_attr "type" "xcall") 6048 (set_attr "cc" "clobber")]) 6049 6050;; Find First Set 6051 6052(define_expand "ffshi2" 6053 [(set (reg:HI 24) 6054 (match_operand:HI 1 "register_operand" "")) 6055 (parallel [(set (reg:HI 24) 6056 (ffs:HI (reg:HI 24))) 6057 (clobber (reg:QI 26))]) 6058 (set (match_operand:HI 0 "register_operand" "") 6059 (reg:HI 24))]) 6060 6061(define_expand "ffssi2" 6062 [(set (reg:SI 22) 6063 (match_operand:SI 1 "register_operand" "")) 6064 (parallel [(set (reg:HI 24) 6065 (truncate:HI (ffs:SI (reg:SI 22)))) 6066 (clobber (reg:QI 22)) 6067 (clobber (reg:QI 26))]) 6068 (set (match_dup 2) 6069 (reg:HI 24)) 6070 (set (match_operand:SI 0 "register_operand" "") 6071 (zero_extend:SI (match_dup 2)))] 6072 "" 6073 { 6074 operands[2] = gen_reg_rtx (HImode); 6075 }) 6076 6077(define_insn "*ffshi2.libgcc" 6078 [(set (reg:HI 24) 6079 (ffs:HI (reg:HI 24))) 6080 (clobber (reg:QI 26))] 6081 "" 6082 "%~call __ffshi2" 6083 [(set_attr "type" "xcall") 6084 (set_attr "cc" "clobber")]) 6085 6086(define_insn "*ffssihi2.libgcc" 6087 [(set (reg:HI 24) 6088 (truncate:HI (ffs:SI (reg:SI 22)))) 6089 (clobber (reg:QI 22)) 6090 (clobber (reg:QI 26))] 6091 "" 6092 "%~call __ffssi2" 6093 [(set_attr "type" "xcall") 6094 (set_attr "cc" "clobber")]) 6095 6096;; Copysign 6097 6098(define_insn "copysignsf3" 6099 [(set (match_operand:SF 0 "register_operand" "=r") 6100 (unspec:SF [(match_operand:SF 1 "register_operand" "0") 6101 (match_operand:SF 2 "register_operand" "r")] 6102 UNSPEC_COPYSIGN))] 6103 "" 6104 "bst %D2,7\;bld %D0,7" 6105 [(set_attr "length" "2") 6106 (set_attr "cc" "none")]) 6107 6108;; Swap Bytes (change byte-endianess) 6109 6110(define_expand "bswapsi2" 6111 [(set (reg:SI 22) 6112 (match_operand:SI 1 "register_operand" "")) 6113 (set (reg:SI 22) 6114 (bswap:SI (reg:SI 22))) 6115 (set (match_operand:SI 0 "register_operand" "") 6116 (reg:SI 22))]) 6117 6118(define_insn "*bswapsi2.libgcc" 6119 [(set (reg:SI 22) 6120 (bswap:SI (reg:SI 22)))] 6121 "" 6122 "%~call __bswapsi2" 6123 [(set_attr "type" "xcall") 6124 (set_attr "cc" "clobber")]) 6125 6126 6127;; CPU instructions 6128 6129;; NOP taking 1 or 2 Ticks 6130(define_expand "nopv" 6131 [(parallel [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "")] 6132 UNSPECV_NOP) 6133 (set (match_dup 1) 6134 (unspec_volatile:BLK [(match_dup 1)] 6135 UNSPECV_MEMORY_BARRIER))])] 6136 "" 6137 { 6138 operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 6139 MEM_VOLATILE_P (operands[1]) = 1; 6140 }) 6141 6142(define_insn "*nopv" 6143 [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "P,K")] 6144 UNSPECV_NOP) 6145 (set (match_operand:BLK 1 "" "") 6146 (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))] 6147 "" 6148 "@ 6149 nop 6150 rjmp ." 6151 [(set_attr "length" "1") 6152 (set_attr "cc" "none")]) 6153 6154;; SLEEP 6155(define_expand "sleep" 6156 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP) 6157 (set (match_dup 0) 6158 (unspec_volatile:BLK [(match_dup 0)] 6159 UNSPECV_MEMORY_BARRIER))])] 6160 "" 6161 { 6162 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 6163 MEM_VOLATILE_P (operands[0]) = 1; 6164 }) 6165 6166(define_insn "*sleep" 6167 [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP) 6168 (set (match_operand:BLK 0 "" "") 6169 (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))] 6170 "" 6171 "sleep" 6172 [(set_attr "length" "1") 6173 (set_attr "cc" "none")]) 6174 6175;; WDR 6176(define_expand "wdr" 6177 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_WDR) 6178 (set (match_dup 0) 6179 (unspec_volatile:BLK [(match_dup 0)] 6180 UNSPECV_MEMORY_BARRIER))])] 6181 "" 6182 { 6183 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 6184 MEM_VOLATILE_P (operands[0]) = 1; 6185 }) 6186 6187(define_insn "*wdr" 6188 [(unspec_volatile [(const_int 0)] UNSPECV_WDR) 6189 (set (match_operand:BLK 0 "" "") 6190 (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))] 6191 "" 6192 "wdr" 6193 [(set_attr "length" "1") 6194 (set_attr "cc" "none")]) 6195 6196;; FMUL 6197(define_expand "fmul" 6198 [(set (reg:QI 24) 6199 (match_operand:QI 1 "register_operand" "")) 6200 (set (reg:QI 25) 6201 (match_operand:QI 2 "register_operand" "")) 6202 (parallel [(set (reg:HI 22) 6203 (unspec:HI [(reg:QI 24) 6204 (reg:QI 25)] UNSPEC_FMUL)) 6205 (clobber (reg:HI 24))]) 6206 (set (match_operand:HI 0 "register_operand" "") 6207 (reg:HI 22))] 6208 "" 6209 { 6210 if (AVR_HAVE_MUL) 6211 { 6212 emit_insn (gen_fmul_insn (operand0, operand1, operand2)); 6213 DONE; 6214 } 6215 avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); 6216 }) 6217 6218(define_insn "fmul_insn" 6219 [(set (match_operand:HI 0 "register_operand" "=r") 6220 (unspec:HI [(match_operand:QI 1 "register_operand" "a") 6221 (match_operand:QI 2 "register_operand" "a")] 6222 UNSPEC_FMUL))] 6223 "AVR_HAVE_MUL" 6224 "fmul %1,%2 6225 movw %0,r0 6226 clr __zero_reg__" 6227 [(set_attr "length" "3") 6228 (set_attr "cc" "clobber")]) 6229 6230(define_insn "*fmul.call" 6231 [(set (reg:HI 22) 6232 (unspec:HI [(reg:QI 24) 6233 (reg:QI 25)] UNSPEC_FMUL)) 6234 (clobber (reg:HI 24))] 6235 "!AVR_HAVE_MUL" 6236 "%~call __fmul" 6237 [(set_attr "type" "xcall") 6238 (set_attr "cc" "clobber")]) 6239 6240;; FMULS 6241(define_expand "fmuls" 6242 [(set (reg:QI 24) 6243 (match_operand:QI 1 "register_operand" "")) 6244 (set (reg:QI 25) 6245 (match_operand:QI 2 "register_operand" "")) 6246 (parallel [(set (reg:HI 22) 6247 (unspec:HI [(reg:QI 24) 6248 (reg:QI 25)] UNSPEC_FMULS)) 6249 (clobber (reg:HI 24))]) 6250 (set (match_operand:HI 0 "register_operand" "") 6251 (reg:HI 22))] 6252 "" 6253 { 6254 if (AVR_HAVE_MUL) 6255 { 6256 emit_insn (gen_fmuls_insn (operand0, operand1, operand2)); 6257 DONE; 6258 } 6259 avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); 6260 }) 6261 6262(define_insn "fmuls_insn" 6263 [(set (match_operand:HI 0 "register_operand" "=r") 6264 (unspec:HI [(match_operand:QI 1 "register_operand" "a") 6265 (match_operand:QI 2 "register_operand" "a")] 6266 UNSPEC_FMULS))] 6267 "AVR_HAVE_MUL" 6268 "fmuls %1,%2 6269 movw %0,r0 6270 clr __zero_reg__" 6271 [(set_attr "length" "3") 6272 (set_attr "cc" "clobber")]) 6273 6274(define_insn "*fmuls.call" 6275 [(set (reg:HI 22) 6276 (unspec:HI [(reg:QI 24) 6277 (reg:QI 25)] UNSPEC_FMULS)) 6278 (clobber (reg:HI 24))] 6279 "!AVR_HAVE_MUL" 6280 "%~call __fmuls" 6281 [(set_attr "type" "xcall") 6282 (set_attr "cc" "clobber")]) 6283 6284;; FMULSU 6285(define_expand "fmulsu" 6286 [(set (reg:QI 24) 6287 (match_operand:QI 1 "register_operand" "")) 6288 (set (reg:QI 25) 6289 (match_operand:QI 2 "register_operand" "")) 6290 (parallel [(set (reg:HI 22) 6291 (unspec:HI [(reg:QI 24) 6292 (reg:QI 25)] UNSPEC_FMULSU)) 6293 (clobber (reg:HI 24))]) 6294 (set (match_operand:HI 0 "register_operand" "") 6295 (reg:HI 22))] 6296 "" 6297 { 6298 if (AVR_HAVE_MUL) 6299 { 6300 emit_insn (gen_fmulsu_insn (operand0, operand1, operand2)); 6301 DONE; 6302 } 6303 avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); 6304 }) 6305 6306(define_insn "fmulsu_insn" 6307 [(set (match_operand:HI 0 "register_operand" "=r") 6308 (unspec:HI [(match_operand:QI 1 "register_operand" "a") 6309 (match_operand:QI 2 "register_operand" "a")] 6310 UNSPEC_FMULSU))] 6311 "AVR_HAVE_MUL" 6312 "fmulsu %1,%2 6313 movw %0,r0 6314 clr __zero_reg__" 6315 [(set_attr "length" "3") 6316 (set_attr "cc" "clobber")]) 6317 6318(define_insn "*fmulsu.call" 6319 [(set (reg:HI 22) 6320 (unspec:HI [(reg:QI 24) 6321 (reg:QI 25)] UNSPEC_FMULSU)) 6322 (clobber (reg:HI 24))] 6323 "!AVR_HAVE_MUL" 6324 "%~call __fmulsu" 6325 [(set_attr "type" "xcall") 6326 (set_attr "cc" "clobber")]) 6327 6328 6329;; Some combiner patterns dealing with bits. 6330;; See PR42210 6331 6332;; Move bit $3.0 into bit $0.$4 6333(define_insn "*movbitqi.1-6.a" 6334 [(set (match_operand:QI 0 "register_operand" "=r") 6335 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0") 6336 (match_operand:QI 2 "single_zero_operand" "n")) 6337 (and:QI (ashift:QI (match_operand:QI 3 "register_operand" "r") 6338 (match_operand:QI 4 "const_0_to_7_operand" "n")) 6339 (match_operand:QI 5 "single_one_operand" "n"))))] 6340 "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode)) 6341 && INTVAL(operands[4]) == exact_log2 (INTVAL(operands[5]) & GET_MODE_MASK (QImode))" 6342 "bst %3,0\;bld %0,%4" 6343 [(set_attr "length" "2") 6344 (set_attr "cc" "none")]) 6345 6346;; Move bit $3.0 into bit $0.$4 6347;; Variation of above. Unfortunately, there is no canonicalized representation 6348;; of moving around bits. So what we see here depends on how user writes down 6349;; bit manipulations. 6350(define_insn "*movbitqi.1-6.b" 6351 [(set (match_operand:QI 0 "register_operand" "=r") 6352 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0") 6353 (match_operand:QI 2 "single_zero_operand" "n")) 6354 (ashift:QI (and:QI (match_operand:QI 3 "register_operand" "r") 6355 (const_int 1)) 6356 (match_operand:QI 4 "const_0_to_7_operand" "n"))))] 6357 "INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))" 6358 "bst %3,0\;bld %0,%4" 6359 [(set_attr "length" "2") 6360 (set_attr "cc" "none")]) 6361 6362;; Move bit $3.0 into bit $0.0. 6363;; For bit 0, combiner generates slightly different pattern. 6364(define_insn "*movbitqi.0" 6365 [(set (match_operand:QI 0 "register_operand" "=r") 6366 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0") 6367 (match_operand:QI 2 "single_zero_operand" "n")) 6368 (and:QI (match_operand:QI 3 "register_operand" "r") 6369 (const_int 1))))] 6370 "0 == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))" 6371 "bst %3,0\;bld %0,0" 6372 [(set_attr "length" "2") 6373 (set_attr "cc" "none")]) 6374 6375;; Move bit $2.0 into bit $0.7. 6376;; For bit 7, combiner generates slightly different pattern 6377(define_insn "*movbitqi.7" 6378 [(set (match_operand:QI 0 "register_operand" "=r") 6379 (ior:QI (and:QI (match_operand:QI 1 "register_operand" "0") 6380 (const_int 127)) 6381 (ashift:QI (match_operand:QI 2 "register_operand" "r") 6382 (const_int 7))))] 6383 "" 6384 "bst %2,0\;bld %0,7" 6385 [(set_attr "length" "2") 6386 (set_attr "cc" "none")]) 6387 6388;; Combiner transforms above four pattern into ZERO_EXTRACT if it sees MEM 6389;; and input/output match. We provide a special pattern for this, because 6390;; in contrast to a IN/BST/BLD/OUT sequence we need less registers and the 6391;; operation on I/O is atomic. 6392(define_insn "*insv.io" 6393 [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "i,i,i")) 6394 (const_int 1) 6395 (match_operand:QI 1 "const_0_to_7_operand" "n,n,n")) 6396 (match_operand:QI 2 "nonmemory_operand" "L,P,r"))] 6397 "" 6398 "@ 6399 cbi %i0,%1 6400 sbi %i0,%1 6401 sbrc %2,0\;sbi %i0,%1\;sbrs %2,0\;cbi %i0,%1" 6402 [(set_attr "length" "1,1,4") 6403 (set_attr "cc" "none")]) 6404 6405(define_insn "*insv.not.io" 6406 [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "i")) 6407 (const_int 1) 6408 (match_operand:QI 1 "const_0_to_7_operand" "n")) 6409 (not:QI (match_operand:QI 2 "register_operand" "r")))] 6410 "" 6411 "sbrs %2,0\;sbi %i0,%1\;sbrc %2,0\;cbi %i0,%1" 6412 [(set_attr "length" "4") 6413 (set_attr "cc" "none")]) 6414 6415;; The insv expander. 6416;; We only support 1-bit inserts 6417(define_expand "insv" 6418 [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "") 6419 (match_operand:QI 1 "const1_operand" "") ; width 6420 (match_operand:QI 2 "const_0_to_7_operand" "")) ; pos 6421 (match_operand:QI 3 "nonmemory_operand" ""))] 6422 "optimize") 6423 6424;; Insert bit $2.0 into $0.$1 6425(define_insn "*insv.reg" 6426 [(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r,d,d,l,l") 6427 (const_int 1) 6428 (match_operand:QI 1 "const_0_to_7_operand" "n,n,n,n,n")) 6429 (match_operand:QI 2 "nonmemory_operand" "r,L,P,L,P"))] 6430 "" 6431 "@ 6432 bst %2,0\;bld %0,%1 6433 andi %0,lo8(~(1<<%1)) 6434 ori %0,lo8(1<<%1) 6435 clt\;bld %0,%1 6436 set\;bld %0,%1" 6437 [(set_attr "length" "2,1,1,2,2") 6438 (set_attr "cc" "none,set_zn,set_zn,none,none")]) 6439 6440 6441;; Some combine patterns that try to fix bad code when a value is composed 6442;; from byte parts like in PR27663. 6443;; The patterns give some release but the code still is not optimal, 6444;; in particular when subreg lowering (-fsplit-wide-types) is turned on. 6445;; That switch obfuscates things here and in many other places. 6446 6447;; "*iorhiqi.byte0" "*iorpsiqi.byte0" "*iorsiqi.byte0" 6448;; "*xorhiqi.byte0" "*xorpsiqi.byte0" "*xorsiqi.byte0" 6449(define_insn_and_split "*<code_stdname><mode>qi.byte0" 6450 [(set (match_operand:HISI 0 "register_operand" "=r") 6451 (xior:HISI 6452 (zero_extend:HISI (match_operand:QI 1 "register_operand" "r")) 6453 (match_operand:HISI 2 "register_operand" "0")))] 6454 "" 6455 "#" 6456 "reload_completed" 6457 [(set (match_dup 3) 6458 (xior:QI (match_dup 3) 6459 (match_dup 1)))] 6460 { 6461 operands[3] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, 0); 6462 }) 6463 6464;; "*iorhiqi.byte1-3" "*iorpsiqi.byte1-3" "*iorsiqi.byte1-3" 6465;; "*xorhiqi.byte1-3" "*xorpsiqi.byte1-3" "*xorsiqi.byte1-3" 6466(define_insn_and_split "*<code_stdname><mode>qi.byte1-3" 6467 [(set (match_operand:HISI 0 "register_operand" "=r") 6468 (xior:HISI 6469 (ashift:HISI (zero_extend:HISI (match_operand:QI 1 "register_operand" "r")) 6470 (match_operand:QI 2 "const_8_16_24_operand" "n")) 6471 (match_operand:HISI 3 "register_operand" "0")))] 6472 "INTVAL(operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" 6473 "#" 6474 "&& reload_completed" 6475 [(set (match_dup 4) 6476 (xior:QI (match_dup 4) 6477 (match_dup 1)))] 6478 { 6479 int byteno = INTVAL(operands[2]) / BITS_PER_UNIT; 6480 operands[4] = simplify_gen_subreg (QImode, operands[0], <MODE>mode, byteno); 6481 }) 6482 6483(define_expand "extzv" 6484 [(set (match_operand:QI 0 "register_operand" "") 6485 (zero_extract:QI (match_operand:QI 1 "register_operand" "") 6486 (match_operand:QI 2 "const1_operand" "") 6487 (match_operand:QI 3 "const_0_to_7_operand" "")))]) 6488 6489(define_insn "*extzv" 6490 [(set (match_operand:QI 0 "register_operand" "=*d,*d,*d,*d,r") 6491 (zero_extract:QI (match_operand:QI 1 "register_operand" "0,r,0,0,r") 6492 (const_int 1) 6493 (match_operand:QI 2 "const_0_to_7_operand" "L,L,P,C04,n")))] 6494 "" 6495 "@ 6496 andi %0,1 6497 mov %0,%1\;andi %0,1 6498 lsr %0\;andi %0,1 6499 swap %0\;andi %0,1 6500 bst %1,%2\;clr %0\;bld %0,0" 6501 [(set_attr "length" "1,2,2,2,3") 6502 (set_attr "cc" "set_zn,set_zn,set_zn,set_zn,clobber")]) 6503 6504(define_insn_and_split "*extzv.qihi1" 6505 [(set (match_operand:HI 0 "register_operand" "=r") 6506 (zero_extract:HI (match_operand:QI 1 "register_operand" "r") 6507 (const_int 1) 6508 (match_operand:QI 2 "const_0_to_7_operand" "n")))] 6509 "" 6510 "#" 6511 "" 6512 [(set (match_dup 3) 6513 (zero_extract:QI (match_dup 1) 6514 (const_int 1) 6515 (match_dup 2))) 6516 (set (match_dup 4) 6517 (const_int 0))] 6518 { 6519 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0); 6520 operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1); 6521 }) 6522 6523(define_insn_and_split "*extzv.qihi2" 6524 [(set (match_operand:HI 0 "register_operand" "=r") 6525 (zero_extend:HI 6526 (zero_extract:QI (match_operand:QI 1 "register_operand" "r") 6527 (const_int 1) 6528 (match_operand:QI 2 "const_0_to_7_operand" "n"))))] 6529 "" 6530 "#" 6531 "" 6532 [(set (match_dup 3) 6533 (zero_extract:QI (match_dup 1) 6534 (const_int 1) 6535 (match_dup 2))) 6536 (set (match_dup 4) 6537 (const_int 0))] 6538 { 6539 operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0); 6540 operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 1); 6541 }) 6542 6543 6544;; Fixed-point instructions 6545(include "avr-fixed.md") 6546 6547;; Operations on 64-bit registers 6548(include "avr-dimode.md") 6549