1;; Machine Description for Renesas RL78 processors 2;; Copyright (C) 2011-2018 Free Software Foundation, Inc. 3;; Contributed by Red Hat. 4 5;; This file is part of GCC. 6 7;; GCC is free software; you can redistribute it and/or modify 8;; it under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 3, or (at your option) 10;; any later version. 11 12;; GCC is distributed in the hope that it will be useful, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public License for more details. 16 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21(define_constants 22 [ 23 (AX_REG 0) 24 (X_REG 0) 25 (A_REG 1) 26 (BC_REG 2) 27 (C_REG 2) 28 (B_REG 3) 29 (DE_REG 4) 30 (E_REG 4) 31 (D_REG 5) 32 (HL_REG 6) 33 (L_REG 6) 34 (H_REG 7) 35 36 (FP_REG 22) 37 (SP_REG 32) 38 (CC_REG 34) 39 (ES_REG 35) 40 (CS_REG 36) 41 42 (UNS_PROLOG 1) 43 (UNS_EPILOG 1) 44 (UNS_RETI 2) 45 (UNS_RETB 3) 46 47 (UNS_SET_RB 10) 48 (UNS_ES_ADDR 11) 49 50 (UNS_TRAMPOLINE_INIT 20) 51 (UNS_TRAMPOLINE_UNINIT 21) 52 (UNS_NONLOCAL_GOTO 22) 53 54 ]) 55 56(define_insn "nop" 57 [(const_int 0)] 58 "" 59 "nop" 60 ) 61 62(define_mode_iterator QHI [QI HI]) 63 64(include "predicates.md") 65(include "constraints.md") 66(include "rl78-expand.md") 67(include "rl78-virt.md") 68(include "rl78-real.md") 69 70(define_attr "is_g13_muldiv_insn" "yes,no" (const_string "no")) 71 72;; Function Prologue/Epilogue Instructions 73 74(define_expand "prologue" 75 [(const_int 0)] 76 "" 77 "rl78_expand_prologue (); DONE;" 78) 79 80(define_expand "epilogue" 81 [(const_int 0)] 82 "" 83 "rl78_expand_epilogue (); DONE;" 84) 85 86(define_expand "sibcall_epilogue" 87 [(return)] 88 "" 89 "FAIL;" 90) 91 92(define_insn "rl78_return" 93 [(return)] 94 "" 95 "ret" 96) 97 98(define_insn "interrupt_return" 99 [(unspec_volatile [(return)] UNS_RETI) ] 100 "" 101 "reti" 102) 103 104(define_insn "brk_interrupt_return" 105 [(unspec_volatile [(return)] UNS_RETB) ] 106 "" 107 "retb" 108) 109 110(define_expand "eh_return" 111 [(match_operand:HI 0 "")] 112 "" 113 "rl78_expand_eh_epilogue (operands[0]); 114 emit_barrier (); 115 DONE;" 116) 117 118;; These are used only by prologue/epilogue so it's "safe" to pass 119;; virtual registers. 120(define_insn "push" 121 [(set (reg:HI SP_REG) 122 (plus:HI (reg:HI SP_REG) 123 (const_int -2))) 124 (set (mem:HI (reg:HI SP_REG)) 125 (match_operand:HI 0 "register_operand" "ABDT,vZint"))] 126 "" 127 "@ 128 push\t%v0 129 push\t%v0 ; %0" 130) 131 132(define_insn "pop" 133 [(set (match_operand:HI 0 "register_operand" "=ABDT,vZint") 134 (mem:HI (reg:HI SP_REG))) 135 (set (reg:HI SP_REG) 136 (plus:HI (reg:HI SP_REG) 137 (const_int 2)))] 138 "" 139 "@ 140 pop\t%v0 141 pop\t%v0 ; %0" 142) 143 144(define_insn "sel_rb" 145 [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)] 146 "!TARGET_G10" 147 "sel\trb%u0" 148 ) 149 150(define_insn "trampoline_init" 151 [(set (match_operand 0 "register_operand" "=Z08W") 152 (unspec_volatile [(match_operand 1 "register_operand" "Z08W") 153 (match_operand 2 "register_operand" "Z10W") 154 ] UNS_TRAMPOLINE_INIT)) 155 ] 156 "" 157 "call !!___trampoline_init ; %0 <= %1 %2" 158 ) 159 160(define_insn "trampoline_uninit" 161 [(unspec_volatile [(const_int 0)] UNS_TRAMPOLINE_UNINIT) 162 ] 163 "" 164 "call !!___trampoline_uninit" 165 ) 166 167;; GCC restores $fp *before* using it to access values on the *old* 168;; frame. So, we do it ourselves, to ensure this is not the case. 169;; Note that while %1 is usually a label_ref, we allow for a 170;; non-immediate as well. 171(define_expand "nonlocal_goto" 172 [(set (pc) 173 (unspec_volatile [(match_operand 0 "") ;; fp (ignore) 174 (match_operand 1 "") ;; target 175 (match_operand 2 "") ;; sp 176 (match_operand 3 "") ;; ? 177 ] UNS_NONLOCAL_GOTO)) 178 ] 179 "" 180 "emit_jump_insn (gen_nonlocal_goto_insn (operands[0], operands[1], operands[2], operands[3])); 181 emit_barrier (); 182 DONE;" 183 ) 184 185(define_insn "nonlocal_goto_insn" 186 [(set (pc) 187 (unspec_volatile [(match_operand 0 "" "") ;; fp (ignore) 188 (match_operand 1 "" "vi") ;; target 189 (match_operand 2 "" "vi") ;; sp 190 (match_operand 3 "" "vi") ;; ? 191 ] UNS_NONLOCAL_GOTO)) 192 ] 193 "" 194 "; nonlocal goto 195 movw ax, %3 196 movw r22, ax 197 movw ax, %2 198 movw sp, ax 199 movw ax, %1 200 br ax 201" 202 ) 203 204(define_expand "es_addr" 205 [(unspec:SI [(reg:QI ES_REG) 206 (match_operand:HI 0 "") 207 ] UNS_ES_ADDR)] 208 "" 209 "" 210) 211 212;;====================================================================== 213;; 214;; "macro" insns - cases where inline chunks of code are more 215;; efficient than anything else. 216 217(define_expand "addsi3" 218 [(set (match_operand:SI 0 "nonimmediate_operand" "=&vm") 219 (plus:SI (match_operand:SI 1 "general_operand" "vim") 220 (match_operand 2 "general_operand" "vim"))) 221 ] 222 "" 223 "emit_insn (gen_addsi3_internal_virt (operands[0], operands[1], operands[2])); 224 DONE;" 225) 226 227(define_expand "adddi3" 228 [(set (match_operand:DI 0 "nonimmediate_operand" "") 229 (plus:DI (match_operand:DI 1 "general_operand" "") 230 (match_operand:DI 2 "general_operand" ""))) 231 ] 232 "" 233 "rl78_emit_libcall (\"__adddi3\", PLUS, DImode, DImode, 3, operands); 234 DONE;" 235) 236 237(define_insn "addsi3_internal_virt" 238 [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm") 239 (plus:SI (match_operand:SI 1 "general_operand" "0, vim, vim") 240 (match_operand 2 "general_operand" "vim,vim,vim"))) 241 (clobber (reg:HI AX_REG)) 242 (clobber (reg:HI BC_REG)) 243 ] 244 "rl78_virt_insns_ok ()" 245 "" 246 [(set_attr "valloc" "macax")] 247) 248 249(define_insn "addsi3_internal_real" 250 [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU") 251 (plus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU") 252 (match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1"))) 253 (clobber (reg:HI AX_REG)) 254 (clobber (reg:HI BC_REG)) 255 ] 256 "rl78_real_insns_ok ()" 257 { return rl78_addsi3_internal (operands, which_alternative); } 258 [(set_attr "valloc" "macax")] 259) 260 261(define_expand "subsi3" 262 [(set (match_operand:SI 0 "nonimmediate_operand") 263 (minus:SI (match_operand:SI 1 "general_operand") 264 (match_operand 2 "general_operand"))) 265 ] 266 "" 267 "emit_insn (gen_subsi3_internal_virt (operands[0], operands[1], operands[2])); 268 DONE;" 269) 270 271(define_expand "subdi3" 272 [(set (match_operand:DI 0 "nonimmediate_operand" "") 273 (minus:DI (match_operand:DI 1 "general_operand" "") 274 (match_operand:DI 2 "general_operand" ""))) 275 ] 276 "" 277 "rl78_emit_libcall (\"__subdi3\", MINUS, DImode, DImode, 3, operands); 278 DONE;" 279) 280 281(define_insn "subsi3_internal_virt" 282 [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm") 283 (minus:SI (match_operand:SI 1 "general_operand" "0, vim, vim") 284 (match_operand 2 "general_operand" "vim,vim,vim"))) 285 (clobber (reg:HI AX_REG)) 286 (clobber (reg:HI BC_REG)) 287 ] 288 "rl78_virt_insns_ok ()" 289 "" 290 [(set_attr "valloc" "macax")] 291) 292 293(define_insn "subsi3_internal_real" 294 [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU") 295 (minus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU") 296 (match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1"))) 297 (clobber (reg:HI AX_REG)) 298 (clobber (reg:HI BC_REG)) 299 ] 300 "rl78_real_insns_ok ()" 301 "@ 302 movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax 303 movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax 304 movw ax,%h1 \;subw ax,%h2 \;movw bc, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax \;movw ax,bc \;movw %h0, ax" 305 [(set_attr "valloc" "macax")] 306) 307 308(define_expand "mulqi3" 309 [(parallel 310 [(set (match_operand:QI 0 "register_operand") 311 (mult:QI (match_operand:QI 1 "general_operand") 312 (match_operand:QI 2 "nonmemory_operand"))) 313 (clobber (reg:HI AX_REG)) 314 ]) 315 ] 316 "" ; mulu supported by all targets 317 "" 318) 319 320(define_expand "mulhi3" 321 [(set (match_operand:HI 0 "register_operand") 322 (mult:HI (match_operand:HI 1 "general_operand") 323 (match_operand:HI 2 "nonmemory_operand"))) 324 ] 325 "! RL78_MUL_NONE" 326 { 327 if (RL78_MUL_G14) 328 emit_insn (gen_mulhi3_g14 (operands[0], operands[1], operands[2])); 329 else /* RL78_MUL_G13 */ 330 emit_insn (gen_mulhi3_g13 (operands[0], operands[1], operands[2])); 331 DONE; 332 } 333) 334 335(define_expand "mulsi3" 336 [(set (match_operand:SI 0 "register_operand") 337 (mult:SI (match_operand:SI 1 "general_operand") 338 (match_operand:SI 2 "nonmemory_operand"))) 339 ] 340 "! RL78_MUL_NONE" 341 { 342 if (RL78_MUL_G14) 343 emit_insn (gen_mulsi3_g14 (operands[0], operands[1], operands[2])); 344 else /* RL78_MUL_G13 */ 345 emit_insn (gen_mulsi3_g13 (operands[0], operands[1], operands[2])); 346 DONE; 347 } 348) 349 350(define_insn "*mulqi3_rl78" 351 [(set (match_operand:QI 0 "register_operand" "=&v") 352 (mult:QI (match_operand:QI 1 "general_operand" "viU") 353 (match_operand:QI 2 "general_operand" "vi"))) 354 (clobber (reg:HI AX_REG)) 355 ] 356 "" ; mulu supported by all targets 357 "; mulqi macro %0 = %1 * %2 358 mov a, %h1 359 mov x, a 360 mov a, %h2 361 mulu x ; ax = a * x 362 mov a, x 363 mov %h0, a 364 ; end of mulqi macro" 365 [(set_attr "valloc" "macax")] 366) 367 368(define_insn "mulhi3_g14" 369 [(set (match_operand:HI 0 "register_operand" "=&v") 370 (mult:HI (match_operand:HI 1 "general_operand" "viU") 371 (match_operand:HI 2 "general_operand" "vi"))) 372 (clobber (reg:HI AX_REG)) 373 (clobber (reg:HI BC_REG)) 374 ] 375 "RL78_MUL_G14" 376 "; G14 mulhi macro %0 = %1 * %2 377 movw ax, %h1 378 movw bc, %h2 379 mulhu ; bcax = bc * ax 380 movw %h0, ax 381 ; end of mulhi macro" 382 [(set_attr "valloc" "macax")] 383) 384 385(define_insn "mulhi3_g13" 386 [(set (match_operand:HI 0 "register_operand" "=&v") 387 (mult:HI (match_operand:HI 1 "general_operand" "viU") 388 (match_operand:HI 2 "general_operand" "vi"))) 389 (clobber (reg:HI AX_REG)) 390 ] 391 "RL78_MUL_G13" 392 "; G13 mulhi macro %0 = %1 * %2 393 mov a, #0x00 394 mov !0xf00e8, a ; MDUC 395 movw ax, %h1 396 movw 0xffff0, ax ; MDAL 397 movw ax, %h2 398 movw 0xffff2, ax ; MDAH 399 nop ; mdb = mdal * mdah 400 movw ax, 0xffff6 ; MDBL 401 movw %h0, ax 402 ; end of mulhi macro" 403 [(set_attr "valloc" "macax") 404 (set_attr "is_g13_muldiv_insn" "yes")] 405) 406 407;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it 408;; because we're only using the lower 16 bits (which is the upper 16 409;; bits of the result). 410(define_insn "mulsi3_g14" 411 [(set (match_operand:SI 0 "register_operand" "=&v") 412 (mult:SI (match_operand:SI 1 "general_operand" "viU") 413 (match_operand:SI 2 "general_operand" "vi"))) 414 (clobber (reg:HI AX_REG)) 415 (clobber (reg:HI BC_REG)) 416 ] 417 "RL78_MUL_G14" 418 "; G14 mulsi macro %0 = %1 * %2 419 movw ax, %h1 420 movw bc, %h2 421 MULHU ; bcax = bc * ax 422 movw %h0, ax 423 movw ax, bc 424 movw 0xffff0, ax 425 movw ax, %H1 426 movw bc, %h2 427 MACHU ; MACR += bc * ax 428 movw ax, %h1 429 movw bc, %H2 430 MACHU ; MACR += bc * ax 431 movw ax, 0xffff0 432 movw %H0, ax 433 ; end of mulsi macro" 434 [(set_attr "valloc" "macax")] 435 ) 436 437;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH. 438;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH. 439;; 0xF00E0 is MDCL. 0xF00E2 is MDCH. 440;; 0xF00E8 is MDUC. 441;; Warning: this matches the silicon not the documentation. 442(define_insn "mulsi3_g13" 443 [(set (match_operand:SI 0 "register_operand" "=&v") 444 (mult:SI (match_operand:SI 1 "general_operand" "viU") 445 (match_operand:SI 2 "general_operand" "viU"))) 446 (clobber (reg:HI AX_REG)) 447 (clobber (reg:HI BC_REG)) 448 ] 449 "RL78_MUL_G13" 450 "; G13 mulsi macro %0 = %1 * %2 451 mov a, #0x00 452 mov !0xf00e8, a ; MDUC 453 movw ax, %h1 454 movw 0xffff0, ax ; MDAL 455 movw ax, %h2 456 movw 0xffff2, ax ; MDAH 457 nop ; mdb = mdal * mdah 458 movw ax, 0xffff6 ; MDBL 459 movw %h0, ax 460 461 mov a, #0x40 462 mov !0xf00e8, a ; MDUC 463 movw ax, 0xffff4 ; MDBH 464 movw !0xf00e0, ax ; MDCL 465 movw ax, #0 466 movw !0xf00e2, ax ; MDCL 467 movw ax, %H1 468 movw 0xffff0, ax ; MDAL 469 movw ax, %h2 470 movw 0xffff2, ax ; MDAH 471 nop ; mdc += mdal * mdah 472 473 mov a, #0x40 474 mov !0xf00e8, a ; MDUC 475 movw ax, %h1 476 movw 0xffff0, ax ; MDAL 477 movw ax, %H2 478 movw 0xffff2, ax ; MDAH 479 nop ; mdc += mdal * mdah 480 nop ; Additional nop for MAC 481 movw ax, !0xf00e0 ; MDCL 482 movw %H0, ax 483 ; end of mulsi macro" 484 [(set_attr "valloc" "macax") 485 (set_attr "is_g13_muldiv_insn" "yes")] 486) 487 488(define_expand "udivmodhi4" 489 [(parallel 490 [(set (match_operand:HI 0 "register_operand") 491 (udiv:HI (match_operand:HI 1 "register_operand") 492 (match_operand:HI 2 "register_operand"))) 493 (set (match_operand:HI 3 "register_operand") 494 (umod:HI (match_dup 1) (match_dup 2))) 495 (clobber (reg:HI AX_REG)) 496 (clobber (reg:HI DE_REG)) 497 ]) 498 ] 499 "RL78_MUL_G14" 500 "" 501) 502 503(define_insn "*udivmodhi4_g14" 504 [(set (match_operand:HI 0 "register_operand" "=v") 505 (udiv:HI (match_operand:HI 1 "register_operand" "v") 506 (match_operand:HI 2 "register_operand" "v"))) 507 (set (match_operand:HI 3 "register_operand" "=v") 508 (umod:HI (match_dup 1) (match_dup 2))) 509 (clobber (reg:HI AX_REG)) 510 (clobber (reg:HI DE_REG)) 511 ] 512 "RL78_MUL_G14" 513 { 514 if (find_reg_note (insn, REG_UNUSED, operands[3])) 515 return "; G14 udivhi macro %0 = %1 / %2 \n\ 516 movw ax, %h1 \n\ 517 movw de, %h2 \n\ 518 push psw ; Save the current interrupt status \n\ 519 di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ 520 divhu ; ax = ax / de \n\ 521 pop psw ; Restore saved interrupt status \n\ 522 movw %h0, ax \n\ 523 ; end of udivhi macro"; 524 else if (find_reg_note (insn, REG_UNUSED, operands[0])) 525 return "; G14 umodhi macro %3 = %1 %% %2 \n\ 526 movw ax, %h1 \n\ 527 movw de, %h2 \n\ 528 push psw ; Save the current interrupt status \n\ 529 di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ 530 divhu ; de = ax %% de \n\ 531 pop psw ; Restore saved interrupt status \n\ 532 movw ax, de \n\ 533 movw %h3, ax \n\ 534 ; end of umodhi macro"; 535 else 536 return "; G14 udivmodhi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\ 537 movw ax, %h1 \n\ 538 movw de, %h2 \n\ 539 push psw ; Save the current interrupt status \n\ 540 di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ 541 divhu ; ax = ax / de, de = ax %% de \n\ 542 pop psw ; Restore saved interrupt status \n\ 543 movw %h0, ax \n\ 544 movw ax, de \n\ 545 movw %h3, ax \n\ 546 ; end of udivmodhi macro"; 547 } 548 [(set_attr "valloc" "divhi")] 549) 550 551(define_expand "udivmodsi4" 552 [(parallel 553 [(set (match_operand:SI 0 "register_operand") 554 (udiv:SI (match_operand:SI 1 "register_operand") 555 (match_operand:SI 2 "register_operand"))) 556 (set (match_operand:SI 3 "register_operand") 557 (umod:SI (match_dup 1) (match_dup 2))) 558 ]) 559 ] 560 "! RL78_MUL_NONE && ! optimize_size" 561 { 562 if (RL78_MUL_G14) 563 emit_insn (gen_udivmodsi4_g14 (operands[0], operands[1], operands[2], operands[3])); 564 else /* RL78_MUL_G13 */ 565 emit_insn (gen_udivmodsi4_g13 (operands[0], operands[1], operands[2], operands[3])); 566 DONE; 567 } 568) 569 570(define_insn "udivmodsi4_g14" 571 [(set (match_operand:SI 0 "register_operand" "=v") 572 (udiv:SI (match_operand:SI 1 "register_operand" "v") 573 (match_operand:SI 2 "register_operand" "v"))) 574 (set (match_operand:SI 3 "register_operand" "=v") 575 (umod:SI (match_dup 1) (match_dup 2))) 576 (clobber (reg:HI AX_REG)) 577 (clobber (reg:HI BC_REG)) 578 (clobber (reg:HI DE_REG)) 579 (clobber (reg:HI HL_REG)) 580 ] 581 "RL78_MUL_G14" 582 { 583 if (find_reg_note (insn, REG_UNUSED, operands[3])) 584 return "; G14 udivsi macro %0 = %1 / %2 \n\ 585 movw ax, %h1 \n\ 586 movw bc, %H1 \n\ 587 movw de, %h2 \n\ 588 movw hl, %H2 \n\ 589 push psw ; Save the current interrupt status \n\ 590 di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ 591 divwu ; bcax = bcax / hlde \n\ 592 pop psw ; Restore saved interrupt status \n\ 593 movw %h0, ax \n\ 594 movw ax, bc \n\ 595 movw %H0, ax \n\ 596 ; end of udivsi macro"; 597 else if (find_reg_note (insn, REG_UNUSED, operands[0])) 598 return "; G14 umodsi macro %3 = %1 %% %2 \n\ 599 movw ax, %h1 \n\ 600 movw bc, %H1 \n\ 601 movw de, %h2 \n\ 602 movw hl, %H2 \n\ 603 push psw ; Save the current interrupt status \n\ 604 di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ 605 divwu ; hlde = bcax %% hlde \n\ 606 pop psw ; Restore saved interrupt status \n\ 607 movw ax, de \n\ 608 movw %h3, ax \n\ 609 movw ax, hl \n\ 610 movw %H3, ax \n\ 611 ; end of umodsi macro"; 612 else 613 return "; G14 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\ 614 movw ax, %h1 \n\ 615 movw bc, %H1 \n\ 616 movw de, %h2 \n\ 617 movw hl, %H2 \n\ 618 push psw ; Save the current interrupt status \n\ 619 di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ 620 divwu ; bcax = bcax / hlde, hlde = bcax %% hlde \n\ 621 pop psw ; Restore saved interrupt status \n\ 622 movw %h0, ax \n\ 623 movw ax, bc \n\ 624 movw %H0, ax \n\ 625 movw ax, de \n\ 626 movw %h3, ax \n\ 627 movw ax, hl \n\ 628 movw %H3, ax \n\ 629 ; end of udivmodsi macro"; 630 } 631 [(set_attr "valloc" "divsi")] 632) 633 634;; Warning: these values match the silicon not the documentation. 635;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH. 636;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH. 637;; 0xF00E0 is MDCL. 0xF00E2 is MDCH. 638;; 0xF00E8 is MDUC. 639 640(define_insn "udivmodsi4_g13" 641 [(set (match_operand:SI 0 "register_operand" "=v") 642 (udiv:SI (match_operand:SI 1 "register_operand" "v") 643 (match_operand:SI 2 "register_operand" "v"))) 644 (set (match_operand:SI 3 "register_operand" "=v") 645 (umod:SI (match_dup 1) (match_dup 2))) 646 (clobber (reg:HI AX_REG)) 647 ] 648 "RL78_MUL_G13" 649 { 650 if (find_reg_note (insn, REG_UNUSED, operands[3])) 651 return "; G13 udivsi macro %0 = %1 / %2 \n\ 652 mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\ 653 mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\ 654 movw ax, %H1 \n\ 655 movw 0xffff2, ax ; MDAH \n\ 656 movw ax, %h1 \n\ 657 movw 0xffff0, ax ; MDAL \n\ 658 movw ax, %H2 \n\ 659 movw 0xffff4, ax ; MDBH \n\ 660 movw ax, %h2 \n\ 661 movw 0xffff6, ax ; MDBL \n\ 662 mov a, #0xC1 ; Set the DIVST bit in MDUC \n\ 663 mov !0xf00e8, a ; This starts the division op \n\ 6641: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\ 665 bt a.0, $1b \n\ 666 movw ax, 0xffff0 ; Read the quotient \n\ 667 movw %h0, ax \n\ 668 movw ax, 0xffff2 \n\ 669 movw %H0, ax \n\ 670 ; end of udivsi macro"; 671 else if (find_reg_note (insn, REG_UNUSED, operands[0])) 672 return "; G13 umodsi macro %3 = %1 %% %2 \n\ 673 mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\ 674 mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\ 675 movw ax, %H1 \n\ 676 movw 0xffff2, ax ; MDAH \n\ 677 movw ax, %h1 \n\ 678 movw 0xffff0, ax ; MDAL \n\ 679 movw ax, %H2 \n\ 680 movw 0xffff4, ax ; MDBH \n\ 681 movw ax, %h2 \n\ 682 movw 0xffff6, ax ; MDBL \n\ 683 mov a, #0xC1 ; Set the DIVST bit in MDUC \n\ 684 mov !0xf00e8, a ; This starts the division op \n\ 6851: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\ 686 bt a.0, $1b \n\ 687 movw ax, !0xf00e0 ; Read the remainder \n\ 688 movw %h3, ax \n\ 689 movw ax, !0xf00e2 \n\ 690 movw %H3, ax \n\ 691 ; end of umodsi macro"; 692 else 693 return "; G13 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\ 694 mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\ 695 mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\ 696 movw ax, %H1 \n\ 697 movw 0xffff2, ax ; MDAH \n\ 698 movw ax, %h1 \n\ 699 movw 0xffff0, ax ; MDAL \n\ 700 movw ax, %H2 \n\ 701 movw 0xffff4, ax ; MDBH \n\ 702 movw ax, %h2 \n\ 703 movw 0xffff6, ax ; MDBL \n\ 704 mov a, #0xC1 ; Set the DIVST bit in MDUC \n\ 705 mov !0xf00e8, a ; This starts the division op \n\ 7061: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\ 707 bt a.0, $1b \n\ 708 movw ax, 0xffff0 ; Read the quotient \n\ 709 movw %h0, ax \n\ 710 movw ax, 0xffff2 \n\ 711 movw %H0, ax \n\ 712 movw ax, !0xf00e0 ; Read the remainder \n\ 713 movw %h3, ax \n\ 714 movw ax, !0xf00e2 \n\ 715 movw %H3, ax \n\ 716 ; end of udivmodsi macro"; 717 } 718 [(set_attr "valloc" "macax") 719 (set_attr "is_g13_muldiv_insn" "yes")] 720) 721 722(define_expand "movdi" 723 [(set (match_operand:DI 0 "nonimmediate_operand" "") 724 (match_operand:DI 1 "general_operand" ""))] 725 "" 726 "rl78_split_movdi(operands, DImode); 727 DONE;" 728) 729 730(define_expand "movdf" 731 [(set (match_operand:DF 0 "nonimmediate_operand" "") 732 (match_operand:DF 1 "general_operand" ""))] 733 "" 734 "rl78_split_movdi(operands, DFmode); 735 DONE;" 736) 737 738(define_expand "umindi3" 739 [(set (match_operand:DI 0 "nonimmediate_operand" "") 740 (umin:DI (match_operand:DI 1 "general_operand" "") 741 (match_operand:DI 2 "general_operand" ""))) 742 ] 743 "optimize_size" 744 "rl78_emit_libcall (\"__umindi3\", UMIN, DImode, DImode, 3, operands); 745 DONE;" 746) 747 748(define_expand "umaxdi3" 749 [(set (match_operand:DI 0 "nonimmediate_operand" "") 750 (umax:DI (match_operand:DI 1 "general_operand" "") 751 (match_operand:DI 2 "general_operand" ""))) 752 ] 753 "optimize_size" 754 "rl78_emit_libcall (\"__umaxdi3\", UMAX, DImode, DImode, 3, operands); 755 DONE;" 756) 757 758(define_expand "smindi3" 759 [(set (match_operand:DI 0 "nonimmediate_operand" "") 760 (smin:DI (match_operand:DI 1 "general_operand" "") 761 (match_operand:DI 2 "general_operand" ""))) 762 ] 763 "optimize_size" 764 "rl78_emit_libcall (\"__smindi3\", SMIN, DImode, DImode, 3, operands); 765 DONE;" 766) 767 768(define_expand "smaxdi3" 769 [(set (match_operand:DI 0 "nonimmediate_operand" "") 770 (smax:DI (match_operand:DI 1 "general_operand" "") 771 (match_operand:DI 2 "general_operand" ""))) 772 ] 773 "optimize_size" 774 "rl78_emit_libcall (\"__smaxdi3\", SMAX, DImode, DImode, 3, operands); 775 DONE;" 776) 777 778(define_expand "anddi3" 779 [(set (match_operand:DI 0 "nonimmediate_operand" "") 780 (and:DI (match_operand:DI 1 "general_operand" "") 781 (match_operand:DI 2 "general_operand" ""))) 782 ] 783 "optimize_size" 784 "rl78_emit_libcall (\"__anddi3\", AND, DImode, DImode, 3, operands); 785 DONE;" 786) 787