2017-12-01 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / config / rl78 / rl78.md
blobc53ca0ff98d387a16a23a36e219f205be75e9571
1 ;;  Machine Description for Renesas RL78 processors
2 ;;  Copyright (C) 2011-2017 Free Software Foundation, Inc.
3 ;;  Contributed by Red Hat.
5 ;; This file is part of GCC.
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.
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.
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/>.
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)
36    (FP_REG 22)
37    (SP_REG 32)
38    (CC_REG 34)
39    (ES_REG 35)
40    (CS_REG 36)
42    (UNS_PROLOG  1)
43    (UNS_EPILOG  1)
44    (UNS_RETI    2)
45    (UNS_RETB    3)
47    (UNS_SET_RB  10)
48    (UNS_ES_ADDR 11)
50    (UNS_TRAMPOLINE_INIT         20)
51    (UNS_TRAMPOLINE_UNINIT       21)
52    (UNS_NONLOCAL_GOTO           22)
54    ])
56 (define_insn "nop"
57   [(const_int 0)]
58   ""
59   "nop"
60   )
62 (define_mode_iterator QHI [QI HI])
64 (include "predicates.md")
65 (include "constraints.md")
66 (include "rl78-expand.md")
67 (include "rl78-virt.md")
68 (include "rl78-real.md")
70 (define_attr "is_g13_muldiv_insn" "yes,no" (const_string "no"))
72 ;; Function Prologue/Epilogue Instructions
74 (define_expand "prologue"
75   [(const_int 0)]
76   ""
77   "rl78_expand_prologue (); DONE;"
80 (define_expand "epilogue"
81   [(const_int 0)]
82   ""
83   "rl78_expand_epilogue (); DONE;"
86 (define_expand "sibcall_epilogue"
87   [(return)]
88   ""
89   "FAIL;"
92 (define_insn "rl78_return"
93   [(return)]
94   ""
95   "ret"
98 (define_insn "interrupt_return"
99   [(unspec_volatile [(return)] UNS_RETI) ]
100   ""
101   "reti"
104 (define_insn "brk_interrupt_return"
105   [(unspec_volatile [(return)] UNS_RETB) ]
106   ""
107   "retb"
110 (define_expand "eh_return"
111   [(match_operand:HI 0 "")]
112   ""
113   "rl78_expand_eh_epilogue (operands[0]);
114    emit_barrier ();
115    DONE;"
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"
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"
144 (define_insn "sel_rb"
145   [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)]
146   "!TARGET_G10"
147   "sel\trb%u0"
148   )
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   )
160 (define_insn "trampoline_uninit"
161   [(unspec_volatile [(const_int 0)] UNS_TRAMPOLINE_UNINIT)
162    ]
163   ""
164   "call !!___trampoline_uninit"
165   )
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   )
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
202   )
204 (define_expand "es_addr"
205   [(unspec:SI [(reg:QI ES_REG)
206                (match_operand:HI 0 "")
207                ] UNS_ES_ADDR)]
208   ""
209   ""
212 ;;======================================================================
214 ;; "macro" insns - cases where inline chunks of code are more
215 ;; efficient than anything else.
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;"
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;"
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")]
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")]
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;"
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;"
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")]
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")]
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   ""
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   }
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   }
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")]
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")]
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")]
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   )
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
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
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")]
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   ""
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")]
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   }
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")]
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.
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\
664 1:      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\
685 1:      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\
706 1:      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")]