]>
Commit | Line | Data |
---|---|---|
78e515f7 | 1 | ;; Machine Description for Renesas RL78 processors |
f1717362 | 2 | ;; Copyright (C) 2011-2016 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 | ||
70 | ||
71 | ;; Function Prologue/Epilogue Instructions | |
72 | ||
73 | (define_expand "prologue" | |
74 | [(const_int 0)] | |
75 | "" | |
76 | "rl78_expand_prologue (); DONE;" | |
77 | ) | |
78 | ||
79 | (define_expand "epilogue" | |
80 | [(const_int 0)] | |
81 | "" | |
82 | "rl78_expand_epilogue (); DONE;" | |
83 | ) | |
84 | ||
85 | (define_expand "sibcall_epilogue" | |
86 | [(return)] | |
87 | "" | |
88 | "FAIL;" | |
89 | ) | |
90 | ||
edf1f7ba | 91 | (define_insn "rl78_return" |
78e515f7 | 92 | [(return)] |
93 | "" | |
94 | "ret" | |
95 | ) | |
96 | ||
97 | (define_insn "interrupt_return" | |
98 | [(unspec_volatile [(return)] UNS_RETI) ] | |
99 | "" | |
100 | "reti" | |
101 | ) | |
102 | ||
103 | (define_insn "brk_interrupt_return" | |
104 | [(unspec_volatile [(return)] UNS_RETB) ] | |
105 | "" | |
106 | "retb" | |
107 | ) | |
108 | ||
109 | (define_expand "eh_return" | |
d1dc25ff | 110 | [(match_operand:HI 0 "")] |
78e515f7 | 111 | "" |
112 | "rl78_expand_eh_epilogue (operands[0]); | |
113 | emit_barrier (); | |
114 | DONE;" | |
115 | ) | |
116 | ||
117 | ;; These are used only by prologue/epilogue so it's "safe" to pass | |
118 | ;; virtual registers. | |
119 | (define_insn "push" | |
120 | [(set (reg:HI SP_REG) | |
121 | (plus:HI (reg:HI SP_REG) | |
122 | (const_int -2))) | |
123 | (set (mem:HI (reg:HI SP_REG)) | |
124 | (match_operand:HI 0 "register_operand" "ABDT,vZint"))] | |
125 | "" | |
126 | "@ | |
127 | push\t%v0 | |
128 | push\t%v0 ; %0" | |
129 | ) | |
130 | ||
131 | (define_insn "pop" | |
132 | [(set (match_operand:HI 0 "register_operand" "=ABDT,vZint") | |
133 | (mem:HI (reg:HI SP_REG))) | |
134 | (set (reg:HI SP_REG) | |
135 | (plus:HI (reg:HI SP_REG) | |
136 | (const_int 2)))] | |
137 | "" | |
138 | "@ | |
139 | pop\t%v0 | |
140 | pop\t%v0 ; %0" | |
141 | ) | |
142 | ||
143 | (define_insn "sel_rb" | |
144 | [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)] | |
1d701d79 | 145 | "!TARGET_G10" |
78e515f7 | 146 | "sel\trb%u0" |
147 | ) | |
148 | ||
149 | (define_insn "trampoline_init" | |
150 | [(set (match_operand 0 "register_operand" "=Z08W") | |
151 | (unspec_volatile [(match_operand 1 "register_operand" "Z08W") | |
152 | (match_operand 2 "register_operand" "Z10W") | |
153 | ] UNS_TRAMPOLINE_INIT)) | |
154 | ] | |
155 | "" | |
156 | "call !!___trampoline_init ; %0 <= %1 %2" | |
157 | ) | |
158 | ||
159 | (define_insn "trampoline_uninit" | |
160 | [(unspec_volatile [(const_int 0)] UNS_TRAMPOLINE_UNINIT) | |
161 | ] | |
162 | "" | |
163 | "call !!___trampoline_uninit" | |
164 | ) | |
165 | ||
166 | ;; GCC restores $fp *before* using it to access values on the *old* | |
167 | ;; frame. So, we do it ourselves, to ensure this is not the case. | |
168 | ;; Note that while %1 is usually a label_ref, we allow for a | |
169 | ;; non-immediate as well. | |
170 | (define_expand "nonlocal_goto" | |
171 | [(set (pc) | |
d1dc25ff | 172 | (unspec_volatile [(match_operand 0 "") ;; fp (ignore) |
173 | (match_operand 1 "") ;; target | |
174 | (match_operand 2 "") ;; sp | |
175 | (match_operand 3 "") ;; ? | |
78e515f7 | 176 | ] UNS_NONLOCAL_GOTO)) |
177 | ] | |
178 | "" | |
179 | "emit_jump_insn (gen_nonlocal_goto_insn (operands[0], operands[1], operands[2], operands[3])); | |
180 | emit_barrier (); | |
181 | DONE;" | |
182 | ) | |
183 | ||
184 | (define_insn "nonlocal_goto_insn" | |
185 | [(set (pc) | |
186 | (unspec_volatile [(match_operand 0 "" "") ;; fp (ignore) | |
187 | (match_operand 1 "" "vi") ;; target | |
188 | (match_operand 2 "" "vi") ;; sp | |
189 | (match_operand 3 "" "vi") ;; ? | |
190 | ] UNS_NONLOCAL_GOTO)) | |
191 | ] | |
192 | "" | |
193 | "; nonlocal goto | |
194 | movw ax, %3 | |
195 | movw r22, ax | |
196 | movw ax, %2 | |
197 | movw sp, ax | |
198 | movw ax, %1 | |
199 | br ax | |
200 | " | |
201 | ) | |
202 | ||
d1dc25ff | 203 | (define_expand "es_addr" |
204 | [(unspec:SI [(reg:QI ES_REG) | |
205 | (match_operand:HI 0 "") | |
206 | ] UNS_ES_ADDR)] | |
207 | "" | |
208 | "" | |
209 | ) | |
210 | ||
78e515f7 | 211 | ;;====================================================================== |
212 | ;; | |
213 | ;; "macro" insns - cases where inline chunks of code are more | |
214 | ;; efficient than anything else. | |
215 | ||
216 | (define_expand "addsi3" | |
3f3556f1 | 217 | [(set (match_operand:SI 0 "nonimmediate_operand" "=&vm") |
218 | (plus:SI (match_operand:SI 1 "general_operand" "vim") | |
219 | (match_operand 2 "general_operand" "vim"))) | |
78e515f7 | 220 | ] |
221 | "" | |
3f3556f1 | 222 | "emit_insn (gen_addsi3_internal_virt (operands[0], operands[1], operands[2])); |
223 | DONE;" | |
78e515f7 | 224 | ) |
225 | ||
3f3556f1 | 226 | (define_insn "addsi3_internal_virt" |
227 | [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm") | |
228 | (plus:SI (match_operand:SI 1 "general_operand" "0, vim, vim") | |
229 | (match_operand 2 "general_operand" "vim,vim,vim"))) | |
230 | (clobber (reg:HI AX_REG)) | |
231 | (clobber (reg:HI BC_REG)) | |
78e515f7 | 232 | ] |
3f3556f1 | 233 | "rl78_virt_insns_ok ()" |
78e515f7 | 234 | "" |
3f3556f1 | 235 | [(set_attr "valloc" "macax")] |
236 | ) | |
237 | ||
238 | (define_insn "addsi3_internal_real" | |
239 | [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU") | |
240 | (plus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU") | |
241 | (match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1"))) | |
242 | (clobber (reg:HI AX_REG)) | |
243 | (clobber (reg:HI BC_REG)) | |
244 | ] | |
245 | "rl78_real_insns_ok ()" | |
95328f38 | 246 | { return rl78_addsi3_internal (operands, which_alternative); } |
3f3556f1 | 247 | [(set_attr "valloc" "macax")] |
248 | ) | |
249 | ||
250 | (define_expand "subsi3" | |
d1dc25ff | 251 | [(set (match_operand:SI 0 "nonimmediate_operand") |
252 | (minus:SI (match_operand:SI 1 "general_operand") | |
253 | (match_operand 2 "general_operand"))) | |
3f3556f1 | 254 | ] |
255 | "" | |
256 | "emit_insn (gen_subsi3_internal_virt (operands[0], operands[1], operands[2])); | |
257 | DONE;" | |
258 | ) | |
259 | ||
260 | (define_insn "subsi3_internal_virt" | |
261 | [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vm, vm") | |
262 | (minus:SI (match_operand:SI 1 "general_operand" "0, vim, vim") | |
263 | (match_operand 2 "general_operand" "vim,vim,vim"))) | |
264 | (clobber (reg:HI AX_REG)) | |
265 | (clobber (reg:HI BC_REG)) | |
266 | ] | |
267 | "rl78_virt_insns_ok ()" | |
268 | "" | |
269 | [(set_attr "valloc" "macax")] | |
270 | ) | |
271 | ||
272 | (define_insn "subsi3_internal_real" | |
273 | [(set (match_operand:SI 0 "nonimmediate_operand" "=v,&vU, vU") | |
274 | (minus:SI (match_operand:SI 1 "general_operand" "+0, viU, viU") | |
275 | (match_operand 2 "general_operand" "viWabWhlWh1,viWabWhlWh1,viWabWhlWh1"))) | |
276 | (clobber (reg:HI AX_REG)) | |
277 | (clobber (reg:HI BC_REG)) | |
278 | ] | |
279 | "rl78_real_insns_ok ()" | |
280 | "@ | |
281 | movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax | |
282 | movw ax,%h1 \;subw ax,%h2 \;movw %h0, ax \;movw ax,%H1 \;sknc \;decw ax \;subw ax,%H2 \;movw %H0,ax | |
283 | 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 | 284 | [(set_attr "valloc" "macax")] |
285 | ) | |
286 | ||
789a3e1c | 287 | (define_expand "mulqi3" |
e98e1692 | 288 | [(parallel |
289 | [(set (match_operand:QI 0 "register_operand") | |
290 | (mult:QI (match_operand:QI 1 "general_operand") | |
291 | (match_operand:QI 2 "nonmemory_operand"))) | |
292 | (clobber (reg:HI AX_REG)) | |
293 | ]) | |
294 | ] | |
789a3e1c | 295 | "" ; mulu supported by all targets |
296 | "" | |
297 | ) | |
298 | ||
299 | (define_expand "mulhi3" | |
d1dc25ff | 300 | [(set (match_operand:HI 0 "register_operand") |
301 | (mult:HI (match_operand:HI 1 "general_operand") | |
302 | (match_operand:HI 2 "nonmemory_operand"))) | |
789a3e1c | 303 | ] |
304 | "! RL78_MUL_NONE" | |
e98e1692 | 305 | { |
306 | if (RL78_MUL_G14) | |
307 | emit_insn (gen_mulhi3_g14 (operands[0], operands[1], operands[2])); | |
308 | else /* RL78_MUL_G13 */ | |
309 | emit_insn (gen_mulhi3_g13 (operands[0], operands[1], operands[2])); | |
310 | DONE; | |
311 | } | |
789a3e1c | 312 | ) |
313 | ||
78e515f7 | 314 | (define_expand "mulsi3" |
d1dc25ff | 315 | [(set (match_operand:SI 0 "register_operand") |
316 | (mult:SI (match_operand:SI 1 "general_operand") | |
317 | (match_operand:SI 2 "nonmemory_operand"))) | |
78e515f7 | 318 | ] |
319 | "! RL78_MUL_NONE" | |
e98e1692 | 320 | { |
321 | if (RL78_MUL_G14) | |
322 | emit_insn (gen_mulsi3_g14 (operands[0], operands[1], operands[2])); | |
323 | else /* RL78_MUL_G13 */ | |
324 | emit_insn (gen_mulsi3_g13 (operands[0], operands[1], operands[2])); | |
325 | DONE; | |
326 | } | |
78e515f7 | 327 | ) |
328 | ||
789a3e1c | 329 | (define_insn "*mulqi3_rl78" |
330 | [(set (match_operand:QI 0 "register_operand" "=&v") | |
d1dc25ff | 331 | (mult:QI (match_operand:QI 1 "general_operand" "viU") |
789a3e1c | 332 | (match_operand:QI 2 "general_operand" "vi"))) |
e98e1692 | 333 | (clobber (reg:HI AX_REG)) |
334 | ] | |
789a3e1c | 335 | "" ; mulu supported by all targets |
336 | "; mulqi macro %0 = %1 * %2 | |
337 | mov a, %h1 | |
338 | mov x, a | |
339 | mov a, %h2 | |
340 | mulu x ; ax = a * x | |
341 | mov a, x | |
342 | mov %h0, a | |
343 | ; end of mulqi macro" | |
e98e1692 | 344 | [(set_attr "valloc" "macax")] |
789a3e1c | 345 | ) |
346 | ||
e98e1692 | 347 | (define_insn "mulhi3_g14" |
789a3e1c | 348 | [(set (match_operand:HI 0 "register_operand" "=&v") |
d1dc25ff | 349 | (mult:HI (match_operand:HI 1 "general_operand" "viU") |
789a3e1c | 350 | (match_operand:HI 2 "general_operand" "vi"))) |
e98e1692 | 351 | (clobber (reg:HI AX_REG)) |
352 | (clobber (reg:HI BC_REG)) | |
353 | ] | |
354 | "RL78_MUL_G14" | |
355 | "; G14 mulhi macro %0 = %1 * %2 | |
789a3e1c | 356 | movw ax, %h1 |
357 | movw bc, %h2 | |
358 | mulhu ; bcax = bc * ax | |
359 | movw %h0, ax | |
360 | ; end of mulhi macro" | |
e98e1692 | 361 | [(set_attr "valloc" "macax")] |
789a3e1c | 362 | ) |
363 | ||
e98e1692 | 364 | (define_insn "mulhi3_g13" |
789a3e1c | 365 | [(set (match_operand:HI 0 "register_operand" "=&v") |
d1dc25ff | 366 | (mult:HI (match_operand:HI 1 "general_operand" "viU") |
789a3e1c | 367 | (match_operand:HI 2 "general_operand" "vi"))) |
e98e1692 | 368 | (clobber (reg:HI AX_REG)) |
369 | ] | |
789a3e1c | 370 | "RL78_MUL_G13" |
e98e1692 | 371 | "; G13 mulhi macro %0 = %1 * %2 |
789a3e1c | 372 | mov a, #0x00 |
373 | mov !0xf00e8, a ; MDUC | |
374 | movw ax, %h1 | |
375 | movw 0xffff0, ax ; MDAL | |
376 | movw ax, %h2 | |
377 | movw 0xffff2, ax ; MDAH | |
378 | nop ; mdb = mdal * mdah | |
379 | movw ax, 0xffff6 ; MDBL | |
380 | movw %h0, ax | |
381 | ; end of mulhi macro" | |
e98e1692 | 382 | [(set_attr "valloc" "macax")] |
789a3e1c | 383 | ) |
384 | ||
78e515f7 | 385 | ;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it |
386 | ;; because we're only using the lower 16 bits (which is the upper 16 | |
387 | ;; bits of the result). | |
e98e1692 | 388 | (define_insn "mulsi3_g14" |
78e515f7 | 389 | [(set (match_operand:SI 0 "register_operand" "=&v") |
d1dc25ff | 390 | (mult:SI (match_operand:SI 1 "general_operand" "viU") |
3f3556f1 | 391 | (match_operand:SI 2 "general_operand" "vi"))) |
e98e1692 | 392 | (clobber (reg:HI AX_REG)) |
393 | (clobber (reg:HI BC_REG)) | |
394 | ] | |
395 | "RL78_MUL_G14" | |
396 | "; G14 mulsi macro %0 = %1 * %2 | |
78e515f7 | 397 | movw ax, %h1 |
398 | movw bc, %h2 | |
399 | MULHU ; bcax = bc * ax | |
400 | movw %h0, ax | |
401 | movw ax, bc | |
402 | movw 0xffff0, ax | |
403 | movw ax, %H1 | |
404 | movw bc, %h2 | |
405 | MACHU ; MACR += bc * ax | |
406 | movw ax, %h1 | |
407 | movw bc, %H2 | |
408 | MACHU ; MACR += bc * ax | |
409 | movw ax, 0xffff0 | |
410 | movw %H0, ax | |
411 | ; end of mulsi macro" | |
412 | [(set_attr "valloc" "macax")] | |
413 | ) | |
414 | ||
415 | ;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH. | |
50008a8e | 416 | ;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH. |
78e515f7 | 417 | ;; 0xF00E0 is MDCL. 0xF00E2 is MDCH. |
418 | ;; 0xF00E8 is MDUC. | |
50008a8e | 419 | ;; Warning: this matches the silicon not the documentation. |
78e515f7 | 420 | (define_insn "mulsi3_g13" |
421 | [(set (match_operand:SI 0 "register_operand" "=&v") | |
3f3556f1 | 422 | (mult:SI (match_operand:SI 1 "general_operand" "viU") |
423 | (match_operand:SI 2 "general_operand" "viU"))) | |
e98e1692 | 424 | (clobber (reg:HI AX_REG)) |
425 | (clobber (reg:HI BC_REG)) | |
426 | ] | |
78e515f7 | 427 | "RL78_MUL_G13" |
e98e1692 | 428 | "; G13 mulsi macro %0 = %1 * %2 |
78e515f7 | 429 | mov a, #0x00 |
430 | mov !0xf00e8, a ; MDUC | |
431 | movw ax, %h1 | |
432 | movw 0xffff0, ax ; MDAL | |
433 | movw ax, %h2 | |
434 | movw 0xffff2, ax ; MDAH | |
435 | nop ; mdb = mdal * mdah | |
50008a8e | 436 | movw ax, 0xffff6 ; MDBL |
78e515f7 | 437 | movw %h0, ax |
438 | ||
439 | mov a, #0x40 | |
440 | mov !0xf00e8, a ; MDUC | |
50008a8e | 441 | movw ax, 0xffff4 ; MDBH |
78e515f7 | 442 | movw !0xf00e0, ax ; MDCL |
443 | movw ax, #0 | |
444 | movw !0xf00e2, ax ; MDCL | |
445 | movw ax, %H1 | |
446 | movw 0xffff0, ax ; MDAL | |
447 | movw ax, %h2 | |
448 | movw 0xffff2, ax ; MDAH | |
449 | nop ; mdc += mdal * mdah | |
450 | ||
451 | mov a, #0x40 | |
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 ; mdc += mdal * mdah | |
57518f85 | 458 | nop ; Additional nop for MAC |
78e515f7 | 459 | movw ax, !0xf00e0 ; MDCL |
460 | movw %H0, ax | |
461 | ; end of mulsi macro" | |
462 | [(set_attr "valloc" "macax")] | |
563dc27b | 463 | ) |
e98e1692 | 464 | |
465 | (define_expand "udivmodhi4" | |
466 | [(parallel | |
467 | [(set (match_operand:HI 0 "register_operand") | |
468 | (udiv:HI (match_operand:HI 1 "register_operand") | |
469 | (match_operand:HI 2 "register_operand"))) | |
470 | (set (match_operand:HI 3 "register_operand") | |
471 | (umod:HI (match_dup 1) (match_dup 2))) | |
472 | (clobber (reg:HI AX_REG)) | |
473 | (clobber (reg:HI DE_REG)) | |
474 | ]) | |
475 | ] | |
476 | "RL78_MUL_G14" | |
477 | "" | |
478 | ) | |
479 | ||
480 | (define_insn "*udivmodhi4_g14" | |
481 | [(set (match_operand:HI 0 "register_operand" "=v") | |
482 | (udiv:HI (match_operand:HI 1 "register_operand" "v") | |
483 | (match_operand:HI 2 "register_operand" "v"))) | |
484 | (set (match_operand:HI 3 "register_operand" "=v") | |
485 | (umod:HI (match_dup 1) (match_dup 2))) | |
486 | (clobber (reg:HI AX_REG)) | |
487 | (clobber (reg:HI DE_REG)) | |
488 | ] | |
489 | "RL78_MUL_G14" | |
490 | { | |
491 | if (find_reg_note (insn, REG_UNUSED, operands[3])) | |
492 | return "; G14 udivhi macro %0 = %1 / %2 \n\ | |
493 | movw ax, %h1 \n\ | |
494 | movw de, %h2 \n\ | |
495 | push psw ; Save the current interrupt status \n\ | |
496 | di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ | |
497 | divhu ; ax = ax / de \n\ | |
498 | pop psw ; Restore saved interrupt status \n\ | |
499 | movw %h0, ax \n\ | |
500 | ; end of udivhi macro"; | |
501 | else if (find_reg_note (insn, REG_UNUSED, operands[0])) | |
502 | return "; G14 umodhi macro %3 = %1 %% %2 \n\ | |
503 | movw ax, %h1 \n\ | |
504 | movw de, %h2 \n\ | |
505 | push psw ; Save the current interrupt status \n\ | |
506 | di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ | |
507 | divhu ; de = ax %% de \n\ | |
508 | pop psw ; Restore saved interrupt status \n\ | |
509 | movw ax, de \n\ | |
510 | movw %h3, ax \n\ | |
511 | ; end of umodhi macro"; | |
512 | else | |
513 | return "; G14 udivmodhi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\ | |
514 | movw ax, %h1 \n\ | |
515 | movw de, %h2 \n\ | |
516 | push psw ; Save the current interrupt status \n\ | |
517 | di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ | |
518 | divhu ; ax = ax / de, de = ax %% de \n\ | |
519 | pop psw ; Restore saved interrupt status \n\ | |
520 | movw %h0, ax \n\ | |
521 | movw ax, de \n\ | |
522 | movw %h3, ax \n\ | |
523 | ; end of udivmodhi macro"; | |
524 | } | |
525 | [(set_attr "valloc" "divhi")] | |
526 | ) | |
527 | ||
528 | (define_expand "udivmodsi4" | |
529 | [(parallel | |
530 | [(set (match_operand:SI 0 "register_operand") | |
531 | (udiv:SI (match_operand:SI 1 "register_operand") | |
532 | (match_operand:SI 2 "register_operand"))) | |
533 | (set (match_operand:SI 3 "register_operand") | |
534 | (umod:SI (match_dup 1) (match_dup 2))) | |
535 | ]) | |
536 | ] | |
537 | "! RL78_MUL_NONE && ! optimize_size" | |
538 | { | |
539 | if (RL78_MUL_G14) | |
540 | emit_insn (gen_udivmodsi4_g14 (operands[0], operands[1], operands[2], operands[3])); | |
541 | else /* RL78_MUL_G13 */ | |
542 | emit_insn (gen_udivmodsi4_g13 (operands[0], operands[1], operands[2], operands[3])); | |
543 | DONE; | |
544 | } | |
545 | ) | |
546 | ||
547 | (define_insn "udivmodsi4_g14" | |
548 | [(set (match_operand:SI 0 "register_operand" "=v") | |
549 | (udiv:SI (match_operand:SI 1 "register_operand" "v") | |
550 | (match_operand:SI 2 "register_operand" "v"))) | |
551 | (set (match_operand:SI 3 "register_operand" "=v") | |
552 | (umod:SI (match_dup 1) (match_dup 2))) | |
553 | (clobber (reg:HI AX_REG)) | |
554 | (clobber (reg:HI BC_REG)) | |
555 | (clobber (reg:HI DE_REG)) | |
556 | (clobber (reg:HI HL_REG)) | |
557 | ] | |
558 | "RL78_MUL_G14" | |
559 | { | |
560 | if (find_reg_note (insn, REG_UNUSED, operands[3])) | |
561 | return "; G14 udivsi macro %0 = %1 / %2 \n\ | |
562 | movw ax, %h1 \n\ | |
563 | movw bc, %H1 \n\ | |
564 | movw de, %h2 \n\ | |
565 | movw hl, %H2 \n\ | |
566 | push psw ; Save the current interrupt status \n\ | |
567 | di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ | |
568 | divwu ; bcax = bcax / hlde \n\ | |
569 | pop psw ; Restore saved interrupt status \n\ | |
570 | movw %h0, ax \n\ | |
571 | movw ax, bc \n\ | |
572 | movw %H0, ax \n\ | |
573 | ; end of udivsi macro"; | |
574 | else if (find_reg_note (insn, REG_UNUSED, operands[0])) | |
575 | return "; G14 umodsi macro %3 = %1 %% %2 \n\ | |
576 | movw ax, %h1 \n\ | |
577 | movw bc, %H1 \n\ | |
578 | movw de, %h2 \n\ | |
579 | movw hl, %H2 \n\ | |
580 | push psw ; Save the current interrupt status \n\ | |
581 | di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ | |
582 | divwu ; hlde = bcax %% hlde \n\ | |
583 | pop psw ; Restore saved interrupt status \n\ | |
584 | movw ax, de \n\ | |
585 | movw %h3, ax \n\ | |
586 | movw ax, hl \n\ | |
587 | movw %H3, ax \n\ | |
588 | ; end of umodsi macro"; | |
589 | else | |
590 | return "; G14 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\ | |
591 | movw ax, %h1 \n\ | |
592 | movw bc, %H1 \n\ | |
593 | movw de, %h2 \n\ | |
594 | movw hl, %H2 \n\ | |
595 | push psw ; Save the current interrupt status \n\ | |
596 | di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\ | |
597 | divwu ; bcax = bcax / hlde, hlde = bcax %% hlde \n\ | |
598 | pop psw ; Restore saved interrupt status \n\ | |
599 | movw %h0, ax \n\ | |
600 | movw ax, bc \n\ | |
601 | movw %H0, ax \n\ | |
602 | movw ax, de \n\ | |
603 | movw %h3, ax \n\ | |
604 | movw ax, hl \n\ | |
605 | movw %H3, ax \n\ | |
606 | ; end of udivmodsi macro"; | |
607 | } | |
608 | [(set_attr "valloc" "divsi")] | |
609 | ) | |
610 | ||
611 | ;; Warning: these values match the silicon not the documentation. | |
612 | ;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH. | |
613 | ;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH. | |
614 | ;; 0xF00E0 is MDCL. 0xF00E2 is MDCH. | |
615 | ;; 0xF00E8 is MDUC. | |
616 | ||
617 | (define_insn "udivmodsi4_g13" | |
618 | [(set (match_operand:SI 0 "register_operand" "=v") | |
619 | (udiv:SI (match_operand:SI 1 "register_operand" "v") | |
620 | (match_operand:SI 2 "register_operand" "v"))) | |
621 | (set (match_operand:SI 3 "register_operand" "=v") | |
622 | (umod:SI (match_dup 1) (match_dup 2))) | |
623 | (clobber (reg:HI AX_REG)) | |
624 | ] | |
625 | "RL78_MUL_G13" | |
626 | { | |
627 | if (find_reg_note (insn, REG_UNUSED, operands[3])) | |
628 | return "; G13 udivsi macro %0 = %1 / %2 \n\ | |
629 | mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\ | |
630 | mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\ | |
631 | movw ax, %H1 \n\ | |
632 | movw 0xffff2, ax ; MDAH \n\ | |
633 | movw ax, %h1 \n\ | |
634 | movw 0xffff0, ax ; MDAL \n\ | |
635 | movw ax, %H2 \n\ | |
636 | movw 0xffff4, ax ; MDBH \n\ | |
637 | movw ax, %h2 \n\ | |
638 | movw 0xffff6, ax ; MDBL \n\ | |
639 | mov a, #0xC1 ; Set the DIVST bit in MDUC \n\ | |
640 | mov !0xf00e8, a ; This starts the division op \n\ | |
641 | 1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\ | |
642 | bt a.0, $1b \n\ | |
643 | movw ax, 0xffff0 ; Read the quotient \n\ | |
644 | movw %h0, ax \n\ | |
645 | movw ax, 0xffff2 \n\ | |
646 | movw %H0, ax \n\ | |
647 | ; end of udivsi macro"; | |
648 | else if (find_reg_note (insn, REG_UNUSED, operands[0])) | |
649 | return "; G13 umodsi macro %3 = %1 %% %2 \n\ | |
650 | mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\ | |
651 | mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\ | |
652 | movw ax, %H1 \n\ | |
653 | movw 0xffff2, ax ; MDAH \n\ | |
654 | movw ax, %h1 \n\ | |
655 | movw 0xffff0, ax ; MDAL \n\ | |
656 | movw ax, %H2 \n\ | |
657 | movw 0xffff4, ax ; MDBH \n\ | |
658 | movw ax, %h2 \n\ | |
659 | movw 0xffff6, ax ; MDBL \n\ | |
660 | mov a, #0xC1 ; Set the DIVST bit in MDUC \n\ | |
661 | mov !0xf00e8, a ; This starts the division op \n\ | |
662 | 1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\ | |
663 | bt a.0, $1b \n\ | |
664 | movw ax, !0xf00e0 ; Read the remainder \n\ | |
665 | movw %h3, ax \n\ | |
666 | movw ax, !0xf00e2 \n\ | |
667 | movw %H3, ax \n\ | |
668 | ; end of umodsi macro"; | |
669 | else | |
670 | return "; G13 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\ | |
671 | mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\ | |
672 | mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\ | |
673 | movw ax, %H1 \n\ | |
674 | movw 0xffff2, ax ; MDAH \n\ | |
675 | movw ax, %h1 \n\ | |
676 | movw 0xffff0, ax ; MDAL \n\ | |
677 | movw ax, %H2 \n\ | |
678 | movw 0xffff4, ax ; MDBH \n\ | |
679 | movw ax, %h2 \n\ | |
680 | movw 0xffff6, ax ; MDBL \n\ | |
681 | mov a, #0xC1 ; Set the DIVST bit in MDUC \n\ | |
682 | mov !0xf00e8, a ; This starts the division op \n\ | |
683 | 1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\ | |
684 | bt a.0, $1b \n\ | |
685 | movw ax, 0xffff0 ; Read the quotient \n\ | |
686 | movw %h0, ax \n\ | |
687 | movw ax, 0xffff2 \n\ | |
688 | movw %H0, ax \n\ | |
689 | movw ax, !0xf00e0 ; Read the remainder \n\ | |
690 | movw %h3, ax \n\ | |
691 | movw ax, !0xf00e2 \n\ | |
692 | movw %H3, ax \n\ | |
693 | ; end of udivmodsi macro"; | |
694 | } | |
695 | [(set_attr "valloc" "macax")] | |
696 | ) |