Mercurial > hg > CbC > CbC_gcc
diff gcc/config/rl78/rl78.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/config/rl78/rl78.md Fri Oct 27 22:46:09 2017 +0900 @@ -0,0 +1,720 @@ +;; Machine Description for Renesas RL78 processors +;; Copyright (C) 2011-2017 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")] +)