1 ;; This file contains instructions that support fixed-point operations 2 ;; for Atmel AVR micro controllers. 3 ;; Copyright (C) 2012-2022 Free Software Foundation, Inc. 4 ;; 5 ;; Contributed by Sean D'Epagnier (sean (a] depagnier.com) 6 ;; Georg-Johann Lay (avr (a] gjlay.de) 7 8 ;; This file is part of GCC. 9 ;; 10 ;; GCC is free software; you can redistribute it and/or modify 11 ;; it under the terms of the GNU General Public License as published by 12 ;; the Free Software Foundation; either version 3, or (at your option) 13 ;; any later version. 14 ;; 15 ;; GCC is distributed in the hope that it will be useful, 16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 ;; GNU General Public License for more details. 19 ;; 20 ;; You should have received a copy of the GNU General Public License 21 ;; along with GCC; see the file COPYING3. If not see 22 ;; <http://www.gnu.org/licenses/>. 23 24 (define_mode_iterator ALL1Q [QQ UQQ]) 25 (define_mode_iterator ALL2Q [HQ UHQ]) 26 (define_mode_iterator ALL2A [HA UHA]) 27 (define_mode_iterator ALL4A [SA USA]) 28 (define_mode_iterator ALL2QA [HQ UHQ HA UHA]) 29 (define_mode_iterator ALL4QA [SQ USQ SA USA]) 30 (define_mode_iterator ALL124QA [ QQ HQ HA SA SQ 31 UQQ UHQ UHA USA USQ]) 32 33 (define_mode_iterator ALL2S [HQ HA]) 34 (define_mode_iterator ALL4S [SA SQ]) 35 (define_mode_iterator ALL24S [ HQ HA SA SQ]) 36 (define_mode_iterator ALL124S [ QQ HQ HA SA SQ]) 37 (define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ]) 38 39 ;;; Conversions 40 41 (define_mode_iterator FIXED_A 42 [QQ UQQ 43 HQ UHQ HA UHA 44 SQ USQ SA USA 45 DQ UDQ DA UDA 46 TA UTA 47 QI HI SI DI]) 48 49 ;; Same so that be can build cross products 50 51 (define_mode_iterator FIXED_B 52 [QQ UQQ 53 HQ UHQ HA UHA 54 SQ USQ SA USA 55 DQ UDQ DA UDA 56 TA UTA 57 QI HI SI DI]) 58 59 (define_insn_and_split "fract<FIXED_B:mode><FIXED_A:mode>2" 60 [(set (match_operand:FIXED_A 0 "register_operand" "=r") 61 (fract_convert:FIXED_A 62 (match_operand:FIXED_B 1 "register_operand" "r")))] 63 "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode" 64 "#" 65 "&& reload_completed" 66 [(parallel [(set (match_dup 0) 67 (fract_convert:FIXED_A 68 (match_dup 1))) 69 (clobber (reg:CC REG_CC))])]) 70 71 (define_insn "*fract<FIXED_B:mode><FIXED_A:mode>2" 72 [(set (match_operand:FIXED_A 0 "register_operand" "=r") 73 (fract_convert:FIXED_A 74 (match_operand:FIXED_B 1 "register_operand" "r"))) 75 (clobber (reg:CC REG_CC))] 76 "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode 77 && reload_completed" 78 { 79 return avr_out_fract (insn, operands, true, NULL); 80 } 81 [(set_attr "adjust_len" "sfract")]) 82 83 (define_insn_and_split "fractuns<FIXED_B:mode><FIXED_A:mode>2" 84 [(set (match_operand:FIXED_A 0 "register_operand" "=r") 85 (unsigned_fract_convert:FIXED_A 86 (match_operand:FIXED_B 1 "register_operand" "r")))] 87 "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode" 88 "#" 89 "&& reload_completed" 90 [(parallel [(set (match_dup 0) 91 (unsigned_fract_convert:FIXED_A 92 (match_dup 1))) 93 (clobber (reg:CC REG_CC))])]) 94 95 (define_insn "*fractuns<FIXED_B:mode><FIXED_A:mode>2" 96 [(set (match_operand:FIXED_A 0 "register_operand" "=r") 97 (unsigned_fract_convert:FIXED_A 98 (match_operand:FIXED_B 1 "register_operand" "r"))) 99 (clobber (reg:CC REG_CC))] 100 "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode 101 && reload_completed" 102 { 103 return avr_out_fract (insn, operands, false, NULL); 104 } 105 [(set_attr "adjust_len" "ufract")]) 106 107 ;****************************************************************************** 108 ;** Saturated Addition and Subtraction 109 ;****************************************************************************** 110 111 ;; Fixme: It would be nice if we could expand the 32-bit versions to a 112 ;; transparent libgcc call if $2 is a REG. Problem is that it is 113 ;; not possible to describe that addition is commutative. 114 ;; And defining register classes/constraintrs for the involved hard 115 ;; registers and let IRA do the work, yields inacceptable bloated code. 116 ;; Thus, we have to live with the up to 11 instructions that are output 117 ;; for these 32-bit saturated operations. 118 119 ;; "ssaddqq3" "ssaddhq3" "ssaddha3" "ssaddsq3" "ssaddsa3" 120 ;; "sssubqq3" "sssubhq3" "sssubha3" "sssubsq3" "sssubsa3" 121 (define_insn_and_split "<code_stdname><mode>3" 122 [(set (match_operand:ALL124S 0 "register_operand" "=??d,d") 123 (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0") 124 (match_operand:ALL124S 2 "nonmemory_operand" "r,Ynn")))] 125 "" 126 "#" 127 "&& reload_completed" 128 [(parallel [(set (match_dup 0) 129 (ss_addsub:ALL124S (match_dup 1) 130 (match_dup 2))) 131 (clobber (reg:CC REG_CC))])]) 132 133 (define_insn "*<code_stdname><mode>3" 134 [(set (match_operand:ALL124S 0 "register_operand" "=??d,d") 135 (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0") 136 (match_operand:ALL124S 2 "nonmemory_operand" "r,Ynn"))) 137 (clobber (reg:CC REG_CC))] 138 "reload_completed" 139 { 140 return avr_out_plus (insn, operands); 141 } 142 [(set_attr "adjust_len" "plus")]) 143 144 ;; "usadduqq3" "usadduhq3" "usadduha3" "usaddusq3" "usaddusa3" 145 ;; "ussubuqq3" "ussubuhq3" "ussubuha3" "ussubusq3" "ussubusa3" 146 (define_insn_and_split "<code_stdname><mode>3" 147 [(set (match_operand:ALL124U 0 "register_operand" "=??r,d") 148 (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0") 149 (match_operand:ALL124U 2 "nonmemory_operand" "r,Ynn")))] 150 "" 151 "#" 152 "&& reload_completed" 153 [(parallel [(set (match_dup 0) 154 (us_addsub:ALL124U (match_dup 1) 155 (match_dup 2))) 156 (clobber (reg:CC REG_CC))])]) 157 158 (define_insn "*<code_stdname><mode>3" 159 [(set (match_operand:ALL124U 0 "register_operand" "=??r,d") 160 (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0") 161 (match_operand:ALL124U 2 "nonmemory_operand" "r,Ynn"))) 162 (clobber (reg:CC REG_CC))] 163 "reload_completed" 164 { 165 return avr_out_plus (insn, operands); 166 } 167 [(set_attr "adjust_len" "plus")]) 168 169 ;****************************************************************************** 170 ;** Saturated Negation and Absolute Value 171 ;****************************************************************************** 172 173 ;; Fixme: This will always result in 0. Dunno why simplify-rtx.cc says 174 ;; "unknown" on how to optimize this. libgcc call would be in order, 175 ;; but the performance is *PLAIN* *HORROR* because the optimizers don't 176 ;; manage to optimize out MEMCPY that's sprincled all over fixed-bit.c */ 177 178 (define_expand "usneg<mode>2" 179 [(parallel [(match_operand:ALL124U 0 "register_operand" "") 180 (match_operand:ALL124U 1 "nonmemory_operand" "")])] 181 "" 182 { 183 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode)); 184 DONE; 185 }) 186 187 (define_insn_and_split "ssnegqq2" 188 [(set (match_operand:QQ 0 "register_operand" "=r") 189 (ss_neg:QQ (match_operand:QQ 1 "register_operand" "0")))] 190 "" 191 "#" 192 "&& reload_completed" 193 [(parallel [(set (match_dup 0) 194 (ss_neg:QQ (match_dup 1))) 195 (clobber (reg:CC REG_CC))])]) 196 197 (define_insn "*ssnegqq2" 198 [(set (match_operand:QQ 0 "register_operand" "=r") 199 (ss_neg:QQ (match_operand:QQ 1 "register_operand" "0"))) 200 (clobber (reg:CC REG_CC))] 201 "reload_completed" 202 "neg %0\;brvc 0f\;dec %0\;0:" 203 [(set_attr "length" "3")]) 204 205 (define_insn_and_split "ssabsqq2" 206 [(set (match_operand:QQ 0 "register_operand" "=r") 207 (ss_abs:QQ (match_operand:QQ 1 "register_operand" "0")))] 208 "" 209 "#" 210 "&& reload_completed" 211 [(parallel [(set (match_dup 0) 212 (ss_abs:QQ (match_dup 1))) 213 (clobber (reg:CC REG_CC))])]) 214 215 (define_insn "*ssabsqq2" 216 [(set (match_operand:QQ 0 "register_operand" "=r") 217 (ss_abs:QQ (match_operand:QQ 1 "register_operand" "0"))) 218 (clobber (reg:CC REG_CC))] 219 "reload_completed" 220 "sbrc %0,7\;neg %0\;sbrc %0,7\;dec %0" 221 [(set_attr "length" "4")]) 222 223 ;; "ssneghq2" "ssnegha2" "ssnegsq2" "ssnegsa2" 224 ;; "ssabshq2" "ssabsha2" "ssabssq2" "ssabssa2" 225 (define_expand "<code_stdname><mode>2" 226 [(set (match_dup 2) 227 (match_operand:ALL24S 1 "register_operand" "")) 228 (set (match_dup 2) 229 (ss_abs_neg:ALL24S (match_dup 2))) 230 (set (match_operand:ALL24S 0 "register_operand" "") 231 (match_dup 2))] 232 "" 233 { 234 operands[2] = gen_rtx_REG (<MODE>mode, 26 - GET_MODE_SIZE (<MODE>mode)); 235 }) 236 237 ;; "*ssneghq2" "*ssnegha2" 238 ;; "*ssabshq2" "*ssabsha2" 239 (define_insn_and_split "*<code_stdname><mode>2_split" 240 [(set (reg:ALL2S 24) 241 (ss_abs_neg:ALL2S (reg:ALL2S 24)))] 242 "" 243 "#" 244 "&& reload_completed" 245 [(parallel [(set (reg:ALL2S 24) 246 (ss_abs_neg:ALL2S (reg:ALL2S 24))) 247 (clobber (reg:CC REG_CC))])]) 248 249 (define_insn "*<code_stdname><mode>2" 250 [(set (reg:ALL2S 24) 251 (ss_abs_neg:ALL2S (reg:ALL2S 24))) 252 (clobber (reg:CC REG_CC))] 253 "reload_completed" 254 "%~call __<code_stdname>_2" 255 [(set_attr "type" "xcall")]) 256 257 ;; "*ssnegsq2" "*ssnegsa2" 258 ;; "*ssabssq2" "*ssabssa2" 259 (define_insn_and_split "*<code_stdname><mode>2_split" 260 [(set (reg:ALL4S 22) 261 (ss_abs_neg:ALL4S (reg:ALL4S 22)))] 262 "" 263 "#" 264 "&& reload_completed" 265 [(parallel [(set (reg:ALL4S 22) 266 (ss_abs_neg:ALL4S (reg:ALL4S 22))) 267 (clobber (reg:CC REG_CC))])]) 268 269 (define_insn "*<code_stdname><mode>2" 270 [(set (reg:ALL4S 22) 271 (ss_abs_neg:ALL4S (reg:ALL4S 22))) 272 (clobber (reg:CC REG_CC))] 273 "reload_completed" 274 "%~call __<code_stdname>_4" 275 [(set_attr "type" "xcall")]) 276 277 ;****************************************************************************** 278 ; mul 279 280 ;; "mulqq3" "muluqq3" 281 (define_expand "mul<mode>3" 282 [(parallel [(match_operand:ALL1Q 0 "register_operand" "") 283 (match_operand:ALL1Q 1 "register_operand" "") 284 (match_operand:ALL1Q 2 "register_operand" "")])] 285 "" 286 { 287 emit_insn (AVR_HAVE_MUL 288 ? gen_mul<mode>3_enh (operands[0], operands[1], operands[2]) 289 : gen_mul<mode>3_nomul (operands[0], operands[1], operands[2])); 290 DONE; 291 }) 292 293 (define_insn_and_split "mulqq3_enh" 294 [(set (match_operand:QQ 0 "register_operand" "=r") 295 (mult:QQ (match_operand:QQ 1 "register_operand" "a") 296 (match_operand:QQ 2 "register_operand" "a")))] 297 "AVR_HAVE_MUL" 298 "#" 299 "&& reload_completed" 300 [(parallel [(set (match_dup 0) 301 (mult:QQ (match_dup 1) 302 (match_dup 2))) 303 (clobber (reg:CC REG_CC))])]) 304 305 (define_insn "*mulqq3_enh" 306 [(set (match_operand:QQ 0 "register_operand" "=r") 307 (mult:QQ (match_operand:QQ 1 "register_operand" "a") 308 (match_operand:QQ 2 "register_operand" "a"))) 309 (clobber (reg:CC REG_CC))] 310 "AVR_HAVE_MUL && reload_completed" 311 "fmuls %1,%2\;dec r1\;brvs 0f\;inc r1\;0:\;mov %0,r1\;clr __zero_reg__" 312 [(set_attr "length" "6")]) 313 314 (define_insn_and_split "muluqq3_enh" 315 [(set (match_operand:UQQ 0 "register_operand" "=r") 316 (mult:UQQ (match_operand:UQQ 1 "register_operand" "r") 317 (match_operand:UQQ 2 "register_operand" "r")))] 318 "AVR_HAVE_MUL" 319 "#" 320 "&& reload_completed" 321 [(parallel [(set (match_dup 0) 322 (mult:UQQ (match_dup 1) 323 (match_dup 2))) 324 (clobber (reg:CC REG_CC))])]) 325 326 (define_insn "*muluqq3_enh" 327 [(set (match_operand:UQQ 0 "register_operand" "=r") 328 (mult:UQQ (match_operand:UQQ 1 "register_operand" "r") 329 (match_operand:UQQ 2 "register_operand" "r"))) 330 (clobber (reg:CC REG_CC))] 331 "AVR_HAVE_MUL && reload_completed" 332 "mul %1,%2\;mov %0,r1\;clr __zero_reg__" 333 [(set_attr "length" "3")]) 334 335 (define_expand "mulqq3_nomul" 336 [(set (reg:QQ 24) 337 (match_operand:QQ 1 "register_operand" "")) 338 (set (reg:QQ 25) 339 (match_operand:QQ 2 "register_operand" "")) 340 ;; "*mulqq3.call" 341 (parallel [(set (reg:QQ 23) 342 (mult:QQ (reg:QQ 24) 343 (reg:QQ 25))) 344 (clobber (reg:QI 22)) 345 (clobber (reg:HI 24))]) 346 (set (match_operand:QQ 0 "register_operand" "") 347 (reg:QQ 23))] 348 "!AVR_HAVE_MUL" 349 { 350 avr_fix_inputs (operands, 1 << 2, regmask (QQmode, 24)); 351 }) 352 353 354 (define_expand "muluqq3_nomul" 355 [(set (reg:UQQ 22) 356 (match_operand:UQQ 1 "register_operand" "")) 357 (set (reg:UQQ 24) 358 (match_operand:UQQ 2 "register_operand" "")) 359 ;; "*umulqihi3.call" 360 (parallel [(set (reg:HI 24) 361 (mult:HI (zero_extend:HI (reg:QI 22)) 362 (zero_extend:HI (reg:QI 24)))) 363 (clobber (reg:QI 21)) 364 (clobber (reg:HI 22))]) 365 (set (match_operand:UQQ 0 "register_operand" "") 366 (reg:UQQ 25))] 367 "!AVR_HAVE_MUL" 368 { 369 avr_fix_inputs (operands, 1 << 2, regmask (UQQmode, 22)); 370 }) 371 372 (define_insn_and_split "*mulqq3.call_split" 373 [(set (reg:QQ 23) 374 (mult:QQ (reg:QQ 24) 375 (reg:QQ 25))) 376 (clobber (reg:QI 22)) 377 (clobber (reg:HI 24))] 378 "!AVR_HAVE_MUL" 379 "#" 380 "&& reload_completed" 381 [(parallel [(set (reg:QQ 23) 382 (mult:QQ (reg:QQ 24) 383 (reg:QQ 25))) 384 (clobber (reg:QI 22)) 385 (clobber (reg:HI 24)) 386 (clobber (reg:CC REG_CC))])]) 387 388 (define_insn "*mulqq3.call" 389 [(set (reg:QQ 23) 390 (mult:QQ (reg:QQ 24) 391 (reg:QQ 25))) 392 (clobber (reg:QI 22)) 393 (clobber (reg:HI 24)) 394 (clobber (reg:CC REG_CC))] 395 "!AVR_HAVE_MUL && reload_completed" 396 "%~call __mulqq3" 397 [(set_attr "type" "xcall")]) 398 399 400 ;; "mulhq3" "muluhq3" 401 ;; "mulha3" "muluha3" 402 (define_expand "mul<mode>3" 403 [(set (reg:ALL2QA 18) 404 (match_operand:ALL2QA 1 "register_operand" "")) 405 (set (reg:ALL2QA 26) 406 (match_operand:ALL2QA 2 "register_operand" "")) 407 ;; "*mulhq3.call.enh" 408 (parallel [(set (reg:ALL2QA 24) 409 (mult:ALL2QA (reg:ALL2QA 18) 410 (reg:ALL2QA 26))) 411 (clobber (reg:HI 22))]) 412 (set (match_operand:ALL2QA 0 "register_operand" "") 413 (reg:ALL2QA 24))] 414 "AVR_HAVE_MUL" 415 { 416 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 18)); 417 }) 418 419 ;; "*mulhq3.call" "*muluhq3.call" 420 ;; "*mulha3.call" "*muluha3.call" 421 (define_insn_and_split "*mul<mode>3.call_split" 422 [(set (reg:ALL2QA 24) 423 (mult:ALL2QA (reg:ALL2QA 18) 424 (reg:ALL2QA 26))) 425 (clobber (reg:HI 22))] 426 "AVR_HAVE_MUL" 427 "#" 428 "&& reload_completed" 429 [(parallel [(set (reg:ALL2QA 24) 430 (mult:ALL2QA (reg:ALL2QA 18) 431 (reg:ALL2QA 26))) 432 (clobber (reg:HI 22)) 433 (clobber (reg:CC REG_CC))])]) 434 435 (define_insn "*mul<mode>3.call" 436 [(set (reg:ALL2QA 24) 437 (mult:ALL2QA (reg:ALL2QA 18) 438 (reg:ALL2QA 26))) 439 (clobber (reg:HI 22)) 440 (clobber (reg:CC REG_CC))] 441 "AVR_HAVE_MUL && reload_completed" 442 "%~call __mul<mode>3" 443 [(set_attr "type" "xcall")]) 444 445 446 ;; On the enhanced core, don't clobber either input and use a separate output 447 448 ;; "mulsa3" "mulusa3" 449 (define_expand "mul<mode>3" 450 [(set (reg:ALL4A 16) 451 (match_operand:ALL4A 1 "register_operand" "")) 452 (set (reg:ALL4A 20) 453 (match_operand:ALL4A 2 "register_operand" "")) 454 (set (reg:ALL4A 24) 455 (mult:ALL4A (reg:ALL4A 16) 456 (reg:ALL4A 20))) 457 (set (match_operand:ALL4A 0 "register_operand" "") 458 (reg:ALL4A 24))] 459 "AVR_HAVE_MUL" 460 { 461 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 16)); 462 }) 463 464 ;; "*mulsa3.call" "*mulusa3.call" 465 (define_insn_and_split "*mul<mode>3.call_split" 466 [(set (reg:ALL4A 24) 467 (mult:ALL4A (reg:ALL4A 16) 468 (reg:ALL4A 20)))] 469 "AVR_HAVE_MUL" 470 "#" 471 "&& reload_completed" 472 [(parallel [(set (reg:ALL4A 24) 473 (mult:ALL4A (reg:ALL4A 16) 474 (reg:ALL4A 20))) 475 (clobber (reg:CC REG_CC))])]) 476 477 (define_insn "*mul<mode>3.call" 478 [(set (reg:ALL4A 24) 479 (mult:ALL4A (reg:ALL4A 16) 480 (reg:ALL4A 20))) 481 (clobber (reg:CC REG_CC))] 482 "AVR_HAVE_MUL && reload_completed" 483 "%~call __mul<mode>3" 484 [(set_attr "type" "xcall")]) 485 486 ; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / 487 ; div 488 489 (define_code_iterator usdiv [udiv div]) 490 491 ;; "divqq3" "udivuqq3" 492 (define_expand "<code><mode>3" 493 [(set (reg:ALL1Q 25) 494 (match_operand:ALL1Q 1 "register_operand" "")) 495 (set (reg:ALL1Q 22) 496 (match_operand:ALL1Q 2 "register_operand" "")) 497 (parallel [(set (reg:ALL1Q 24) 498 (usdiv:ALL1Q (reg:ALL1Q 25) 499 (reg:ALL1Q 22))) 500 (clobber (reg:QI 25))]) 501 (set (match_operand:ALL1Q 0 "register_operand" "") 502 (reg:ALL1Q 24))] 503 "" 504 { 505 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 25)); 506 }) 507 508 509 ;; "*divqq3.call" "*udivuqq3.call" 510 (define_insn_and_split "*<code><mode>3.call_split" 511 [(set (reg:ALL1Q 24) 512 (usdiv:ALL1Q (reg:ALL1Q 25) 513 (reg:ALL1Q 22))) 514 (clobber (reg:QI 25))] 515 "" 516 "#" 517 "&& reload_completed" 518 [(parallel [(set (reg:ALL1Q 24) 519 (usdiv:ALL1Q (reg:ALL1Q 25) 520 (reg:ALL1Q 22))) 521 (clobber (reg:QI 25)) 522 (clobber (reg:CC REG_CC))])]) 523 524 (define_insn "*<code><mode>3.call" 525 [(set (reg:ALL1Q 24) 526 (usdiv:ALL1Q (reg:ALL1Q 25) 527 (reg:ALL1Q 22))) 528 (clobber (reg:QI 25)) 529 (clobber (reg:CC REG_CC))] 530 "reload_completed" 531 "%~call __<code><mode>3" 532 [(set_attr "type" "xcall")]) 533 534 ;; "divhq3" "udivuhq3" 535 ;; "divha3" "udivuha3" 536 (define_expand "<code><mode>3" 537 [(set (reg:ALL2QA 26) 538 (match_operand:ALL2QA 1 "register_operand" "")) 539 (set (reg:ALL2QA 22) 540 (match_operand:ALL2QA 2 "register_operand" "")) 541 (parallel [(set (reg:ALL2QA 24) 542 (usdiv:ALL2QA (reg:ALL2QA 26) 543 (reg:ALL2QA 22))) 544 (clobber (reg:HI 26)) 545 (clobber (reg:QI 21))]) 546 (set (match_operand:ALL2QA 0 "register_operand" "") 547 (reg:ALL2QA 24))] 548 "" 549 { 550 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 26)); 551 }) 552 553 ;; "*divhq3.call" "*udivuhq3.call" 554 ;; "*divha3.call" "*udivuha3.call" 555 (define_insn_and_split "*<code><mode>3.call_split" 556 [(set (reg:ALL2QA 24) 557 (usdiv:ALL2QA (reg:ALL2QA 26) 558 (reg:ALL2QA 22))) 559 (clobber (reg:HI 26)) 560 (clobber (reg:QI 21))] 561 "" 562 "#" 563 "&& reload_completed" 564 [(parallel [(set (reg:ALL2QA 24) 565 (usdiv:ALL2QA (reg:ALL2QA 26) 566 (reg:ALL2QA 22))) 567 (clobber (reg:HI 26)) 568 (clobber (reg:QI 21)) 569 (clobber (reg:CC REG_CC))])]) 570 571 (define_insn "*<code><mode>3.call" 572 [(set (reg:ALL2QA 24) 573 (usdiv:ALL2QA (reg:ALL2QA 26) 574 (reg:ALL2QA 22))) 575 (clobber (reg:HI 26)) 576 (clobber (reg:QI 21)) 577 (clobber (reg:CC REG_CC))] 578 "reload_completed" 579 "%~call __<code><mode>3" 580 [(set_attr "type" "xcall")]) 581 582 ;; Note the first parameter gets passed in already offset by 2 bytes 583 584 ;; "divsa3" "udivusa3" 585 (define_expand "<code><mode>3" 586 [(set (reg:ALL4A 24) 587 (match_operand:ALL4A 1 "register_operand" "")) 588 (set (reg:ALL4A 18) 589 (match_operand:ALL4A 2 "register_operand" "")) 590 (parallel [(set (reg:ALL4A 22) 591 (usdiv:ALL4A (reg:ALL4A 24) 592 (reg:ALL4A 18))) 593 (clobber (reg:HI 26)) 594 (clobber (reg:HI 30))]) 595 (set (match_operand:ALL4A 0 "register_operand" "") 596 (reg:ALL4A 22))] 597 "" 598 { 599 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 24)); 600 }) 601 602 ;; "*divsa3.call" "*udivusa3.call" 603 (define_insn_and_split "*<code><mode>3.call_split" 604 [(set (reg:ALL4A 22) 605 (usdiv:ALL4A (reg:ALL4A 24) 606 (reg:ALL4A 18))) 607 (clobber (reg:HI 26)) 608 (clobber (reg:HI 30))] 609 "" 610 "#" 611 "&& reload_completed" 612 [(parallel [(set (reg:ALL4A 22) 613 (usdiv:ALL4A (reg:ALL4A 24) 614 (reg:ALL4A 18))) 615 (clobber (reg:HI 26)) 616 (clobber (reg:HI 30)) 617 (clobber (reg:CC REG_CC))])]) 618 619 (define_insn "*<code><mode>3.call" 620 [(set (reg:ALL4A 22) 621 (usdiv:ALL4A (reg:ALL4A 24) 622 (reg:ALL4A 18))) 623 (clobber (reg:HI 26)) 624 (clobber (reg:HI 30)) 625 (clobber (reg:CC REG_CC))] 626 "reload_completed" 627 "%~call __<code><mode>3" 628 [(set_attr "type" "xcall")]) 629 630 631 ;****************************************************************************** 632 ;** Rounding 633 ;****************************************************************************** 634 635 ;; "roundqq3" "rounduqq3" 636 ;; "roundhq3" "rounduhq3" "roundha3" "rounduha3" 637 ;; "roundsq3" "roundusq3" "roundsa3" "roundusa3" 638 (define_expand "round<mode>3" 639 [(set (match_dup 4) 640 (match_operand:ALL124QA 1 "register_operand" "")) 641 (set (reg:QI 24) 642 (match_dup 5)) 643 (parallel [(set (match_dup 3) 644 (unspec:ALL124QA [(match_dup 4) 645 (reg:QI 24)] UNSPEC_ROUND)) 646 (clobber (match_dup 4))]) 647 (set (match_operand:ALL124QA 0 "register_operand" "") 648 (match_dup 3)) 649 (use (match_operand:HI 2 "nonmemory_operand" ""))] 650 "" 651 { 652 if (CONST_INT_P (operands[2]) 653 && !(optimize_size 654 && 4 == GET_MODE_SIZE (<MODE>mode))) 655 { 656 emit_insn (gen_round<mode>3_const (operands[0], operands[1], operands[2])); 657 DONE; 658 } 659 660 // Input and output of the libgcc function 661 const unsigned int regno_in[] = { -1U, 22, 22, -1U, 18 }; 662 const unsigned int regno_out[] = { -1U, 24, 24, -1U, 22 }; 663 664 operands[3] = gen_rtx_REG (<MODE>mode, regno_out[(size_t) GET_MODE_SIZE (<MODE>mode)]); 665 operands[4] = gen_rtx_REG (<MODE>mode, regno_in[(size_t) GET_MODE_SIZE (<MODE>mode)]); 666 avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, REGNO (operands[4]))); 667 operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, operands[2]), HImode, 0); 668 // $2 is no more needed, but is referenced for expand. 669 operands[2] = const0_rtx; 670 }) 671 672 ;; Expand rounding with known rounding points inline so that the addend / mask 673 ;; will be consumed by operation with immediate operands and there is no 674 ;; need for a shift with variable offset. 675 676 ;; "roundqq3_const" "rounduqq3_const" 677 ;; "roundhq3_const" "rounduhq3_const" "roundha3_const" "rounduha3_const" 678 ;; "roundsq3_const" "roundusq3_const" "roundsa3_const" "roundusa3_const" 679 (define_insn_and_split "round<mode>3_const" 680 [(set (match_operand:ALL124QA 0 "register_operand" "=d") 681 (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0") 682 (match_operand:HI 2 "const_int_operand" "n") 683 (const_int 0)] 684 UNSPEC_ROUND))] 685 "" 686 "#" 687 "&& reload_completed" 688 [(parallel [(set (match_dup 0) 689 (unspec:ALL124QA [(match_dup 1) 690 (match_dup 2) 691 (const_int 0)] 692 UNSPEC_ROUND)) 693 (clobber (reg:CC REG_CC))])]) 694 695 (define_insn "*round<mode>3_const" 696 [(set (match_operand:ALL124QA 0 "register_operand" "=d") 697 (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0") 698 (match_operand:HI 2 "const_int_operand" "n") 699 (const_int 0)] 700 UNSPEC_ROUND)) 701 (clobber (reg:CC REG_CC))] 702 "reload_completed" 703 { 704 return avr_out_round (insn, operands); 705 } 706 [(set_attr "adjust_len" "round")]) 707 708 709 ;; "*roundqq3.libgcc" "*rounduqq3.libgcc" 710 (define_insn_and_split "*round<mode>3.libgcc_split" 711 [(set (reg:ALL1Q 24) 712 (unspec:ALL1Q [(reg:ALL1Q 22) 713 (reg:QI 24)] UNSPEC_ROUND)) 714 (clobber (reg:ALL1Q 22))] 715 "" 716 "#" 717 "&& reload_completed" 718 [(parallel [(set (reg:ALL1Q 24) 719 (unspec:ALL1Q [(reg:ALL1Q 22) 720 (reg:QI 24)] UNSPEC_ROUND)) 721 (clobber (reg:ALL1Q 22)) 722 (clobber (reg:CC REG_CC))])]) 723 724 (define_insn "*round<mode>3.libgcc" 725 [(set (reg:ALL1Q 24) 726 (unspec:ALL1Q [(reg:ALL1Q 22) 727 (reg:QI 24)] UNSPEC_ROUND)) 728 (clobber (reg:ALL1Q 22)) 729 (clobber (reg:CC REG_CC))] 730 "reload_completed" 731 "%~call __round<mode>3" 732 [(set_attr "type" "xcall")]) 733 734 ;; "*roundhq3.libgcc" "*rounduhq3.libgcc" 735 ;; "*roundha3.libgcc" "*rounduha3.libgcc" 736 (define_insn_and_split "*round<mode>3.libgcc_split" 737 [(set (reg:ALL2QA 24) 738 (unspec:ALL2QA [(reg:ALL2QA 22) 739 (reg:QI 24)] UNSPEC_ROUND)) 740 (clobber (reg:ALL2QA 22))] 741 "" 742 "#" 743 "&& reload_completed" 744 [(parallel [(set (reg:ALL2QA 24) 745 (unspec:ALL2QA [(reg:ALL2QA 22) 746 (reg:QI 24)] UNSPEC_ROUND)) 747 (clobber (reg:ALL2QA 22)) 748 (clobber (reg:CC REG_CC))])]) 749 750 (define_insn "*round<mode>3.libgcc" 751 [(set (reg:ALL2QA 24) 752 (unspec:ALL2QA [(reg:ALL2QA 22) 753 (reg:QI 24)] UNSPEC_ROUND)) 754 (clobber (reg:ALL2QA 22)) 755 (clobber (reg:CC REG_CC))] 756 "reload_completed" 757 "%~call __round<mode>3" 758 [(set_attr "type" "xcall")]) 759 760 ;; "*roundsq3.libgcc" "*roundusq3.libgcc" 761 ;; "*roundsa3.libgcc" "*roundusa3.libgcc" 762 (define_insn_and_split "*round<mode>3.libgcc_split" 763 [(set (reg:ALL4QA 22) 764 (unspec:ALL4QA [(reg:ALL4QA 18) 765 (reg:QI 24)] UNSPEC_ROUND)) 766 (clobber (reg:ALL4QA 18))] 767 "" 768 "#" 769 "&& reload_completed" 770 [(parallel [(set (reg:ALL4QA 22) 771 (unspec:ALL4QA [(reg:ALL4QA 18) 772 (reg:QI 24)] UNSPEC_ROUND)) 773 (clobber (reg:ALL4QA 18)) 774 (clobber (reg:CC REG_CC))])]) 775 776 (define_insn "*round<mode>3.libgcc" 777 [(set (reg:ALL4QA 22) 778 (unspec:ALL4QA [(reg:ALL4QA 18) 779 (reg:QI 24)] UNSPEC_ROUND)) 780 (clobber (reg:ALL4QA 18)) 781 (clobber (reg:CC REG_CC))] 782 "reload_completed" 783 "%~call __round<mode>3" 784 [(set_attr "type" "xcall")]) 785