xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/rl78/rl78.md (revision 04028aa9310ca9c619eca5cf58ddf1e58624d1d7)
1;;  Machine Description for Renesas RL78 processors
2;;  Copyright (C) 2011-2013 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 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 "rl78_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;; 0xFFFF6 is MDBL.  0xFFFF4 is MDBH.
277;; 0xF00E0 is MDCL.  0xF00E2 is MDCH.
278;; 0xF00E8 is MDUC.
279;; Warning: this matches the silicon not the documentation.
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, 0xffff6	; MDBL
295	movw	%h0, ax
296
297	mov	a, #0x40
298	mov	!0xf00e8, a	; MDUC
299	movw	ax, 0xffff4	; 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  )
321