111
|
1 ;; Machine Description for Renesas RL78 processors
|
145
|
2 ;; Copyright (C) 2011-2020 Free Software Foundation, Inc.
|
111
|
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\
|
|
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")]
|
|
720 )
|
131
|
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 )
|