]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/rl78/rl78.md
.
[thirdparty/gcc.git] / gcc / config / rl78 / rl78.md
1 ;; Machine Description for Renesas RL78 processors
2 ;; Copyright (C) 2011 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 \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)
38 (CC_REG 33)
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
49 (UNS_TRAMPOLINE_INIT 20)
50 (UNS_TRAMPOLINE_UNINIT 21)
51 (UNS_NONLOCAL_GOTO 22)
52
53 ])
54
55 (define_insn "nop"
56 [(const_int 0)]
57 ""
58 "nop"
59 )
60
61 (define_mode_iterator QHI [QI HI])
62
63 (include "predicates.md")
64 (include "constraints.md")
65 (include "rl78-expand.md")
66 (include "rl78-virt.md")
67 (include "rl78-real.md")
68
69
70 ;; Function Prologue/Epilogue Instructions
71
72 (define_expand "prologue"
73 [(const_int 0)]
74 ""
75 "rl78_expand_prologue (); DONE;"
76 )
77
78 (define_expand "epilogue"
79 [(const_int 0)]
80 ""
81 "rl78_expand_epilogue (); DONE;"
82 )
83
84 (define_expand "sibcall_epilogue"
85 [(return)]
86 ""
87 "FAIL;"
88 )
89
90 (define_insn "return"
91 [(return)]
92 ""
93 "ret"
94 )
95
96 (define_insn "interrupt_return"
97 [(unspec_volatile [(return)] UNS_RETI) ]
98 ""
99 "reti"
100 )
101
102 (define_insn "brk_interrupt_return"
103 [(unspec_volatile [(return)] UNS_RETB) ]
104 ""
105 "retb"
106 )
107
108 (define_expand "eh_return"
109 [(match_operand:HI 0 "" "")]
110 ""
111 "rl78_expand_eh_epilogue (operands[0]);
112 emit_barrier ();
113 DONE;"
114 )
115
116 ;; These are used only by prologue/epilogue so it's "safe" to pass
117 ;; virtual registers.
118 (define_insn "push"
119 [(set (reg:HI SP_REG)
120 (plus:HI (reg:HI SP_REG)
121 (const_int -2)))
122 (set (mem:HI (reg:HI SP_REG))
123 (match_operand:HI 0 "register_operand" "ABDT,vZint"))]
124 ""
125 "@
126 push\t%v0
127 push\t%v0 ; %0"
128 )
129
130 (define_insn "pop"
131 [(set (match_operand:HI 0 "register_operand" "=ABDT,vZint")
132 (mem:HI (reg:HI SP_REG)))
133 (set (reg:HI SP_REG)
134 (plus:HI (reg:HI SP_REG)
135 (const_int 2)))]
136 ""
137 "@
138 pop\t%v0
139 pop\t%v0 ; %0"
140 )
141
142 (define_insn "sel_rb"
143 [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)]
144 ""
145 "sel\trb%u0"
146 )
147
148 (define_insn "trampoline_init"
149 [(set (match_operand 0 "register_operand" "=Z08W")
150 (unspec_volatile [(match_operand 1 "register_operand" "Z08W")
151 (match_operand 2 "register_operand" "Z10W")
152 ] UNS_TRAMPOLINE_INIT))
153 ]
154 ""
155 "call !!___trampoline_init ; %0 <= %1 %2"
156 )
157
158 (define_insn "trampoline_uninit"
159 [(unspec_volatile [(const_int 0)] UNS_TRAMPOLINE_UNINIT)
160 ]
161 ""
162 "call !!___trampoline_uninit"
163 )
164
165 ;; GCC restores $fp *before* using it to access values on the *old*
166 ;; frame. So, we do it ourselves, to ensure this is not the case.
167 ;; Note that while %1 is usually a label_ref, we allow for a
168 ;; non-immediate as well.
169 (define_expand "nonlocal_goto"
170 [(set (pc)
171 (unspec_volatile [(match_operand 0 "" "") ;; fp (ignore)
172 (match_operand 1 "" "vi") ;; target
173 (match_operand 2 "" "vi") ;; sp
174 (match_operand 3 "" "vi") ;; ?
175 ] UNS_NONLOCAL_GOTO))
176 ]
177 ""
178 "emit_jump_insn (gen_nonlocal_goto_insn (operands[0], operands[1], operands[2], operands[3]));
179 emit_barrier ();
180 DONE;"
181 )
182
183 (define_insn "nonlocal_goto_insn"
184 [(set (pc)
185 (unspec_volatile [(match_operand 0 "" "") ;; fp (ignore)
186 (match_operand 1 "" "vi") ;; target
187 (match_operand 2 "" "vi") ;; sp
188 (match_operand 3 "" "vi") ;; ?
189 ] UNS_NONLOCAL_GOTO))
190 ]
191 ""
192 "; nonlocal goto
193 movw ax, %3
194 movw r22, ax
195 movw ax, %2
196 movw sp, ax
197 movw ax, %1
198 br ax
199 "
200 )
201
202 ;;======================================================================
203 ;;
204 ;; "macro" insns - cases where inline chunks of code are more
205 ;; efficient than anything else.
206
207 (define_expand "addsi3"
208 [(set (match_operand:SI 0 "register_operand" "=&v")
209 (plus:SI (match_operand:SI 1 "nonmemory_operand" "vi")
210 (match_operand 2 "nonmemory_operand" "vi")))
211 ]
212 ""
213 "if (!nonmemory_operand (operands[1], SImode))
214 operands[1] = force_reg (SImode, operands[1]);
215 if (!nonmemory_operand (operands[1], SImode))
216 operands[2] = force_reg (SImode, operands[2]);"
217 )
218
219 (define_insn "addsi3_internal"
220 [(set (match_operand:SI 0 "register_operand" "=&v")
221 (plus:SI (match_operand:SI 1 "nonmemory_operand" "vi")
222 (match_operand:SI 2 "nonmemory_operand" "vi")))
223 ]
224 ""
225 "; addSI macro %0 = %1 + %2
226 movw ax, %h1
227 addw ax, %h2
228 movw %h0, ax
229 movw ax,%H1
230 sknc
231 incw ax
232 addw ax,%H2
233 movw %H0,ax
234 ; end of addSI macro"
235 [(set_attr "valloc" "macax")]
236 )
237
238 (define_expand "mulsi3"
239 [(set (match_operand:SI 0 "register_operand" "=&v")
240 (mult:SI (match_operand:SI 1 "nonmemory_operand" "vi")
241 (match_operand:SI 2 "nonmemory_operand" "vi")))
242 ]
243 "! RL78_MUL_NONE"
244 ""
245 )
246
247 ;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it
248 ;; because we're only using the lower 16 bits (which is the upper 16
249 ;; bits of the result).
250 (define_insn "mulsi3_rl78"
251 [(set (match_operand:SI 0 "register_operand" "=&v")
252 (mult:SI (match_operand:SI 1 "nonmemory_operand" "vi")
253 (match_operand:SI 2 "nonmemory_operand" "vi")))
254 ]
255 "RL78_MUL_RL78"
256 "; mulsi macro %0 = %1 * %2
257 movw ax, %h1
258 movw bc, %h2
259 MULHU ; bcax = bc * ax
260 movw %h0, ax
261 movw ax, bc
262 movw 0xffff0, ax
263 movw ax, %H1
264 movw bc, %h2
265 MACHU ; MACR += bc * ax
266 movw ax, %h1
267 movw bc, %H2
268 MACHU ; MACR += bc * ax
269 movw ax, 0xffff0
270 movw %H0, ax
271 ; end of mulsi macro"
272 [(set_attr "valloc" "macax")]
273 )
274
275 ;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH.
276 ;; 0xFFFF4 is MDBL. 0xFFFF6 is MDBH.
277 ;; 0xF00E0 is MDCL. 0xF00E2 is MDCH.
278 ;; 0xF00E8 is MDUC.
279 ;; Warning: this matches the documentation, not the silicon.
280 (define_insn "mulsi3_g13"
281 [(set (match_operand:SI 0 "register_operand" "=&v")
282 (mult:SI (match_operand:SI 1 "nonmemory_operand" "vi")
283 (match_operand:SI 2 "nonmemory_operand" "vi")))
284 ]
285 "RL78_MUL_G13"
286 "; mulsi macro %0 = %1 * %2
287 mov a, #0x00
288 mov !0xf00e8, a ; MDUC
289 movw ax, %h1
290 movw 0xffff0, ax ; MDAL
291 movw ax, %h2
292 movw 0xffff2, ax ; MDAH
293 nop ; mdb = mdal * mdah
294 movw ax, 0xffff4 ; MDBL
295 movw %h0, ax
296
297 mov a, #0x40
298 mov !0xf00e8, a ; MDUC
299 movw ax, 0xffff6 ; MDBH
300 movw !0xf00e0, ax ; MDCL
301 movw ax, #0
302 movw !0xf00e2, ax ; MDCL
303 movw ax, %H1
304 movw 0xffff0, ax ; MDAL
305 movw ax, %h2
306 movw 0xffff2, ax ; MDAH
307 nop ; mdc += mdal * mdah
308
309 mov a, #0x40
310 mov !0xf00e8, a ; MDUC
311 movw ax, %h1
312 movw 0xffff0, ax ; MDAL
313 movw ax, %H2
314 movw 0xffff2, ax ; MDAH
315 nop ; mdc += mdal * mdah
316 movw ax, !0xf00e0 ; MDCL
317 movw %H0, ax
318 ; end of mulsi macro"
319 [(set_attr "valloc" "macax")]
320 )