;; Machine Description for Renesas RL78 processors
;; Copyright (C) 2011-2020 Free Software Foundation, Inc.
;; Contributed by Red Hat.
;; This file is part of GCC.
;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
(define_constants
[
(AX_REG 0)
(X_REG 0)
(A_REG 1)
(BC_REG 2)
(C_REG 2)
(B_REG 3)
(DE_REG 4)
(E_REG 4)
(D_REG 5)
(HL_REG 6)
(L_REG 6)
(H_REG 7)
(FP_REG 22)
(SP_REG 32)
(CC_REG 34)
(ES_REG 35)
(CS_REG 36)
(UNS_PROLOG 1)
(UNS_EPILOG 1)
(UNS_RETI 2)
(UNS_RETB 3)
(UNS_SET_RB 10)
(UNS_ES_ADDR 11)
(UNS_TRAMPOLINE_INIT 20)
(UNS_TRAMPOLINE_UNINIT 21)
(UNS_NONLOCAL_GOTO 22)
])
(define_insn "nop"
[(const_int 0)]
""
"nop"
)
(define_mode_iterator QHI [QI HI])
(include "predicates.md")
(include "constraints.md")
(include "rl78-expand.md")
(include "rl78-virt.md")
(include "rl78-real.md")
(define_attr "is_g13_muldiv_insn" "yes,no" (const_string "no"))
;; Function Prologue/Epilogue Instructions
(define_expand "prologue"
[(const_int 0)]
""
"rl78_expand_prologue (); DONE;"
)
(define_expand "epilogue"
[(const_int 0)]
""
"rl78_expand_epilogue (); DONE;"
)
(define_expand "sibcall_epilogue"
[(return)]
""
"FAIL;"
)
(define_insn "rl78_return"
[(return)]
""
"ret"
)
(define_insn "interrupt_return"
[(unspec_volatile [(return)] UNS_RETI) ]
""
"reti"
)
(define_insn "brk_interrupt_return"
[(unspec_volatile [(return)] UNS_RETB) ]
""
"retb"
)
(define_expand "eh_return"
[(match_operand:HI 0 "")]
""
"rl78_expand_eh_epilogue (operands[0]);
emit_barrier ();
DONE;"
)
;; These are used only by prologue/epilogue so it's "safe" to pass
;; virtual registers.
(define_insn "push"
[(set (reg:HI SP_REG)
(plus:HI (reg:HI SP_REG)
(const_int -2)))
(set (mem:HI (reg:HI SP_REG))
(match_operand:HI 0 "register_operand" "ABDT,vZint"))]
""
"@
push\t%v0
push\t%v0 ; %0"
)
(define_insn "pop"
[(set (match_operand:HI 0 "register_operand" "=ABDT,vZint")
(mem:HI (reg:HI SP_REG)))
(set (reg:HI SP_REG)
(plus:HI (reg:HI SP_REG)
(const_int 2)))]
""
"@
pop\t%v0
pop\t%v0 ; %0"
)
(define_insn "sel_rb"
[(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)]
"!TARGET_G10"
"sel\trb%u0"
)
(define_insn "trampoline_init"
[(set (match_operand 0 "register_operand" "=Z08W")
(unspec_volatile [(match_operand 1 "register_operand" "Z08W")
(match_operand 2 "register_operand" "Z10W")
] UNS_TRAMPOLINE_INIT))
]
""
"call !!___trampoline_init ; %0 <= %1 %2"
)
(define_insn "trampoline_uninit"
[(unspec_volatile [(const_int 0)] UNS_TRAMPOLINE_UNINIT)
]
""
"call !!___trampoline_uninit"
)
;; GCC restores $fp *before* using it to access values on the *old*
;; frame. So, we do it ourselves, to ensure this is not the case.
;; Note that while %1 is usually a label_ref, we allow for a
;; non-immediate as well.
(define_expand "nonlocal_goto"
[(set (pc)
(unspec_volatile [(match_operand 0 "") ;; fp (ignore)
(match_operand 1 "") ;; target
(match_operand 2 "") ;; sp
(match_operand 3 "") ;; ?
] UNS_NONLOCAL_GOTO))
]
""
"emit_jump_insn (gen_nonlocal_goto_insn (operands[0], operands[1], operands[2], operands[3]));
emit_barrier ();
DONE;"
)
(define_insn "nonlocal_goto_insn"
[(set (pc)
(unspec_volatile [(match_operand 0 "" "") ;; fp (ignore)
(match_operand 1 "" "vi") ;; target
(match_operand 2 "" "vi") ;; sp
(match_operand 3 "" "vi") ;; ?
] UNS_NONLOCAL_GOTO))
]
""
"; nonlocal goto
movw ax, %3
movw r22, ax
movw ax, %2
movw sp, ax
movw ax, %1
br ax
"
)
(define_expand "es_addr"
[(unspec:SI [(reg:QI ES_REG)
(match_operand:HI 0 "")
] UNS_ES_ADDR)]
""
""
)
;;======================================================================
;;
;; "macro" insns - cases where inline chunks of code are more
;; efficient than anything else.
(define_expand "addsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=&vm")
(plus:SI (match_operand:SI 1 "general_operand" "vim")
(match_operand 2 "general_operand" "vim")))
]
""
"emit_insn (gen_addsi3_internal_virt (operands[0], operands[1], operands[2]));
DONE;"
)
(define_expand "adddi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(plus:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
""
"rl78_emit_libcall (\"__adddi3\", PLUS, DImode, DImode, 3, operands);
DONE;"
)
(define_insn "addsi3_internal_virt"
[(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm")
(plus:SI (match_operand:SI 1 "general_operand" "0, vim, vim")
(match_operand 2 "general_operand" "vim,vim,vim")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"rl78_virt_insns_ok ()"
""
[(set_attr "valloc" "macax")]
)
(define_insn "addsi3_internal_real"
[(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU")
(plus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU")
(match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"rl78_real_insns_ok ()"
{ return rl78_addsi3_internal (operands, which_alternative); }
[(set_attr "valloc" "macax")]
)
(define_expand "subsi3"
[(set (match_operand:SI 0 "nonimmediate_operand")
(minus:SI (match_operand:SI 1 "general_operand")
(match_operand 2 "general_operand")))
]
""
"emit_insn (gen_subsi3_internal_virt (operands[0], operands[1], operands[2]));
DONE;"
)
(define_expand "subdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(minus:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
""
"rl78_emit_libcall (\"__subdi3\", MINUS, DImode, DImode, 3, operands);
DONE;"
)
(define_insn "subsi3_internal_virt"
[(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm")
(minus:SI (match_operand:SI 1 "general_operand" "0, vim, vim")
(match_operand 2 "general_operand" "vim,vim,vim")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"rl78_virt_insns_ok ()"
""
[(set_attr "valloc" "macax")]
)
(define_insn "subsi3_internal_real"
[(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU")
(minus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU")
(match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"rl78_real_insns_ok ()"
"@
movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax
movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax
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"
[(set_attr "valloc" "macax")]
)
(define_expand "mulqi3"
[(parallel
[(set (match_operand:QI 0 "register_operand")
(mult:QI (match_operand:QI 1 "general_operand")
(match_operand:QI 2 "nonmemory_operand")))
(clobber (reg:HI AX_REG))
])
]
"" ; mulu supported by all targets
""
)
(define_expand "mulhi3"
[(set (match_operand:HI 0 "register_operand")
(mult:HI (match_operand:HI 1 "general_operand")
(match_operand:HI 2 "nonmemory_operand")))
]
"! RL78_MUL_NONE"
{
if (RL78_MUL_G14)
emit_insn (gen_mulhi3_g14 (operands[0], operands[1], operands[2]));
else /* RL78_MUL_G13 */
emit_insn (gen_mulhi3_g13 (operands[0], operands[1], operands[2]));
DONE;
}
)
(define_expand "mulsi3"
[(set (match_operand:SI 0 "register_operand")
(mult:SI (match_operand:SI 1 "general_operand")
(match_operand:SI 2 "nonmemory_operand")))
]
"! RL78_MUL_NONE"
{
if (RL78_MUL_G14)
emit_insn (gen_mulsi3_g14 (operands[0], operands[1], operands[2]));
else /* RL78_MUL_G13 */
emit_insn (gen_mulsi3_g13 (operands[0], operands[1], operands[2]));
DONE;
}
)
(define_insn "*mulqi3_rl78"
[(set (match_operand:QI 0 "register_operand" "=&v")
(mult:QI (match_operand:QI 1 "general_operand" "viU")
(match_operand:QI 2 "general_operand" "vi")))
(clobber (reg:HI AX_REG))
]
"" ; mulu supported by all targets
"; mulqi macro %0 = %1 * %2
mov a, %h1
mov x, a
mov a, %h2
mulu x ; ax = a * x
mov a, x
mov %h0, a
; end of mulqi macro"
[(set_attr "valloc" "macax")]
)
(define_insn "mulhi3_g14"
[(set (match_operand:HI 0 "register_operand" "=&v")
(mult:HI (match_operand:HI 1 "general_operand" "viU")
(match_operand:HI 2 "general_operand" "vi")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"RL78_MUL_G14"
"; G14 mulhi macro %0 = %1 * %2
movw ax, %h1
movw bc, %h2
mulhu ; bcax = bc * ax
movw %h0, ax
; end of mulhi macro"
[(set_attr "valloc" "macax")]
)
(define_insn "mulhi3_g13"
[(set (match_operand:HI 0 "register_operand" "=&v")
(mult:HI (match_operand:HI 1 "general_operand" "viU")
(match_operand:HI 2 "general_operand" "vi")))
(clobber (reg:HI AX_REG))
]
"RL78_MUL_G13"
"; G13 mulhi macro %0 = %1 * %2
mov a, #0x00
mov !0xf00e8, a ; MDUC
movw ax, %h1
movw 0xffff0, ax ; MDAL
movw ax, %h2
movw 0xffff2, ax ; MDAH
nop ; mdb = mdal * mdah
movw ax, 0xffff6 ; MDBL
movw %h0, ax
; end of mulhi macro"
[(set_attr "valloc" "macax")
(set_attr "is_g13_muldiv_insn" "yes")]
)
;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it
;; because we're only using the lower 16 bits (which is the upper 16
;; bits of the result).
(define_insn "mulsi3_g14"
[(set (match_operand:SI 0 "register_operand" "=&v")
(mult:SI (match_operand:SI 1 "general_operand" "viU")
(match_operand:SI 2 "general_operand" "vi")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"RL78_MUL_G14"
"; G14 mulsi macro %0 = %1 * %2
movw ax, %h1
movw bc, %h2
MULHU ; bcax = bc * ax
movw %h0, ax
movw ax, bc
movw 0xffff0, ax
movw ax, %H1
movw bc, %h2
MACHU ; MACR += bc * ax
movw ax, %h1
movw bc, %H2
MACHU ; MACR += bc * ax
movw ax, 0xffff0
movw %H0, ax
; end of mulsi macro"
[(set_attr "valloc" "macax")]
)
;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH.
;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH.
;; 0xF00E0 is MDCL. 0xF00E2 is MDCH.
;; 0xF00E8 is MDUC.
;; Warning: this matches the silicon not the documentation.
(define_insn "mulsi3_g13"
[(set (match_operand:SI 0 "register_operand" "=&v")
(mult:SI (match_operand:SI 1 "general_operand" "viU")
(match_operand:SI 2 "general_operand" "viU")))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
]
"RL78_MUL_G13"
"; G13 mulsi macro %0 = %1 * %2
mov a, #0x00
mov !0xf00e8, a ; MDUC
movw ax, %h1
movw 0xffff0, ax ; MDAL
movw ax, %h2
movw 0xffff2, ax ; MDAH
nop ; mdb = mdal * mdah
movw ax, 0xffff6 ; MDBL
movw %h0, ax
mov a, #0x40
mov !0xf00e8, a ; MDUC
movw ax, 0xffff4 ; MDBH
movw !0xf00e0, ax ; MDCL
movw ax, #0
movw !0xf00e2, ax ; MDCL
movw ax, %H1
movw 0xffff0, ax ; MDAL
movw ax, %h2
movw 0xffff2, ax ; MDAH
nop ; mdc += mdal * mdah
mov a, #0x40
mov !0xf00e8, a ; MDUC
movw ax, %h1
movw 0xffff0, ax ; MDAL
movw ax, %H2
movw 0xffff2, ax ; MDAH
nop ; mdc += mdal * mdah
nop ; Additional nop for MAC
movw ax, !0xf00e0 ; MDCL
movw %H0, ax
; end of mulsi macro"
[(set_attr "valloc" "macax")
(set_attr "is_g13_muldiv_insn" "yes")]
)
(define_expand "udivmodhi4"
[(parallel
[(set (match_operand:HI 0 "register_operand")
(udiv:HI (match_operand:HI 1 "register_operand")
(match_operand:HI 2 "register_operand")))
(set (match_operand:HI 3 "register_operand")
(umod:HI (match_dup 1) (match_dup 2)))
(clobber (reg:HI AX_REG))
(clobber (reg:HI DE_REG))
])
]
"RL78_MUL_G14"
""
)
(define_insn "*udivmodhi4_g14"
[(set (match_operand:HI 0 "register_operand" "=v")
(udiv:HI (match_operand:HI 1 "register_operand" "v")
(match_operand:HI 2 "register_operand" "v")))
(set (match_operand:HI 3 "register_operand" "=v")
(umod:HI (match_dup 1) (match_dup 2)))
(clobber (reg:HI AX_REG))
(clobber (reg:HI DE_REG))
]
"RL78_MUL_G14"
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "; G14 udivhi macro %0 = %1 / %2 \n\
movw ax, %h1 \n\
movw de, %h2 \n\
push psw ; Save the current interrupt status \n\
di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
divhu ; ax = ax / de \n\
pop psw ; Restore saved interrupt status \n\
movw %h0, ax \n\
; end of udivhi macro";
else if (find_reg_note (insn, REG_UNUSED, operands[0]))
return "; G14 umodhi macro %3 = %1 %% %2 \n\
movw ax, %h1 \n\
movw de, %h2 \n\
push psw ; Save the current interrupt status \n\
di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
divhu ; de = ax %% de \n\
pop psw ; Restore saved interrupt status \n\
movw ax, de \n\
movw %h3, ax \n\
; end of umodhi macro";
else
return "; G14 udivmodhi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\
movw ax, %h1 \n\
movw de, %h2 \n\
push psw ; Save the current interrupt status \n\
di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
divhu ; ax = ax / de, de = ax %% de \n\
pop psw ; Restore saved interrupt status \n\
movw %h0, ax \n\
movw ax, de \n\
movw %h3, ax \n\
; end of udivmodhi macro";
}
[(set_attr "valloc" "divhi")]
)
(define_expand "udivmodsi4"
[(parallel
[(set (match_operand:SI 0 "register_operand")
(udiv:SI (match_operand:SI 1 "register_operand")
(match_operand:SI 2 "register_operand")))
(set (match_operand:SI 3 "register_operand")
(umod:SI (match_dup 1) (match_dup 2)))
])
]
"! RL78_MUL_NONE && ! optimize_size"
{
if (RL78_MUL_G14)
emit_insn (gen_udivmodsi4_g14 (operands[0], operands[1], operands[2], operands[3]));
else /* RL78_MUL_G13 */
emit_insn (gen_udivmodsi4_g13 (operands[0], operands[1], operands[2], operands[3]));
DONE;
}
)
(define_insn "udivmodsi4_g14"
[(set (match_operand:SI 0 "register_operand" "=v")
(udiv:SI (match_operand:SI 1 "register_operand" "v")
(match_operand:SI 2 "register_operand" "v")))
(set (match_operand:SI 3 "register_operand" "=v")
(umod:SI (match_dup 1) (match_dup 2)))
(clobber (reg:HI AX_REG))
(clobber (reg:HI BC_REG))
(clobber (reg:HI DE_REG))
(clobber (reg:HI HL_REG))
]
"RL78_MUL_G14"
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "; G14 udivsi macro %0 = %1 / %2 \n\
movw ax, %h1 \n\
movw bc, %H1 \n\
movw de, %h2 \n\
movw hl, %H2 \n\
push psw ; Save the current interrupt status \n\
di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
divwu ; bcax = bcax / hlde \n\
pop psw ; Restore saved interrupt status \n\
movw %h0, ax \n\
movw ax, bc \n\
movw %H0, ax \n\
; end of udivsi macro";
else if (find_reg_note (insn, REG_UNUSED, operands[0]))
return "; G14 umodsi macro %3 = %1 %% %2 \n\
movw ax, %h1 \n\
movw bc, %H1 \n\
movw de, %h2 \n\
movw hl, %H2 \n\
push psw ; Save the current interrupt status \n\
di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
divwu ; hlde = bcax %% hlde \n\
pop psw ; Restore saved interrupt status \n\
movw ax, de \n\
movw %h3, ax \n\
movw ax, hl \n\
movw %H3, ax \n\
; end of umodsi macro";
else
return "; G14 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\
movw ax, %h1 \n\
movw bc, %H1 \n\
movw de, %h2 \n\
movw hl, %H2 \n\
push psw ; Save the current interrupt status \n\
di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
divwu ; bcax = bcax / hlde, hlde = bcax %% hlde \n\
pop psw ; Restore saved interrupt status \n\
movw %h0, ax \n\
movw ax, bc \n\
movw %H0, ax \n\
movw ax, de \n\
movw %h3, ax \n\
movw ax, hl \n\
movw %H3, ax \n\
; end of udivmodsi macro";
}
[(set_attr "valloc" "divsi")]
)
;; Warning: these values match the silicon not the documentation.
;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH.
;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH.
;; 0xF00E0 is MDCL. 0xF00E2 is MDCH.
;; 0xF00E8 is MDUC.
(define_insn "udivmodsi4_g13"
[(set (match_operand:SI 0 "register_operand" "=v")
(udiv:SI (match_operand:SI 1 "register_operand" "v")
(match_operand:SI 2 "register_operand" "v")))
(set (match_operand:SI 3 "register_operand" "=v")
(umod:SI (match_dup 1) (match_dup 2)))
(clobber (reg:HI AX_REG))
]
"RL78_MUL_G13"
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "; G13 udivsi macro %0 = %1 / %2 \n\
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\
mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\
movw ax, %H1 \n\
movw 0xffff2, ax ; MDAH \n\
movw ax, %h1 \n\
movw 0xffff0, ax ; MDAL \n\
movw ax, %H2 \n\
movw 0xffff4, ax ; MDBH \n\
movw ax, %h2 \n\
movw 0xffff6, ax ; MDBL \n\
mov a, #0xC1 ; Set the DIVST bit in MDUC \n\
mov !0xf00e8, a ; This starts the division op \n\
1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\
bt a.0, $1b \n\
movw ax, 0xffff0 ; Read the quotient \n\
movw %h0, ax \n\
movw ax, 0xffff2 \n\
movw %H0, ax \n\
; end of udivsi macro";
else if (find_reg_note (insn, REG_UNUSED, operands[0]))
return "; G13 umodsi macro %3 = %1 %% %2 \n\
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\
mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\
movw ax, %H1 \n\
movw 0xffff2, ax ; MDAH \n\
movw ax, %h1 \n\
movw 0xffff0, ax ; MDAL \n\
movw ax, %H2 \n\
movw 0xffff4, ax ; MDBH \n\
movw ax, %h2 \n\
movw 0xffff6, ax ; MDBL \n\
mov a, #0xC1 ; Set the DIVST bit in MDUC \n\
mov !0xf00e8, a ; This starts the division op \n\
1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\
bt a.0, $1b \n\
movw ax, !0xf00e0 ; Read the remainder \n\
movw %h3, ax \n\
movw ax, !0xf00e2 \n\
movw %H3, ax \n\
; end of umodsi macro";
else
return "; G13 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\
mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\
movw ax, %H1 \n\
movw 0xffff2, ax ; MDAH \n\
movw ax, %h1 \n\
movw 0xffff0, ax ; MDAL \n\
movw ax, %H2 \n\
movw 0xffff4, ax ; MDBH \n\
movw ax, %h2 \n\
movw 0xffff6, ax ; MDBL \n\
mov a, #0xC1 ; Set the DIVST bit in MDUC \n\
mov !0xf00e8, a ; This starts the division op \n\
1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\
bt a.0, $1b \n\
movw ax, 0xffff0 ; Read the quotient \n\
movw %h0, ax \n\
movw ax, 0xffff2 \n\
movw %H0, ax \n\
movw ax, !0xf00e0 ; Read the remainder \n\
movw %h3, ax \n\
movw ax, !0xf00e2 \n\
movw %H3, ax \n\
; end of udivmodsi macro";
}
[(set_attr "valloc" "macax")
(set_attr "is_g13_muldiv_insn" "yes")]
)
(define_expand "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"rl78_split_movdi(operands, DImode);
DONE;"
)
(define_expand "movdf"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"rl78_split_movdi(operands, DFmode);
DONE;"
)
(define_expand "umindi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(umin:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
"optimize_size"
"rl78_emit_libcall (\"__umindi3\", UMIN, DImode, DImode, 3, operands);
DONE;"
)
(define_expand "umaxdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(umax:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
"optimize_size"
"rl78_emit_libcall (\"__umaxdi3\", UMAX, DImode, DImode, 3, operands);
DONE;"
)
(define_expand "smindi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(smin:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
"optimize_size"
"rl78_emit_libcall (\"__smindi3\", SMIN, DImode, DImode, 3, operands);
DONE;"
)
(define_expand "smaxdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(smax:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
"optimize_size"
"rl78_emit_libcall (\"__smaxdi3\", SMAX, DImode, DImode, 3, operands);
DONE;"
)
(define_expand "anddi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(and:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))
]
"optimize_size"
"rl78_emit_libcall (\"__anddi3\", AND, DImode, DImode, 3, operands);
DONE;"
)