1;; Machine description for GNU compiler, 2;; for Atmel AVR micro controllers. 3;; Copyright (C) 1998-2022 Free Software Foundation, Inc. 4;; Contributed by Georg Lay (avr@gjlay.de) 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 23 24;; The purpose of this file is to provide a light-weight DImode 25;; implementation for AVR. The trouble with DImode is that tree -> RTL 26;; lowering leads to really unpleasant code for operations that don't 27;; work byte-wise like NEG, PLUS, MINUS, etc. Defining optabs entries for 28;; them won't help because the optab machinery assumes these operations 29;; are cheap and does not check if a libgcc implementation is available. 30;; 31;; The DImode insns are all straight forward -- except movdi. The approach 32;; of this implementation is to provide DImode insns without the burden of 33;; introducing movdi. 34;; 35;; The caveat is that if there are insns for some mode, there must also be a 36;; respective move insn that describes reloads. Therefore, this 37;; implementation uses an accumulator-based model with two hard-coded, 38;; accumulator-like registers 39;; 40;; A[] = reg:DI 18 41;; B[] = reg:DI 10 42;; 43;; so that no DImode insn contains pseudos or needs reloading. 44 45(define_constants 46 [(ACC_A 18) 47 (ACC_B 10)]) 48 49;; Supported modes that are 8 bytes wide 50(define_mode_iterator ALL8 [DI DQ UDQ DA UDA TA UTA]) 51 52(define_mode_iterator ALL8U [UDQ UDA UTA]) 53(define_mode_iterator ALL8S [ DQ DA TA]) 54 55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 56;; Addition 57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 58 59;; "adddi3" 60;; "adddq3" "addudq3" 61;; "addda3" "adduda3" 62;; "addta3" "adduta3" 63(define_expand "add<mode>3" 64 [(parallel [(match_operand:ALL8 0 "general_operand" "") 65 (match_operand:ALL8 1 "general_operand" "") 66 (match_operand:ALL8 2 "general_operand" "")])] 67 "avr_have_dimode" 68 { 69 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); 70 71 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A)); 72 emit_move_insn (acc_a, operands[1]); 73 74 if (DImode == <MODE>mode 75 && s8_operand (operands[2], VOIDmode)) 76 { 77 emit_move_insn (gen_rtx_REG (QImode, REG_X), operands[2]); 78 emit_insn (gen_adddi3_const8_insn ()); 79 } 80 else if (const_operand (operands[2], GET_MODE (operands[2]))) 81 { 82 emit_insn (gen_add<mode>3_const_insn (operands[2])); 83 } 84 else 85 { 86 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]); 87 emit_insn (gen_add<mode>3_insn ()); 88 } 89 90 emit_move_insn (operands[0], acc_a); 91 DONE; 92 }) 93 94;; "adddi3_insn" 95;; "adddq3_insn" "addudq3_insn" 96;; "addda3_insn" "adduda3_insn" 97;; "addta3_insn" "adduta3_insn" 98(define_insn_and_split "add<mode>3_insn" 99 [(set (reg:ALL8 ACC_A) 100 (plus:ALL8 (reg:ALL8 ACC_A) 101 (reg:ALL8 ACC_B)))] 102 "avr_have_dimode" 103 "#" 104 "&& reload_completed" 105 [(parallel [(set (reg:ALL8 ACC_A) 106 (plus:ALL8 (reg:ALL8 ACC_A) 107 (reg:ALL8 ACC_B))) 108 (clobber (reg:CC REG_CC))])]) 109 110(define_insn "*add<mode>3_insn" 111 [(set (reg:ALL8 ACC_A) 112 (plus:ALL8 (reg:ALL8 ACC_A) 113 (reg:ALL8 ACC_B))) 114 (clobber (reg:CC REG_CC))] 115 "avr_have_dimode && reload_completed" 116 "%~call __adddi3" 117 [(set_attr "adjust_len" "call")]) 118 119(define_insn_and_split "adddi3_const8_insn" 120 [(set (reg:DI ACC_A) 121 (plus:DI (reg:DI ACC_A) 122 (sign_extend:DI (reg:QI REG_X))))] 123 "avr_have_dimode" 124 "#" 125 "&& reload_completed" 126 [(parallel [(set (reg:DI ACC_A) 127 (plus:DI (reg:DI ACC_A) 128 (sign_extend:DI (reg:QI REG_X)))) 129 (clobber (reg:CC REG_CC))])]) 130 131(define_insn "*adddi3_const8_insn" 132 [(set (reg:DI ACC_A) 133 (plus:DI (reg:DI ACC_A) 134 (sign_extend:DI (reg:QI REG_X)))) 135 (clobber (reg:CC REG_CC))] 136 "avr_have_dimode && reload_completed" 137 "%~call __adddi3_s8" 138 [(set_attr "adjust_len" "call")]) 139 140;; "adddi3_const_insn" 141;; "adddq3_const_insn" "addudq3_const_insn" 142;; "addda3_const_insn" "adduda3_const_insn" 143;; "addta3_const_insn" "adduta3_const_insn" 144(define_insn_and_split "add<mode>3_const_insn" 145 [(set (reg:ALL8 ACC_A) 146 (plus:ALL8 (reg:ALL8 ACC_A) 147 (match_operand:ALL8 0 "const_operand" "n Ynn")))] 148 "avr_have_dimode 149 && !s8_operand (operands[0], VOIDmode)" 150 "#" 151 "&& reload_completed" 152 [(parallel [(set (reg:ALL8 ACC_A) 153 (plus:ALL8 (reg:ALL8 ACC_A) 154 (match_dup 0))) 155 (clobber (reg:CC REG_CC))])]) 156 157(define_insn "*add<mode>3_const_insn" 158 [(set (reg:ALL8 ACC_A) 159 (plus:ALL8 (reg:ALL8 ACC_A) 160 (match_operand:ALL8 0 "const_operand" "n Ynn"))) 161 (clobber (reg:CC REG_CC))] 162 "avr_have_dimode 163 && !s8_operand (operands[0], VOIDmode) 164 && reload_completed" 165 { 166 return avr_out_plus (insn, operands); 167 } 168 [(set_attr "adjust_len" "plus")]) 169 170 171;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 172;; Subtraction 173;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 174 175;; "subdi3" 176;; "subdq3" "subudq3" 177;; "subda3" "subuda3" 178;; "subta3" "subuta3" 179(define_expand "sub<mode>3" 180 [(parallel [(match_operand:ALL8 0 "general_operand" "") 181 (match_operand:ALL8 1 "general_operand" "") 182 (match_operand:ALL8 2 "general_operand" "")])] 183 "avr_have_dimode" 184 { 185 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); 186 187 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A)); 188 emit_move_insn (acc_a, operands[1]); 189 190 if (const_operand (operands[2], GET_MODE (operands[2]))) 191 { 192 emit_insn (gen_sub<mode>3_const_insn (operands[2])); 193 } 194 else 195 { 196 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]); 197 emit_insn (gen_sub<mode>3_insn ()); 198 } 199 200 emit_move_insn (operands[0], acc_a); 201 DONE; 202 }) 203 204;; "subdi3_insn" 205;; "subdq3_insn" "subudq3_insn" 206;; "subda3_insn" "subuda3_insn" 207;; "subta3_insn" "subuta3_insn" 208(define_insn_and_split "sub<mode>3_insn" 209 [(set (reg:ALL8 ACC_A) 210 (minus:ALL8 (reg:ALL8 ACC_A) 211 (reg:ALL8 ACC_B)))] 212 "avr_have_dimode" 213 "#" 214 "&& reload_completed" 215 [(parallel [(set (reg:ALL8 ACC_A) 216 (minus:ALL8 (reg:ALL8 ACC_A) 217 (reg:ALL8 ACC_B))) 218 (clobber (reg:CC REG_CC))])]) 219 220(define_insn "*sub<mode>3_insn" 221 [(set (reg:ALL8 ACC_A) 222 (minus:ALL8 (reg:ALL8 ACC_A) 223 (reg:ALL8 ACC_B))) 224 (clobber (reg:CC REG_CC))] 225 "avr_have_dimode && reload_completed" 226 "%~call __subdi3" 227 [(set_attr "adjust_len" "call")]) 228 229;; "subdi3_const_insn" 230;; "subdq3_const_insn" "subudq3_const_insn" 231;; "subda3_const_insn" "subuda3_const_insn" 232;; "subta3_const_insn" "subuta3_const_insn" 233(define_insn_and_split "sub<mode>3_const_insn" 234 [(set (reg:ALL8 ACC_A) 235 (minus:ALL8 (reg:ALL8 ACC_A) 236 (match_operand:ALL8 0 "const_operand" "n Ynn")))] 237 "avr_have_dimode" 238 "#" 239 "&& reload_completed" 240 [(parallel [(set (reg:ALL8 ACC_A) 241 (minus:ALL8 (reg:ALL8 ACC_A) 242 (match_dup 0))) 243 (clobber (reg:CC REG_CC))])]) 244 245(define_insn "*sub<mode>3_const_insn" 246 [(set (reg:ALL8 ACC_A) 247 (minus:ALL8 (reg:ALL8 ACC_A) 248 (match_operand:ALL8 0 "const_operand" "n Ynn"))) 249 (clobber (reg:CC REG_CC))] 250 "avr_have_dimode && reload_completed" 251 { 252 return avr_out_plus (insn, operands); 253 } 254 [(set_attr "adjust_len" "plus")]) 255 256;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 257;; Signed Saturating Addition and Subtraction 258;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 259 260(define_expand "<code_stdname><mode>3" 261 [(set (match_operand:ALL8S 0 "general_operand" "") 262 (ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "") 263 (match_operand:ALL8S 2 "general_operand" "")))] 264 "avr_have_dimode" 265 { 266 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); 267 268 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A)); 269 emit_move_insn (acc_a, operands[1]); 270 271 if (const_operand (operands[2], GET_MODE (operands[2]))) 272 { 273 emit_insn (gen_<code_stdname><mode>3_const_insn (operands[2])); 274 } 275 else 276 { 277 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]); 278 emit_insn (gen_<code_stdname><mode>3_insn ()); 279 } 280 281 emit_move_insn (operands[0], acc_a); 282 DONE; 283 }) 284 285(define_insn_and_split "<code_stdname><mode>3_insn" 286 [(set (reg:ALL8S ACC_A) 287 (ss_addsub:ALL8S (reg:ALL8S ACC_A) 288 (reg:ALL8S ACC_B)))] 289 "avr_have_dimode" 290 "#" 291 "&& reload_completed" 292 [(parallel [(set (reg:ALL8S ACC_A) 293 (ss_addsub:ALL8S (reg:ALL8S ACC_A) 294 (reg:ALL8S ACC_B))) 295 (clobber (reg:CC REG_CC))])]) 296 297(define_insn "*<code_stdname><mode>3_insn" 298 [(set (reg:ALL8S ACC_A) 299 (ss_addsub:ALL8S (reg:ALL8S ACC_A) 300 (reg:ALL8S ACC_B))) 301 (clobber (reg:CC REG_CC))] 302 "avr_have_dimode && reload_completed" 303 "%~call __<code_stdname><mode>3" 304 [(set_attr "adjust_len" "call")]) 305 306(define_insn_and_split "<code_stdname><mode>3_const_insn" 307 [(set (reg:ALL8S ACC_A) 308 (ss_addsub:ALL8S (reg:ALL8S ACC_A) 309 (match_operand:ALL8S 0 "const_operand" "n Ynn")))] 310 "avr_have_dimode" 311 "#" 312 "&& reload_completed" 313 [(parallel [(set (reg:ALL8S ACC_A) 314 (ss_addsub:ALL8S (reg:ALL8S ACC_A) 315 (match_dup 0))) 316 (clobber (reg:CC REG_CC))])]) 317 318(define_insn "*<code_stdname><mode>3_const_insn" 319 [(set (reg:ALL8S ACC_A) 320 (ss_addsub:ALL8S (reg:ALL8S ACC_A) 321 (match_operand:ALL8S 0 "const_operand" "n Ynn"))) 322 (clobber (reg:CC REG_CC))] 323 "avr_have_dimode && reload_completed" 324 { 325 return avr_out_plus (insn, operands); 326 } 327 [(set_attr "adjust_len" "plus")]) 328 329;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 330;; Unsigned Saturating Addition and Subtraction 331;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 332 333(define_expand "<code_stdname><mode>3" 334 [(set (match_operand:ALL8U 0 "general_operand" "") 335 (us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "") 336 (match_operand:ALL8U 2 "general_operand" "")))] 337 "avr_have_dimode" 338 { 339 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); 340 341 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A)); 342 emit_move_insn (acc_a, operands[1]); 343 344 if (const_operand (operands[2], GET_MODE (operands[2]))) 345 { 346 emit_insn (gen_<code_stdname><mode>3_const_insn (operands[2])); 347 } 348 else 349 { 350 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]); 351 emit_insn (gen_<code_stdname><mode>3_insn ()); 352 } 353 354 emit_move_insn (operands[0], acc_a); 355 DONE; 356 }) 357 358(define_insn_and_split "<code_stdname><mode>3_insn" 359 [(set (reg:ALL8U ACC_A) 360 (us_addsub:ALL8U (reg:ALL8U ACC_A) 361 (reg:ALL8U ACC_B)))] 362 "avr_have_dimode" 363 "#" 364 "&& reload_completed" 365 [(parallel [(set (reg:ALL8U ACC_A) 366 (us_addsub:ALL8U (reg:ALL8U ACC_A) 367 (reg:ALL8U ACC_B))) 368 (clobber (reg:CC REG_CC))])]) 369 370(define_insn "*<code_stdname><mode>3_insn" 371 [(set (reg:ALL8U ACC_A) 372 (us_addsub:ALL8U (reg:ALL8U ACC_A) 373 (reg:ALL8U ACC_B))) 374 (clobber (reg:CC REG_CC))] 375 "avr_have_dimode && reload_completed" 376 "%~call __<code_stdname><mode>3" 377 [(set_attr "adjust_len" "call")]) 378 379(define_insn_and_split "<code_stdname><mode>3_const_insn" 380 [(set (reg:ALL8U ACC_A) 381 (us_addsub:ALL8U (reg:ALL8U ACC_A) 382 (match_operand:ALL8U 0 "const_operand" "n Ynn")))] 383 "avr_have_dimode" 384 "#" 385 "&& reload_completed" 386 [(parallel [(set (reg:ALL8U ACC_A) 387 (us_addsub:ALL8U (reg:ALL8U ACC_A) 388 (match_operand:ALL8U 0 "const_operand" "n Ynn"))) 389 (clobber (reg:CC REG_CC))])]) 390 391(define_insn "*<code_stdname><mode>3_const_insn" 392 [(set (reg:ALL8U ACC_A) 393 (us_addsub:ALL8U (reg:ALL8U ACC_A) 394 (match_operand:ALL8U 0 "const_operand" "n Ynn"))) 395 (clobber (reg:CC REG_CC))] 396 "avr_have_dimode && reload_completed" 397 { 398 return avr_out_plus (insn, operands); 399 } 400 [(set_attr "adjust_len" "plus")]) 401 402;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 403;; Negation 404;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 405 406(define_expand "negdi2" 407 [(parallel [(match_operand:DI 0 "general_operand" "") 408 (match_operand:DI 1 "general_operand" "")])] 409 "avr_have_dimode" 410 { 411 rtx acc_a = gen_rtx_REG (DImode, ACC_A); 412 413 emit_move_insn (acc_a, operands[1]); 414 emit_insn (gen_negdi2_insn ()); 415 emit_move_insn (operands[0], acc_a); 416 DONE; 417 }) 418 419(define_insn_and_split "negdi2_insn" 420 [(set (reg:DI ACC_A) 421 (neg:DI (reg:DI ACC_A)))] 422 "avr_have_dimode" 423 "#" 424 "&& reload_completed" 425 [(parallel [(set (reg:DI ACC_A) 426 (neg:DI (reg:DI ACC_A))) 427 (clobber (reg:CC REG_CC))])]) 428 429(define_insn "*negdi2_insn" 430 [(set (reg:DI ACC_A) 431 (neg:DI (reg:DI ACC_A))) 432 (clobber (reg:CC REG_CC))] 433 "avr_have_dimode && reload_completed" 434 "%~call __negdi2" 435 [(set_attr "adjust_len" "call")]) 436 437 438;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 439;; Comparison 440;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 441 442(define_expand "conditional_jump" 443 [(set (pc) 444 (if_then_else 445 (match_operator 0 "ordered_comparison_operator" [(reg:CC REG_CC) 446 (const_int 0)]) 447 (label_ref (match_operand 1 "" "")) 448 (pc)))] 449 "avr_have_dimode") 450 451;; "cbranchdi4" 452;; "cbranchdq4" "cbranchudq4" 453;; "cbranchda4" "cbranchuda4" 454;; "cbranchta4" "cbranchuta4" 455(define_expand "cbranch<mode>4" 456 [(set (pc) 457 (if_then_else (match_operator 0 "ordered_comparison_operator" 458 [(match_operand:ALL8 1 "register_operand") 459 (match_operand:ALL8 2 "nonmemory_operand")]) 460 (label_ref (match_operand 3)) 461 (pc)))] 462 "avr_have_dimode" 463 { 464 int icode = (int) GET_CODE (operands[0]); 465 466 targetm.canonicalize_comparison (&icode, &operands[1], &operands[2], false); 467 operands[0] = gen_rtx_fmt_ee ((enum rtx_code) icode, 468 VOIDmode, operands[1], operands[2]); 469 470 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); 471 472 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A)); 473 emit_move_insn (acc_a, operands[1]); 474 475 if (s8_operand (operands[2], VOIDmode)) 476 { 477 emit_move_insn (gen_rtx_REG (QImode, REG_X), operands[2]); 478 emit_jump_insn (gen_cbranch_const8_di2_split (operands[0], operands[3])); 479 } 480 else if (const_operand (operands[2], GET_MODE (operands[2]))) 481 { 482 emit_jump_insn (gen_cbranch_const_<mode>2_split (operands[0], 483 operands[2], 484 operands[3])); 485 } 486 else 487 { 488 emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]); 489 emit_jump_insn (gen_cbranch_<mode>2_split (operands[0], operands[3])); 490 } 491 DONE; 492 }) 493 494(define_insn_and_split "cbranch_<mode>2_split" 495 [(set (pc) 496 (if_then_else (match_operator 0 "ordered_comparison_operator" 497 [(reg:ALL8 ACC_A) 498 (reg:ALL8 ACC_B)]) 499 (label_ref (match_operand 1)) 500 (pc)))] 501 "avr_have_dimode" 502 "#" 503 "&& reload_completed" 504 [(const_int 0)] 505 { 506 emit_insn (gen_compare_<mode>2 ()); 507 emit_jump_insn (gen_conditional_jump (operands[0], operands[1])); 508 DONE; 509 }) 510 511;; "compare_di2" 512;; "compare_dq2" "compare_udq2" 513;; "compare_da2" "compare_uda2" 514;; "compare_ta2" "compare_uta2" 515(define_insn "compare_<mode>2" 516 [(set (reg:CC REG_CC) 517 (compare:CC (reg:ALL8 ACC_A) 518 (reg:ALL8 ACC_B)))] 519 "reload_completed && avr_have_dimode" 520 "%~call __cmpdi2" 521 [(set_attr "adjust_len" "call")]) 522 523(define_insn_and_split "cbranch_const8_di2_split" 524 [(set (pc) 525 (if_then_else (match_operator 0 "ordered_comparison_operator" 526 [(reg:DI ACC_A) 527 (sign_extend:DI (reg:QI REG_X))]) 528 (label_ref (match_operand 1 "" "")) 529 (pc)))] 530 "avr_have_dimode" 531 "#" 532 "&& reload_completed" 533 [(const_int 0)] 534 { 535 emit_insn (gen_compare_const8_di2 ()); 536 emit_jump_insn (gen_conditional_jump (operands[0], operands[1])); 537 DONE; 538 }) 539 540(define_insn "compare_const8_di2" 541 [(set (reg:CC REG_CC) 542 (compare:CC (reg:DI ACC_A) 543 (sign_extend:DI (reg:QI REG_X))))] 544 "reload_completed && avr_have_dimode" 545 "%~call __cmpdi2_s8" 546 [(set_attr "adjust_len" "call")]) 547 548(define_insn_and_split "cbranch_const_<mode>2_split" 549 [(set (pc) 550 (if_then_else (match_operator 0 "ordered_comparison_operator" 551 [(reg:ALL8 ACC_A) 552 (match_operand:ALL8 1 "const_operand" "n Ynn")]) 553 (label_ref (match_operand 2 "" "")) 554 (pc))) 555 (clobber (match_scratch:QI 3 "=&d"))] 556 "avr_have_dimode 557 && !s8_operand (operands[1], VOIDmode)" 558 "#" 559 "&& reload_completed" 560 [(const_int 0)] 561 { 562 emit_insn (gen_compare_const_<mode>2 (operands[1], operands[3])); 563 emit_jump_insn (gen_conditional_jump (operands[0], operands[2])); 564 DONE; 565 }) 566 567 568;; "compare_const_di2" 569;; "compare_const_dq2" "compare_const_udq2" 570;; "compare_const_da2" "compare_const_uda2" 571;; "compare_const_ta2" "compare_const_uta2" 572(define_insn "compare_const_<mode>2" 573 [(set (reg:CC REG_CC) 574 (compare:CC (reg:ALL8 ACC_A) 575 (match_operand:ALL8 0 "const_operand" "n Ynn"))) 576 (clobber (match_operand:QI 1 "register_operand" "=&d"))] 577 "reload_completed 578 && avr_have_dimode 579 && !s8_operand (operands[0], VOIDmode)" 580 { 581 return avr_out_compare64 (insn, operands, NULL); 582 } 583 [(set_attr "adjust_len" "compare64")]) 584 585 586;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 587;; Shifts and Rotate 588;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 589 590(define_code_iterator di_shifts 591 [ashift ashiftrt lshiftrt rotate]) 592 593;; Shift functions from libgcc are called without defining these insns, 594;; but with them we can describe their reduced register footprint. 595 596;; "ashldi3" "ashrdi3" "lshrdi3" "rotldi3" 597;; "ashldq3" "ashrdq3" "lshrdq3" "rotldq3" 598;; "ashlda3" "ashrda3" "lshrda3" "rotlda3" 599;; "ashlta3" "ashrta3" "lshrta3" "rotlta3" 600;; "ashludq3" "ashrudq3" "lshrudq3" "rotludq3" 601;; "ashluda3" "ashruda3" "lshruda3" "rotluda3" 602;; "ashluta3" "ashruta3" "lshruta3" "rotluta3" 603(define_expand "<code_stdname><mode>3" 604 [(parallel [(match_operand:ALL8 0 "general_operand" "") 605 (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "") 606 (match_operand:QI 2 "general_operand" ""))])] 607 "avr_have_dimode" 608 { 609 rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); 610 611 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, ACC_A)); 612 emit_move_insn (acc_a, operands[1]); 613 emit_move_insn (gen_rtx_REG (QImode, 16), operands[2]); 614 emit_insn (gen_<code_stdname><mode>3_insn ()); 615 emit_move_insn (operands[0], acc_a); 616 DONE; 617 }) 618 619;; "ashldi3_insn" "ashrdi3_insn" "lshrdi3_insn" "rotldi3_insn" 620;; "ashldq3_insn" "ashrdq3_insn" "lshrdq3_insn" "rotldq3_insn" 621;; "ashlda3_insn" "ashrda3_insn" "lshrda3_insn" "rotlda3_insn" 622;; "ashlta3_insn" "ashrta3_insn" "lshrta3_insn" "rotlta3_insn" 623;; "ashludq3_insn" "ashrudq3_insn" "lshrudq3_insn" "rotludq3_insn" 624;; "ashluda3_insn" "ashruda3_insn" "lshruda3_insn" "rotluda3_insn" 625;; "ashluta3_insn" "ashruta3_insn" "lshruta3_insn" "rotluta3_insn" 626(define_insn_and_split "<code_stdname><mode>3_insn" 627 [(set (reg:ALL8 ACC_A) 628 (di_shifts:ALL8 (reg:ALL8 ACC_A) 629 (reg:QI 16)))] 630 "avr_have_dimode" 631 "#" 632 "&& reload_completed" 633 [(parallel [(set (reg:ALL8 ACC_A) 634 (di_shifts:ALL8 (reg:ALL8 ACC_A) 635 (reg:QI 16))) 636 (clobber (reg:CC REG_CC))])]) 637 638(define_insn "*<code_stdname><mode>3_insn" 639 [(set (reg:ALL8 ACC_A) 640 (di_shifts:ALL8 (reg:ALL8 ACC_A) 641 (reg:QI 16))) 642 (clobber (reg:CC REG_CC))] 643 "avr_have_dimode && reload_completed" 644 "%~call __<code_stdname>di3" 645 [(set_attr "adjust_len" "call")]) 646 647;; "umulsidi3" 648;; "mulsidi3" 649(define_expand "<extend_u>mulsidi3" 650 [(parallel [(match_operand:DI 0 "register_operand" "") 651 (match_operand:SI 1 "general_operand" "") 652 (match_operand:SI 2 "general_operand" "") 653 ;; Just to mention the iterator 654 (clobber (any_extend:SI (match_dup 1)))])] 655 "avr_have_dimode 656 && AVR_HAVE_MUL" 657 { 658 avr_fix_inputs (operands, 1 << 2, regmask (SImode, 22)); 659 emit_move_insn (gen_rtx_REG (SImode, 22), operands[1]); 660 emit_move_insn (gen_rtx_REG (SImode, 18), operands[2]); 661 emit_insn (gen_<extend_u>mulsidi3_insn()); 662 // Use emit_move_insn and not open-coded expand because of missing movdi 663 emit_move_insn (operands[0], gen_rtx_REG (DImode, ACC_A)); 664 DONE; 665 }) 666 667;; "umulsidi3_insn" 668;; "mulsidi3_insn" 669 670(define_insn_and_split "<extend_u>mulsidi3_insn" 671 [(set (reg:DI ACC_A) 672 (mult:DI (any_extend:DI (reg:SI 18)) 673 (any_extend:DI (reg:SI 22)))) 674 (clobber (reg:HI REG_X)) 675 (clobber (reg:HI REG_Z))] 676 "avr_have_dimode 677 && AVR_HAVE_MUL" 678 "#" 679 "&& reload_completed" 680 [(parallel [(set (reg:DI ACC_A) 681 (mult:DI (any_extend:DI (reg:SI 18)) 682 (any_extend:DI (reg:SI 22)))) 683 (clobber (reg:HI REG_X)) 684 (clobber (reg:HI REG_Z)) 685 (clobber (reg:CC REG_CC))])]) 686 687(define_insn "*<extend_u>mulsidi3_insn" 688 [(set (reg:DI ACC_A) 689 (mult:DI (any_extend:DI (reg:SI 18)) 690 (any_extend:DI (reg:SI 22)))) 691 (clobber (reg:HI REG_X)) 692 (clobber (reg:HI REG_Z)) 693 (clobber (reg:CC REG_CC))] 694 "avr_have_dimode 695 && AVR_HAVE_MUL 696 && reload_completed" 697 "%~call __<extend_u>mulsidi3" 698 [(set_attr "adjust_len" "call")]) 699