]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/rl78/rl78.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / rl78 / rl78.md
CommitLineData
78e515f7 1;; Machine Description for Renesas RL78 processors
fbd26352 2;; Copyright (C) 2011-2019 Free Software Foundation, Inc.
78e515f7 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\f
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)
3f3556f1 38 (CC_REG 34)
78e515f7 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)
563dc27b 48 (UNS_ES_ADDR 11)
78e515f7 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
dce5e16b 70(define_attr "is_g13_muldiv_insn" "yes,no" (const_string "no"))
78e515f7 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
edf1f7ba 92(define_insn "rl78_return"
78e515f7 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"
d1dc25ff 111 [(match_operand:HI 0 "")]
78e515f7 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)]
1d701d79 146 "!TARGET_G10"
78e515f7 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)
d1dc25ff 173 (unspec_volatile [(match_operand 0 "") ;; fp (ignore)
174 (match_operand 1 "") ;; target
175 (match_operand 2 "") ;; sp
176 (match_operand 3 "") ;; ?
78e515f7 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
d1dc25ff 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
78e515f7 212;;======================================================================
213;;
214;; "macro" insns - cases where inline chunks of code are more
215;; efficient than anything else.
216
217(define_expand "addsi3"
3f3556f1 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")))
78e515f7 221 ]
222 ""
3f3556f1 223 "emit_insn (gen_addsi3_internal_virt (operands[0], operands[1], operands[2]));
224 DONE;"
78e515f7 225)
226
99efc84b 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
3f3556f1 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))
78e515f7 243 ]
3f3556f1 244 "rl78_virt_insns_ok ()"
78e515f7 245 ""
3f3556f1 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 ()"
95328f38 257 { return rl78_addsi3_internal (operands, which_alternative); }
3f3556f1 258 [(set_attr "valloc" "macax")]
259)
260
261(define_expand "subsi3"
d1dc25ff 262 [(set (match_operand:SI 0 "nonimmediate_operand")
263 (minus:SI (match_operand:SI 1 "general_operand")
264 (match_operand 2 "general_operand")))
3f3556f1 265 ]
266 ""
267 "emit_insn (gen_subsi3_internal_virt (operands[0], operands[1], operands[2]));
268 DONE;"
269)
270
020b1a05 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
3f3556f1 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"
78e515f7 305 [(set_attr "valloc" "macax")]
306)
307
789a3e1c 308(define_expand "mulqi3"
e98e1692 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 ]
789a3e1c 316 "" ; mulu supported by all targets
317 ""
318)
319
320(define_expand "mulhi3"
d1dc25ff 321 [(set (match_operand:HI 0 "register_operand")
322 (mult:HI (match_operand:HI 1 "general_operand")
323 (match_operand:HI 2 "nonmemory_operand")))
789a3e1c 324 ]
325 "! RL78_MUL_NONE"
e98e1692 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 }
789a3e1c 333)
334
78e515f7 335(define_expand "mulsi3"
d1dc25ff 336 [(set (match_operand:SI 0 "register_operand")
337 (mult:SI (match_operand:SI 1 "general_operand")
338 (match_operand:SI 2 "nonmemory_operand")))
78e515f7 339 ]
340 "! RL78_MUL_NONE"
e98e1692 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 }
78e515f7 348)
349
789a3e1c 350(define_insn "*mulqi3_rl78"
351 [(set (match_operand:QI 0 "register_operand" "=&v")
d1dc25ff 352 (mult:QI (match_operand:QI 1 "general_operand" "viU")
789a3e1c 353 (match_operand:QI 2 "general_operand" "vi")))
e98e1692 354 (clobber (reg:HI AX_REG))
355 ]
789a3e1c 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"
e98e1692 365 [(set_attr "valloc" "macax")]
789a3e1c 366)
367
e98e1692 368(define_insn "mulhi3_g14"
789a3e1c 369 [(set (match_operand:HI 0 "register_operand" "=&v")
d1dc25ff 370 (mult:HI (match_operand:HI 1 "general_operand" "viU")
789a3e1c 371 (match_operand:HI 2 "general_operand" "vi")))
e98e1692 372 (clobber (reg:HI AX_REG))
373 (clobber (reg:HI BC_REG))
374 ]
375 "RL78_MUL_G14"
376 "; G14 mulhi macro %0 = %1 * %2
789a3e1c 377 movw ax, %h1
378 movw bc, %h2
379 mulhu ; bcax = bc * ax
380 movw %h0, ax
381 ; end of mulhi macro"
e98e1692 382 [(set_attr "valloc" "macax")]
789a3e1c 383)
384
e98e1692 385(define_insn "mulhi3_g13"
789a3e1c 386 [(set (match_operand:HI 0 "register_operand" "=&v")
d1dc25ff 387 (mult:HI (match_operand:HI 1 "general_operand" "viU")
789a3e1c 388 (match_operand:HI 2 "general_operand" "vi")))
e98e1692 389 (clobber (reg:HI AX_REG))
390 ]
789a3e1c 391 "RL78_MUL_G13"
e98e1692 392 "; G13 mulhi macro %0 = %1 * %2
789a3e1c 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"
dce5e16b 403 [(set_attr "valloc" "macax")
404 (set_attr "is_g13_muldiv_insn" "yes")]
789a3e1c 405)
406
78e515f7 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).
e98e1692 410(define_insn "mulsi3_g14"
78e515f7 411 [(set (match_operand:SI 0 "register_operand" "=&v")
d1dc25ff 412 (mult:SI (match_operand:SI 1 "general_operand" "viU")
3f3556f1 413 (match_operand:SI 2 "general_operand" "vi")))
e98e1692 414 (clobber (reg:HI AX_REG))
415 (clobber (reg:HI BC_REG))
416 ]
417 "RL78_MUL_G14"
418 "; G14 mulsi macro %0 = %1 * %2
78e515f7 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.
50008a8e 438;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH.
78e515f7 439;; 0xF00E0 is MDCL. 0xF00E2 is MDCH.
440;; 0xF00E8 is MDUC.
50008a8e 441;; Warning: this matches the silicon not the documentation.
78e515f7 442(define_insn "mulsi3_g13"
443 [(set (match_operand:SI 0 "register_operand" "=&v")
3f3556f1 444 (mult:SI (match_operand:SI 1 "general_operand" "viU")
445 (match_operand:SI 2 "general_operand" "viU")))
e98e1692 446 (clobber (reg:HI AX_REG))
447 (clobber (reg:HI BC_REG))
448 ]
78e515f7 449 "RL78_MUL_G13"
e98e1692 450 "; G13 mulsi macro %0 = %1 * %2
78e515f7 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
50008a8e 458 movw ax, 0xffff6 ; MDBL
78e515f7 459 movw %h0, ax
460
461 mov a, #0x40
462 mov !0xf00e8, a ; MDUC
50008a8e 463 movw ax, 0xffff4 ; MDBH
78e515f7 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
57518f85 480 nop ; Additional nop for MAC
78e515f7 481 movw ax, !0xf00e0 ; MDCL
482 movw %H0, ax
483 ; end of mulsi macro"
dce5e16b 484 [(set_attr "valloc" "macax")
485 (set_attr "is_g13_muldiv_insn" "yes")]
563dc27b 486)
e98e1692 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 }
dce5e16b 718 [(set_attr "valloc" "macax")
719 (set_attr "is_g13_muldiv_insn" "yes")]
e98e1692 720)
f77335d9 721
ce8becce 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
c12ddda4 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
a2618819 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
f77335d9 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)
de5538ce 757
14920f56 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
de5538ce 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)
e1192dcf 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)