Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/rl78/rl78.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ;; Machine Description for Renesas RL78 processors | |
2 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. | |
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 ) |