xref: /openbsd/gnu/usr.bin/gcc/gcc/config/h8300/h8300.c (revision 4e43c760)
1c87b03e5Sespie /* Subroutines for insn-output.c for Hitachi H8/300.
2c87b03e5Sespie    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3c87b03e5Sespie    2001, 2002, 2003 Free Software Foundation, Inc.
4c87b03e5Sespie    Contributed by Steve Chamberlain (sac@cygnus.com),
5c87b03e5Sespie    Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
6c87b03e5Sespie 
7c87b03e5Sespie This file is part of GNU CC.
8c87b03e5Sespie 
9c87b03e5Sespie GNU CC is free software; you can redistribute it and/or modify
10c87b03e5Sespie it under the terms of the GNU General Public License as published by
11c87b03e5Sespie the Free Software Foundation; either version 2, or (at your option)
12c87b03e5Sespie any later version.
13c87b03e5Sespie 
14c87b03e5Sespie GNU CC is distributed in the hope that it will be useful,
15c87b03e5Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
16c87b03e5Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17c87b03e5Sespie GNU General Public License for more details.
18c87b03e5Sespie 
19c87b03e5Sespie You should have received a copy of the GNU General Public License
20c87b03e5Sespie along with GNU CC; see the file COPYING.  If not, write to
21c87b03e5Sespie the Free Software Foundation, 59 Temple Place - Suite 330,
22c87b03e5Sespie Boston, MA 02111-1307, USA.  */
23c87b03e5Sespie 
24c87b03e5Sespie #include "config.h"
25c87b03e5Sespie #include "system.h"
26c87b03e5Sespie #include "rtl.h"
27c87b03e5Sespie #include "tree.h"
28c87b03e5Sespie #include "regs.h"
29c87b03e5Sespie #include "hard-reg-set.h"
30c87b03e5Sespie #include "real.h"
31c87b03e5Sespie #include "insn-config.h"
32c87b03e5Sespie #include "conditions.h"
33c87b03e5Sespie #include "output.h"
34c87b03e5Sespie #include "insn-attr.h"
35c87b03e5Sespie #include "flags.h"
36c87b03e5Sespie #include "recog.h"
37c87b03e5Sespie #include "expr.h"
38c87b03e5Sespie #include "function.h"
39c87b03e5Sespie #include "toplev.h"
40c87b03e5Sespie #include "c-pragma.h"
41c87b03e5Sespie #include "tm_p.h"
42c87b03e5Sespie #include "ggc.h"
43c87b03e5Sespie #include "target.h"
44c87b03e5Sespie #include "target-def.h"
45c87b03e5Sespie 
46c87b03e5Sespie /* Forward declarations.  */
47c87b03e5Sespie static const char *byte_reg PARAMS ((rtx, int));
48c87b03e5Sespie static int h8300_interrupt_function_p PARAMS ((tree));
49c87b03e5Sespie static int h8300_monitor_function_p PARAMS ((tree));
50c87b03e5Sespie static int h8300_os_task_function_p PARAMS ((tree));
51c87b03e5Sespie static void dosize PARAMS ((FILE *, int, unsigned int));
52c87b03e5Sespie static int round_frame_size PARAMS ((int));
53c87b03e5Sespie static unsigned int compute_saved_regs PARAMS ((void));
54c87b03e5Sespie static void push PARAMS ((FILE *, int));
55c87b03e5Sespie static void pop PARAMS ((FILE *, int));
56c87b03e5Sespie static const char *cond_string PARAMS ((enum rtx_code));
57c87b03e5Sespie static unsigned int h8300_asm_insn_count PARAMS ((const char *));
58c87b03e5Sespie const struct attribute_spec h8300_attribute_table[];
59c87b03e5Sespie static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
60c87b03e5Sespie static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
61c87b03e5Sespie static tree h8300_handle_tiny_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
62c87b03e5Sespie static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
63c87b03e5Sespie static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
64c87b03e5Sespie static void h8300_insert_attributes PARAMS ((tree, tree *));
65c87b03e5Sespie #ifndef OBJECT_FORMAT_ELF
66c87b03e5Sespie static void h8300_asm_named_section PARAMS ((const char *, unsigned int));
67c87b03e5Sespie #endif
68c87b03e5Sespie static void h8300_encode_label PARAMS ((tree));
69c87b03e5Sespie static void h8300_encode_section_info PARAMS ((tree, int));
70c87b03e5Sespie static const char *h8300_strip_name_encoding PARAMS ((const char *));
71c87b03e5Sespie 
72c87b03e5Sespie /* CPU_TYPE, says what cpu we're compiling for.  */
73c87b03e5Sespie int cpu_type;
74c87b03e5Sespie 
75c87b03e5Sespie /* True if the current function is an interrupt handler
76c87b03e5Sespie    (either via #pragma or an attribute specification).  */
77c87b03e5Sespie static int interrupt_handler;
78c87b03e5Sespie 
79c87b03e5Sespie /* True if the current function is an OS Task
80c87b03e5Sespie    (via an attribute specification).  */
81c87b03e5Sespie static int os_task;
82c87b03e5Sespie 
83c87b03e5Sespie /* True if the current function is a monitor
84c87b03e5Sespie    (via an attribute specification).  */
85c87b03e5Sespie static int monitor;
86c87b03e5Sespie 
87c87b03e5Sespie /* True if a #pragma saveall has been seen for the current function.  */
88c87b03e5Sespie static int pragma_saveall;
89c87b03e5Sespie 
90c87b03e5Sespie static const char *const names_big[] =
91c87b03e5Sespie { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
92c87b03e5Sespie 
93c87b03e5Sespie static const char *const names_extended[] =
94c87b03e5Sespie { "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7" };
95c87b03e5Sespie 
96c87b03e5Sespie static const char *const names_upper_extended[] =
97c87b03e5Sespie { "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7" };
98c87b03e5Sespie 
99c87b03e5Sespie /* Points to one of the above.  */
100c87b03e5Sespie /* ??? The above could be put in an array indexed by CPU_TYPE.  */
101c87b03e5Sespie const char * const *h8_reg_names;
102c87b03e5Sespie 
103c87b03e5Sespie /* Various operations needed by the following, indexed by CPU_TYPE.  */
104c87b03e5Sespie 
105c87b03e5Sespie const char *h8_push_op, *h8_pop_op, *h8_mov_op;
106c87b03e5Sespie 
107c87b03e5Sespie /* Initialize the GCC target structure.  */
108c87b03e5Sespie #undef TARGET_ATTRIBUTE_TABLE
109c87b03e5Sespie #define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
110c87b03e5Sespie 
111c87b03e5Sespie #undef TARGET_ASM_ALIGNED_HI_OP
112c87b03e5Sespie #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
113c87b03e5Sespie 
114c87b03e5Sespie #undef TARGET_ASM_FUNCTION_PROLOGUE
115c87b03e5Sespie #define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
116c87b03e5Sespie #undef TARGET_ASM_FUNCTION_EPILOGUE
117c87b03e5Sespie #define TARGET_ASM_FUNCTION_EPILOGUE h8300_output_function_epilogue
118c87b03e5Sespie #undef TARGET_ENCODE_SECTION_INFO
119c87b03e5Sespie #define TARGET_ENCODE_SECTION_INFO h8300_encode_section_info
120c87b03e5Sespie #undef TARGET_STRIP_NAME_ENCODING
121c87b03e5Sespie #define TARGET_STRIP_NAME_ENCODING h8300_strip_name_encoding
122c87b03e5Sespie 
123c87b03e5Sespie #undef TARGET_INSERT_ATTRIBUTES
124c87b03e5Sespie #define TARGET_INSERT_ATTRIBUTES h8300_insert_attributes
125c87b03e5Sespie 
126c87b03e5Sespie struct gcc_target targetm = TARGET_INITIALIZER;
127c87b03e5Sespie 
128c87b03e5Sespie /* See below where shifts are handled for explanation of this enum.  */
129c87b03e5Sespie 
130c87b03e5Sespie enum shift_alg
131c87b03e5Sespie {
132c87b03e5Sespie   SHIFT_INLINE,
133c87b03e5Sespie   SHIFT_ROT_AND,
134c87b03e5Sespie   SHIFT_SPECIAL,
135c87b03e5Sespie   SHIFT_LOOP
136c87b03e5Sespie };
137c87b03e5Sespie 
138c87b03e5Sespie /* Symbols of the various shifts which can be used as indices.  */
139c87b03e5Sespie 
140c87b03e5Sespie enum shift_type
141c87b03e5Sespie {
142c87b03e5Sespie   SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT
143c87b03e5Sespie };
144c87b03e5Sespie 
145c87b03e5Sespie /* Macros to keep the shift algorithm tables small.  */
146c87b03e5Sespie #define INL SHIFT_INLINE
147c87b03e5Sespie #define ROT SHIFT_ROT_AND
148c87b03e5Sespie #define LOP SHIFT_LOOP
149c87b03e5Sespie #define SPC SHIFT_SPECIAL
150c87b03e5Sespie 
151c87b03e5Sespie /* The shift algorithms for each machine, mode, shift type, and shift
152c87b03e5Sespie    count are defined below.  The three tables below correspond to
153c87b03e5Sespie    QImode, HImode, and SImode, respectively.  Each table is organized
154c87b03e5Sespie    by, in the order of indecies, machine, shift type, and shift count.  */
155c87b03e5Sespie 
156c87b03e5Sespie static enum shift_alg shift_alg_qi[3][3][8] = {
157c87b03e5Sespie   {
158c87b03e5Sespie     /* TARGET_H8300  */
159c87b03e5Sespie     /* 0    1    2    3    4    5    6    7  */
160c87b03e5Sespie     { INL, INL, INL, INL, INL, ROT, ROT, ROT }, /* SHIFT_ASHIFT   */
161c87b03e5Sespie     { INL, INL, INL, INL, INL, ROT, ROT, ROT }, /* SHIFT_LSHIFTRT */
162c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, SPC }  /* SHIFT_ASHIFTRT */
163c87b03e5Sespie   },
164c87b03e5Sespie   {
165c87b03e5Sespie     /* TARGET_H8300H  */
166c87b03e5Sespie     /* 0    1    2    3    4    5    6    7  */
167c87b03e5Sespie     { INL, INL, INL, INL, INL, ROT, ROT, ROT }, /* SHIFT_ASHIFT   */
168c87b03e5Sespie     { INL, INL, INL, INL, INL, ROT, ROT, ROT }, /* SHIFT_LSHIFTRT */
169c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, SPC }  /* SHIFT_ASHIFTRT */
170c87b03e5Sespie   },
171c87b03e5Sespie   {
172c87b03e5Sespie     /* TARGET_H8300S  */
173c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
174c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, ROT, ROT }, /* SHIFT_ASHIFT   */
175c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, ROT, ROT }, /* SHIFT_LSHIFTRT */
176c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, SPC }  /* SHIFT_ASHIFTRT */
177c87b03e5Sespie   }
178c87b03e5Sespie };
179c87b03e5Sespie 
180c87b03e5Sespie static enum shift_alg shift_alg_hi[3][3][16] = {
181c87b03e5Sespie   {
182c87b03e5Sespie     /* TARGET_H8300  */
183c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
184c87b03e5Sespie     /*  8    9   10   11   12   13   14   15  */
185c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, SPC,
186c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC }, /* SHIFT_ASHIFT   */
187c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, SPC,
188c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC }, /* SHIFT_LSHIFTRT */
189c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, SPC,
190c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC }, /* SHIFT_ASHIFTRT */
191c87b03e5Sespie   },
192c87b03e5Sespie   {
193c87b03e5Sespie     /* TARGET_H8300H  */
194c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
195c87b03e5Sespie     /*  8    9   10   11   12   13   14   15  */
196c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, SPC,
197c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT }, /* SHIFT_ASHIFT   */
198c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, SPC,
199c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT }, /* SHIFT_LSHIFTRT */
200c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, SPC,
201c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC }, /* SHIFT_ASHIFTRT */
202c87b03e5Sespie   },
203c87b03e5Sespie   {
204c87b03e5Sespie     /* TARGET_H8300S  */
205c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
206c87b03e5Sespie     /*  8    9   10   11   12   13   14   15  */
207c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, INL,
208c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT }, /* SHIFT_ASHIFT   */
209c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, INL,
210c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT }, /* SHIFT_LSHIFTRT */
211c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, INL,
212c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC }, /* SHIFT_ASHIFTRT */
213c87b03e5Sespie   }
214c87b03e5Sespie };
215c87b03e5Sespie 
216c87b03e5Sespie static enum shift_alg shift_alg_si[3][3][32] = {
217c87b03e5Sespie   {
218c87b03e5Sespie     /* TARGET_H8300  */
219c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
220c87b03e5Sespie     /*  8    9   10   11   12   13   14   15  */
221c87b03e5Sespie     /* 16   17   18   19   20   21   22   23  */
222c87b03e5Sespie     /* 24   25   26   27   28   29   30   31  */
223c87b03e5Sespie     { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
224c87b03e5Sespie       SPC, LOP, LOP, LOP, LOP, LOP, LOP, LOP,
225c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, LOP, LOP, LOP,
226c87b03e5Sespie       SPC, SPC, SPC, SPC, LOP, LOP, LOP, SPC }, /* SHIFT_ASHIFT   */
227c87b03e5Sespie     { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
228c87b03e5Sespie       SPC, SPC, LOP, LOP, LOP, LOP, LOP, SPC,
229c87b03e5Sespie       SPC, SPC, SPC, LOP, LOP, LOP, LOP, LOP,
230c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC }, /* SHIFT_LSHIFTRT */
231c87b03e5Sespie     { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
232c87b03e5Sespie       SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
233c87b03e5Sespie       SPC, SPC, LOP, LOP, LOP, LOP, LOP, LOP,
234c87b03e5Sespie       SPC, SPC, SPC, LOP, LOP, LOP, LOP, SPC }, /* SHIFT_ASHIFTRT */
235c87b03e5Sespie   },
236c87b03e5Sespie   {
237c87b03e5Sespie     /* TARGET_H8300H  */
238c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
239c87b03e5Sespie     /*  8    9   10   11   12   13   14   15  */
240c87b03e5Sespie     /* 16   17   18   19   20   21   22   23  */
241c87b03e5Sespie     /* 24   25   26   27   28   29   30   31  */
242c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, LOP,
243c87b03e5Sespie       SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
244c87b03e5Sespie       SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
245c87b03e5Sespie       SPC, LOP, LOP, LOP, SPC, SPC, SPC, SPC }, /* SHIFT_ASHIFT   */
246c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, LOP,
247c87b03e5Sespie       SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
248c87b03e5Sespie       SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
249c87b03e5Sespie       SPC, LOP, LOP, LOP, SPC, SPC, SPC, SPC }, /* SHIFT_LSHIFTRT */
250c87b03e5Sespie     { INL, INL, INL, INL, INL, LOP, LOP, LOP,
251c87b03e5Sespie       SPC, LOP, LOP, LOP, LOP, LOP, LOP, LOP,
252c87b03e5Sespie       SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
253c87b03e5Sespie       SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC }, /* SHIFT_ASHIFTRT */
254c87b03e5Sespie   },
255c87b03e5Sespie   {
256c87b03e5Sespie     /* TARGET_H8300S  */
257c87b03e5Sespie     /*  0    1    2    3    4    5    6    7  */
258c87b03e5Sespie     /*  8    9   10   11   12   13   14   15  */
259c87b03e5Sespie     /* 16   17   18   19   20   21   22   23  */
260c87b03e5Sespie     /* 24   25   26   27   28   29   30   31  */
261c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, INL,
262c87b03e5Sespie       INL, INL, INL, LOP, LOP, LOP, LOP, SPC,
263c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
264c87b03e5Sespie       SPC, SPC, LOP, LOP, SPC, SPC, SPC, SPC }, /* SHIFT_ASHIFT   */
265c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, INL,
266c87b03e5Sespie       INL, INL, INL, LOP, LOP, LOP, LOP, SPC,
267c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
268c87b03e5Sespie       SPC, SPC, LOP, LOP, SPC, SPC, SPC, SPC }, /* SHIFT_LSHIFTRT */
269c87b03e5Sespie     { INL, INL, INL, INL, INL, INL, INL, INL,
270c87b03e5Sespie       INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
271c87b03e5Sespie       SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
272c87b03e5Sespie       SPC, SPC, LOP, LOP, LOP, LOP, LOP, SPC }, /* SHIFT_ASHIFTRT */
273c87b03e5Sespie   }
274c87b03e5Sespie };
275c87b03e5Sespie 
276c87b03e5Sespie #undef INL
277c87b03e5Sespie #undef ROT
278c87b03e5Sespie #undef LOP
279c87b03e5Sespie #undef SPC
280c87b03e5Sespie 
281c87b03e5Sespie enum h8_cpu
282c87b03e5Sespie {
283c87b03e5Sespie   H8_300,
284c87b03e5Sespie   H8_300H,
285c87b03e5Sespie   H8_S
286c87b03e5Sespie };
287c87b03e5Sespie 
288c87b03e5Sespie /* Initialize various cpu specific globals at start up.  */
289c87b03e5Sespie 
290c87b03e5Sespie void
h8300_init_once()291c87b03e5Sespie h8300_init_once ()
292c87b03e5Sespie {
293c87b03e5Sespie   static const char *const h8_push_ops[2] = { "push" , "push.l" };
294c87b03e5Sespie   static const char *const h8_pop_ops[2]  = { "pop"  , "pop.l"  };
295c87b03e5Sespie   static const char *const h8_mov_ops[2]  = { "mov.w", "mov.l"  };
296c87b03e5Sespie 
297c87b03e5Sespie   if (TARGET_H8300)
298c87b03e5Sespie     {
299c87b03e5Sespie       cpu_type = (int) CPU_H8300;
300c87b03e5Sespie       h8_reg_names = names_big;
301c87b03e5Sespie     }
302c87b03e5Sespie   else
303c87b03e5Sespie     {
304c87b03e5Sespie       /* For this we treat the H8/300H and H8S the same.  */
305c87b03e5Sespie       cpu_type = (int) CPU_H8300H;
306c87b03e5Sespie       h8_reg_names = names_extended;
307c87b03e5Sespie     }
308c87b03e5Sespie   h8_push_op = h8_push_ops[cpu_type];
309c87b03e5Sespie   h8_pop_op = h8_pop_ops[cpu_type];
310c87b03e5Sespie   h8_mov_op = h8_mov_ops[cpu_type];
311c87b03e5Sespie 
312c87b03e5Sespie   if (!TARGET_H8300S && TARGET_MAC)
313c87b03e5Sespie     {
314c87b03e5Sespie       error ("-ms2600 is used without -ms");
315c87b03e5Sespie       target_flags |= MASK_H8300S;
316c87b03e5Sespie     }
317c87b03e5Sespie 
318c87b03e5Sespie   if (TARGET_H8300 && TARGET_NORMAL_MODE)
319c87b03e5Sespie     {
320c87b03e5Sespie       error ("-mn is used without -mh or -ms");
321c87b03e5Sespie       target_flags ^= MASK_NORMAL_MODE;
322c87b03e5Sespie     }
323c87b03e5Sespie 
324c87b03e5Sespie   /* Some of the shifts are optimized for speed by default.
325c87b03e5Sespie      See http://gcc.gnu.org/ml/gcc-patches/2002-07/msg01858.html
326c87b03e5Sespie      If optimizing for size, change shift_alg for those shift to
327c87b03e5Sespie      SHIFT_LOOP.  */
328c87b03e5Sespie   if (optimize_size)
329c87b03e5Sespie     {
330c87b03e5Sespie       /* H8/300 */
331c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_ASHIFT][5] = SHIFT_LOOP;
332c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_ASHIFT][6] = SHIFT_LOOP;
333c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_ASHIFT][13] = SHIFT_LOOP;
334c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_ASHIFT][14] = SHIFT_LOOP;
335c87b03e5Sespie 
336c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_LSHIFTRT][13] = SHIFT_LOOP;
337c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_LSHIFTRT][14] = SHIFT_LOOP;
338c87b03e5Sespie 
339c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_ASHIFTRT][13] = SHIFT_LOOP;
340c87b03e5Sespie       shift_alg_hi[H8_300][SHIFT_ASHIFTRT][14] = SHIFT_LOOP;
341c87b03e5Sespie 
342c87b03e5Sespie       /* H8/300H */
343c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_ASHIFT][5] = SHIFT_LOOP;
344c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_ASHIFT][6] = SHIFT_LOOP;
345c87b03e5Sespie 
346c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_LSHIFTRT][5] = SHIFT_LOOP;
347c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_LSHIFTRT][6] = SHIFT_LOOP;
348c87b03e5Sespie 
349c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][5] = SHIFT_LOOP;
350c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][6] = SHIFT_LOOP;
351c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][13] = SHIFT_LOOP;
352c87b03e5Sespie       shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][14] = SHIFT_LOOP;
353c87b03e5Sespie 
354c87b03e5Sespie       /* H8S */
355c87b03e5Sespie       shift_alg_hi[H8_S][SHIFT_ASHIFTRT][14] = SHIFT_LOOP;
356c87b03e5Sespie     }
357c87b03e5Sespie }
358c87b03e5Sespie 
359c87b03e5Sespie static const char *
byte_reg(x,b)360c87b03e5Sespie byte_reg (x, b)
361c87b03e5Sespie      rtx x;
362c87b03e5Sespie      int b;
363c87b03e5Sespie {
364c87b03e5Sespie   static const char *const names_small[] = {
365c87b03e5Sespie     "r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
366c87b03e5Sespie     "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"
367c87b03e5Sespie   };
368c87b03e5Sespie 
369c87b03e5Sespie   return names_small[REGNO (x) * 2 + b];
370c87b03e5Sespie }
371c87b03e5Sespie 
372c87b03e5Sespie /* REGNO must be saved/restored across calls if this macro is true.  */
373c87b03e5Sespie 
374c87b03e5Sespie #define WORD_REG_USED(regno)						\
375c87b03e5Sespie   (regno < 7								\
376c87b03e5Sespie    /* No need to save registers if this function will not return.  */	\
377c87b03e5Sespie    && ! TREE_THIS_VOLATILE (current_function_decl)			\
378c87b03e5Sespie    && (pragma_saveall							\
379c87b03e5Sespie        /* Save any call saved register that was used.  */		\
380c87b03e5Sespie        || (regs_ever_live[regno] && !call_used_regs[regno])		\
381c87b03e5Sespie        /* Save the frame pointer if it was used.  */			\
382c87b03e5Sespie        || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])	\
383c87b03e5Sespie        /* Save any register used in an interrupt handler.  */		\
384c87b03e5Sespie        || (interrupt_handler && regs_ever_live[regno])			\
385c87b03e5Sespie        /* Save call clobbered registers in non-leaf interrupt		\
386c87b03e5Sespie 	  handlers.  */							\
387c87b03e5Sespie        || (interrupt_handler						\
388c87b03e5Sespie 	   && call_used_regs[regno]					\
389c87b03e5Sespie 	   && !current_function_is_leaf)))
390c87b03e5Sespie 
391c87b03e5Sespie /* Output assembly language to FILE for the operation OP with operand size
392c87b03e5Sespie    SIZE to adjust the stack pointer.  */
393c87b03e5Sespie 
394c87b03e5Sespie static void
dosize(file,sign,size)395c87b03e5Sespie dosize (file, sign, size)
396c87b03e5Sespie      FILE *file;
397c87b03e5Sespie      int sign;
398c87b03e5Sespie      unsigned int size;
399c87b03e5Sespie {
400c87b03e5Sespie   /* On the H8/300H and H8S, for sizes <= 8 bytes, it is as good or
401c87b03e5Sespie      better to use adds/subs insns rather than add.l/sub.l with an
402c87b03e5Sespie      immediate value.
403c87b03e5Sespie 
404c87b03e5Sespie      Also, on the H8/300, if we don't have a temporary to hold the
405c87b03e5Sespie      size of the frame in the prologue, we simply emit a sequence of
406c87b03e5Sespie      subs since this shouldn't happen often.  */
407c87b03e5Sespie   if ((TARGET_H8300 && size <= 4)
408c87b03e5Sespie       || ((TARGET_H8300H || TARGET_H8300S) && size <= 8)
409c87b03e5Sespie       || (TARGET_H8300 && interrupt_handler)
410c87b03e5Sespie       || (TARGET_H8300 && current_function_needs_context
411c87b03e5Sespie 	  && sign < 0))
412c87b03e5Sespie     {
413c87b03e5Sespie       const char *op = (sign > 0) ? "add" : "sub";
414c87b03e5Sespie       unsigned HOST_WIDE_INT amount;
415c87b03e5Sespie 
416c87b03e5Sespie       /* Try different amounts in descending order.  */
417c87b03e5Sespie       for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
418c87b03e5Sespie 	   amount > 0;
419c87b03e5Sespie 	   amount /= 2)
420c87b03e5Sespie 	{
421c87b03e5Sespie 	  char insn[100];
422c87b03e5Sespie 
423c87b03e5Sespie 	  sprintf (insn, "\t%ss\t#%d,%s\n", op, amount,
424c87b03e5Sespie 		   TARGET_H8300 ? "r7" : "er7");
425c87b03e5Sespie 	  for (; size >= amount; size -= amount)
426c87b03e5Sespie 	    fputs (insn, file);
427c87b03e5Sespie 	}
428c87b03e5Sespie     }
429c87b03e5Sespie   else
430c87b03e5Sespie     {
431c87b03e5Sespie       if (TARGET_H8300)
432c87b03e5Sespie 	{
433c87b03e5Sespie 	  fprintf (file, "\tmov.w\t#%d,r3\n\tadd.w\tr3,r7\n", sign * size);
434c87b03e5Sespie 	}
435c87b03e5Sespie       else
436c87b03e5Sespie 	{
437c87b03e5Sespie 	  fprintf (file, "\tadd.l\t#%d,er7\n", sign * size);
438c87b03e5Sespie 	}
439c87b03e5Sespie     }
440c87b03e5Sespie }
441c87b03e5Sespie 
442c87b03e5Sespie /* Round up frame size SIZE.  */
443c87b03e5Sespie 
444c87b03e5Sespie static int
round_frame_size(size)445c87b03e5Sespie round_frame_size (size)
446c87b03e5Sespie      int size;
447c87b03e5Sespie {
448c87b03e5Sespie   return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
449c87b03e5Sespie 	  & -STACK_BOUNDARY / BITS_PER_UNIT);
450c87b03e5Sespie }
451c87b03e5Sespie 
452c87b03e5Sespie /* Compute which registers to push/pop.
453c87b03e5Sespie    Return a bit vector of registers.  */
454c87b03e5Sespie 
455c87b03e5Sespie static unsigned int
compute_saved_regs()456c87b03e5Sespie compute_saved_regs ()
457c87b03e5Sespie {
458c87b03e5Sespie   unsigned int saved_regs = 0;
459c87b03e5Sespie   int regno;
460c87b03e5Sespie 
461c87b03e5Sespie   /* Construct a bit vector of registers to be pushed/popped.  */
462c87b03e5Sespie   for (regno = 0; regno <= FRAME_POINTER_REGNUM; regno++)
463c87b03e5Sespie     {
464c87b03e5Sespie       if (WORD_REG_USED (regno))
465c87b03e5Sespie 	saved_regs |= 1 << regno;
466c87b03e5Sespie     }
467c87b03e5Sespie 
468c87b03e5Sespie   /* Don't push/pop the frame pointer as it is treated separately.  */
469c87b03e5Sespie   if (frame_pointer_needed)
470c87b03e5Sespie     saved_regs &= ~(1 << FRAME_POINTER_REGNUM);
471c87b03e5Sespie 
472c87b03e5Sespie   return saved_regs;
473c87b03e5Sespie }
474c87b03e5Sespie 
475c87b03e5Sespie /* Output assembly language code to push register RN.  */
476c87b03e5Sespie 
477c87b03e5Sespie static void
push(file,rn)478c87b03e5Sespie push (file, rn)
479c87b03e5Sespie      FILE *file;
480c87b03e5Sespie      int rn;
481c87b03e5Sespie {
482c87b03e5Sespie   if (TARGET_H8300)
483c87b03e5Sespie     fprintf (file, "\t%s\t%s,@-r7\n", h8_mov_op, h8_reg_names[rn]);
484c87b03e5Sespie   else
485c87b03e5Sespie     fprintf (file, "\t%s\t%s,@-er7\n", h8_mov_op, h8_reg_names[rn]);
486c87b03e5Sespie }
487c87b03e5Sespie 
488c87b03e5Sespie /* Output assembly language code to pop register RN.  */
489c87b03e5Sespie 
490c87b03e5Sespie static void
pop(file,rn)491c87b03e5Sespie pop (file, rn)
492c87b03e5Sespie      FILE *file;
493c87b03e5Sespie      int rn;
494c87b03e5Sespie {
495c87b03e5Sespie   if (TARGET_H8300)
496c87b03e5Sespie     fprintf (file, "\t%s\t@r7+,%s\n", h8_mov_op, h8_reg_names[rn]);
497c87b03e5Sespie   else
498c87b03e5Sespie     fprintf (file, "\t%s\t@er7+,%s\n", h8_mov_op, h8_reg_names[rn]);
499c87b03e5Sespie }
500c87b03e5Sespie 
501c87b03e5Sespie /* This is what the stack looks like after the prolog of
502c87b03e5Sespie    a function with a frame has been set up:
503c87b03e5Sespie 
504c87b03e5Sespie    <args>
505c87b03e5Sespie    PC
506c87b03e5Sespie    FP			<- fp
507c87b03e5Sespie    <locals>
508c87b03e5Sespie    <saved registers>	<- sp
509c87b03e5Sespie 
510c87b03e5Sespie    This is what the stack looks like after the prolog of
511c87b03e5Sespie    a function which doesn't have a frame:
512c87b03e5Sespie 
513c87b03e5Sespie    <args>
514c87b03e5Sespie    PC
515c87b03e5Sespie    <locals>
516c87b03e5Sespie    <saved registers>	<- sp
517c87b03e5Sespie */
518c87b03e5Sespie 
519c87b03e5Sespie /* Output assembly language code for the function prologue.  */
520c87b03e5Sespie 
521c87b03e5Sespie static void
h8300_output_function_prologue(file,size)522c87b03e5Sespie h8300_output_function_prologue (file, size)
523c87b03e5Sespie      FILE *file;
524c87b03e5Sespie      HOST_WIDE_INT size;
525c87b03e5Sespie {
526c87b03e5Sespie   int fsize = round_frame_size (size);
527c87b03e5Sespie   int regno;
528c87b03e5Sespie   int saved_regs;
529c87b03e5Sespie   int n_regs;
530c87b03e5Sespie 
531c87b03e5Sespie   /* Note a function with the interrupt attribute and set interrupt_handler
532c87b03e5Sespie      accordingly.  */
533c87b03e5Sespie   if (h8300_interrupt_function_p (current_function_decl))
534c87b03e5Sespie     interrupt_handler = 1;
535c87b03e5Sespie 
536c87b03e5Sespie   /* If the current function has the OS_Task attribute set, then
537c87b03e5Sespie      we have a naked prologue.  */
538c87b03e5Sespie   if (h8300_os_task_function_p (current_function_decl))
539c87b03e5Sespie     {
540c87b03e5Sespie       fprintf (file, ";OS_Task prologue\n");
541c87b03e5Sespie       os_task = 1;
542c87b03e5Sespie       return;
543c87b03e5Sespie     }
544c87b03e5Sespie 
545c87b03e5Sespie   if (h8300_monitor_function_p (current_function_decl))
546c87b03e5Sespie     {
547c87b03e5Sespie       /* My understanding of monitor functions is they act just
548c87b03e5Sespie 	 like interrupt functions, except the prologue must
549c87b03e5Sespie 	 mask interrupts.  */
550c87b03e5Sespie       fprintf (file, ";monitor prologue\n");
551c87b03e5Sespie       interrupt_handler = 1;
552c87b03e5Sespie       monitor = 1;
553c87b03e5Sespie       if (TARGET_H8300)
554c87b03e5Sespie 	{
555c87b03e5Sespie 	  fprintf (file, "\tsubs\t#2,sp\n");
556c87b03e5Sespie 	  push (file, 0);
557c87b03e5Sespie 	  fprintf (file, "\tstc\tccr,r0l\n");
558c87b03e5Sespie 	  fprintf (file, "\tmov.b\tr0l,@(2,sp)\n");
559c87b03e5Sespie 	  pop (file, 0);
560c87b03e5Sespie 	  fprintf (file, "\torc\t#128,ccr\n");
561c87b03e5Sespie 	}
562c87b03e5Sespie       else if (TARGET_H8300H)
563c87b03e5Sespie 	{
564c87b03e5Sespie 	  push (file, 0);
565c87b03e5Sespie 	  fprintf (file, "\tstc\tccr,r0l\n");
566c87b03e5Sespie 	  fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");
567c87b03e5Sespie 	  pop (file, 0);
568c87b03e5Sespie 	  fprintf (file, "\torc\t#128,ccr\n");
569c87b03e5Sespie 	}
570c87b03e5Sespie       else if (TARGET_H8300S)
571c87b03e5Sespie 	{
572c87b03e5Sespie 	  fprintf (file, "\tstc\texr,@-sp\n");
573c87b03e5Sespie 	  push (file, 0);
574c87b03e5Sespie 	  fprintf (file, "\tstc\tccr,r0l\n");
575c87b03e5Sespie 	  fprintf (file, "\tmov.b\tr0l,@(6,sp)\n");
576c87b03e5Sespie 	  pop (file, 0);
577c87b03e5Sespie 	  fprintf (file, "\torc\t#128,ccr\n");
578c87b03e5Sespie 	}
579c87b03e5Sespie       else
580c87b03e5Sespie 	abort ();
581c87b03e5Sespie     }
582c87b03e5Sespie 
583c87b03e5Sespie   if (frame_pointer_needed)
584c87b03e5Sespie     {
585c87b03e5Sespie       /* Push fp.  */
586c87b03e5Sespie       push (file, FRAME_POINTER_REGNUM);
587c87b03e5Sespie       fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,
588c87b03e5Sespie 	       h8_reg_names[STACK_POINTER_REGNUM],
589c87b03e5Sespie 	       h8_reg_names[FRAME_POINTER_REGNUM]);
590c87b03e5Sespie     }
591c87b03e5Sespie 
592c87b03e5Sespie   /* Leave room for locals.  */
593c87b03e5Sespie   dosize (file, -1, fsize);
594c87b03e5Sespie 
595c87b03e5Sespie   /* Push the rest of the registers in ascending order.  */
596c87b03e5Sespie   saved_regs = compute_saved_regs ();
597c87b03e5Sespie   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs)
598c87b03e5Sespie     {
599c87b03e5Sespie       n_regs = 1;
600c87b03e5Sespie       if (saved_regs & (1 << regno))
601c87b03e5Sespie 	{
602c87b03e5Sespie 	  if (TARGET_H8300S)
603c87b03e5Sespie 	    {
604c87b03e5Sespie 	      /* See how many registers we can push at the same time.  */
605c87b03e5Sespie 	      if ((regno == 0 || regno == 4)
606c87b03e5Sespie 		  && ((saved_regs >> regno) & 0x0f) == 0x0f)
607c87b03e5Sespie 		n_regs = 4;
608c87b03e5Sespie 
609c87b03e5Sespie 	      else if ((regno == 0 || regno == 4)
610c87b03e5Sespie 		       && ((saved_regs >> regno) & 0x07) == 0x07)
611c87b03e5Sespie 		n_regs = 3;
612c87b03e5Sespie 
613c87b03e5Sespie 	      else if ((regno == 0 || regno == 2 || regno == 4 || regno == 6)
614c87b03e5Sespie 		       && ((saved_regs >> regno) & 0x03) == 0x03)
615c87b03e5Sespie 		n_regs = 2;
616c87b03e5Sespie 	    }
617c87b03e5Sespie 
618c87b03e5Sespie 	  switch (n_regs)
619c87b03e5Sespie 	    {
620c87b03e5Sespie 	    case 1:
621c87b03e5Sespie 	      push (file, regno);
622c87b03e5Sespie 	      break;
623c87b03e5Sespie 	    case 2:
624c87b03e5Sespie 	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",
625c87b03e5Sespie 		       h8_reg_names[regno],
626c87b03e5Sespie 		       h8_reg_names[regno + 1]);
627c87b03e5Sespie 	      break;
628c87b03e5Sespie 	    case 3:
629c87b03e5Sespie 	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",
630c87b03e5Sespie 		       h8_reg_names[regno],
631c87b03e5Sespie 		       h8_reg_names[regno + 2]);
632c87b03e5Sespie 	      break;
633c87b03e5Sespie 	    case 4:
634c87b03e5Sespie 	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",
635c87b03e5Sespie 		       h8_reg_names[regno],
636c87b03e5Sespie 		       h8_reg_names[regno + 3]);
637c87b03e5Sespie 	      break;
638c87b03e5Sespie 	    default:
639c87b03e5Sespie 	      abort ();
640c87b03e5Sespie 	    }
641c87b03e5Sespie 	}
642c87b03e5Sespie     }
643c87b03e5Sespie }
644c87b03e5Sespie 
645c87b03e5Sespie /* Output assembly language code for the function epilogue.  */
646c87b03e5Sespie 
647c87b03e5Sespie static void
h8300_output_function_epilogue(file,size)648c87b03e5Sespie h8300_output_function_epilogue (file, size)
649c87b03e5Sespie      FILE *file;
650c87b03e5Sespie      HOST_WIDE_INT size;
651c87b03e5Sespie {
652c87b03e5Sespie   int fsize = round_frame_size (size);
653c87b03e5Sespie   int regno;
654c87b03e5Sespie   rtx insn = get_last_insn ();
655c87b03e5Sespie   int saved_regs;
656c87b03e5Sespie   int n_regs;
657c87b03e5Sespie 
658c87b03e5Sespie   if (os_task)
659c87b03e5Sespie     {
660c87b03e5Sespie       /* OS_Task epilogues are nearly naked -- they just have an
661c87b03e5Sespie 	 rts instruction.  */
662c87b03e5Sespie       fprintf (file, ";OS_task epilogue\n");
663c87b03e5Sespie       fprintf (file, "\trts\n");
664c87b03e5Sespie       goto out;
665c87b03e5Sespie     }
666c87b03e5Sespie 
667c87b03e5Sespie   /* Monitor epilogues are the same as interrupt function epilogues.
668c87b03e5Sespie      Just make a note that we're in an monitor epilogue.  */
669c87b03e5Sespie   if (monitor)
670c87b03e5Sespie     fprintf (file, ";monitor epilogue\n");
671c87b03e5Sespie 
672c87b03e5Sespie   /* If the last insn was a BARRIER, we don't have to write any code.  */
673c87b03e5Sespie   if (GET_CODE (insn) == NOTE)
674c87b03e5Sespie     insn = prev_nonnote_insn (insn);
675c87b03e5Sespie   if (insn && GET_CODE (insn) == BARRIER)
676c87b03e5Sespie     goto out;
677c87b03e5Sespie 
678c87b03e5Sespie   /* Pop the saved registers in descending order.  */
679c87b03e5Sespie   saved_regs = compute_saved_regs ();
680c87b03e5Sespie   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno -= n_regs)
681c87b03e5Sespie     {
682c87b03e5Sespie       n_regs = 1;
683c87b03e5Sespie       if (saved_regs & (1 << regno))
684c87b03e5Sespie 	{
685c87b03e5Sespie 	  if (TARGET_H8300S)
686c87b03e5Sespie 	    {
687c87b03e5Sespie 	      /* See how many registers we can pop at the same time.  */
688c87b03e5Sespie 	      if ((regno == 7 || regno == 3)
689c87b03e5Sespie 		  && ((saved_regs >> (regno - 3)) & 0x0f) == 0x0f)
690c87b03e5Sespie 		n_regs = 4;
691c87b03e5Sespie 
692c87b03e5Sespie 	      else if ((regno == 6 || regno == 2)
693c87b03e5Sespie 		       && ((saved_regs >> (regno - 2)) & 0x07) == 0x07)
694c87b03e5Sespie 		n_regs = 3;
695c87b03e5Sespie 
696c87b03e5Sespie 	      else if ((regno == 7 || regno == 5 || regno == 3 || regno == 1)
697c87b03e5Sespie 		       && ((saved_regs >> (regno - 1)) & 0x03) == 0x03)
698c87b03e5Sespie 		n_regs = 2;
699c87b03e5Sespie 	    }
700c87b03e5Sespie 
701c87b03e5Sespie 	  switch (n_regs)
702c87b03e5Sespie 	    {
703c87b03e5Sespie 	    case 1:
704c87b03e5Sespie 	      pop (file, regno);
705c87b03e5Sespie 	      break;
706c87b03e5Sespie 	    case 2:
707c87b03e5Sespie 	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",
708c87b03e5Sespie 		       h8_reg_names[regno - 1],
709c87b03e5Sespie 		       h8_reg_names[regno]);
710c87b03e5Sespie 	      break;
711c87b03e5Sespie 	    case 3:
712c87b03e5Sespie 	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",
713c87b03e5Sespie 		       h8_reg_names[regno - 2],
714c87b03e5Sespie 		       h8_reg_names[regno]);
715c87b03e5Sespie 	      break;
716c87b03e5Sespie 	    case 4:
717c87b03e5Sespie 	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",
718c87b03e5Sespie 		       h8_reg_names[regno - 3],
719c87b03e5Sespie 		       h8_reg_names[regno]);
720c87b03e5Sespie 	      break;
721c87b03e5Sespie 	    default:
722c87b03e5Sespie 	      abort ();
723c87b03e5Sespie 	    }
724c87b03e5Sespie 	}
725c87b03e5Sespie     }
726c87b03e5Sespie 
727c87b03e5Sespie   /* Deallocate locals.  */
728c87b03e5Sespie   dosize (file, 1, fsize);
729c87b03e5Sespie 
730c87b03e5Sespie   /* Pop frame pointer if we had one.  */
731c87b03e5Sespie   if (frame_pointer_needed)
732c87b03e5Sespie     pop (file, FRAME_POINTER_REGNUM);
733c87b03e5Sespie 
734c87b03e5Sespie   if (interrupt_handler)
735c87b03e5Sespie     fprintf (file, "\trte\n");
736c87b03e5Sespie   else
737c87b03e5Sespie     fprintf (file, "\trts\n");
738c87b03e5Sespie 
739c87b03e5Sespie  out:
740c87b03e5Sespie   interrupt_handler = 0;
741c87b03e5Sespie   os_task = 0;
742c87b03e5Sespie   monitor = 0;
743c87b03e5Sespie   pragma_saveall = 0;
744c87b03e5Sespie }
745c87b03e5Sespie 
746c87b03e5Sespie /* Output assembly code for the start of the file.  */
747c87b03e5Sespie 
748c87b03e5Sespie void
asm_file_start(file)749c87b03e5Sespie asm_file_start (file)
750c87b03e5Sespie      FILE *file;
751c87b03e5Sespie {
752c87b03e5Sespie   fprintf (file, ";\tGCC For the Hitachi H8/300\n");
753c87b03e5Sespie   fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n");
754c87b03e5Sespie 
755c87b03e5Sespie   if (optimize_size)
756c87b03e5Sespie     fprintf (file, "; -Os\n");
757c87b03e5Sespie   else if (optimize)
758c87b03e5Sespie     fprintf (file, "; -O%d\n", optimize);
759c87b03e5Sespie   if (TARGET_H8300H)
760*4e43c760Sespie     fprintf (file, TARGET_NORMAL_MODE ? "\n\t.h8300hn\n" : "\n\t.h8300h\n");
761c87b03e5Sespie   else if (TARGET_H8300S)
762*4e43c760Sespie     fprintf (file, TARGET_NORMAL_MODE ? "\n\t.h8300sn\n" : "\n\t.h8300s\n");
763c87b03e5Sespie   else
764c87b03e5Sespie     fprintf (file, "\n\n");
765c87b03e5Sespie   output_file_directive (file, main_input_filename);
766c87b03e5Sespie }
767c87b03e5Sespie 
768c87b03e5Sespie /* Output assembly language code for the end of file.  */
769c87b03e5Sespie 
770c87b03e5Sespie void
asm_file_end(file)771c87b03e5Sespie asm_file_end (file)
772c87b03e5Sespie      FILE *file;
773c87b03e5Sespie {
774c87b03e5Sespie   fprintf (file, "\t.end\n");
775c87b03e5Sespie }
776c87b03e5Sespie 
777c87b03e5Sespie /* Return true if OP is a valid source operand for an integer move
778c87b03e5Sespie    instruction.  */
779c87b03e5Sespie 
780c87b03e5Sespie int
general_operand_src(op,mode)781c87b03e5Sespie general_operand_src (op, mode)
782c87b03e5Sespie      rtx op;
783c87b03e5Sespie      enum machine_mode mode;
784c87b03e5Sespie {
785c87b03e5Sespie   if (GET_MODE (op) == mode
786c87b03e5Sespie       && GET_CODE (op) == MEM
787c87b03e5Sespie       && GET_CODE (XEXP (op, 0)) == POST_INC)
788c87b03e5Sespie     return 1;
789c87b03e5Sespie   return general_operand (op, mode);
790c87b03e5Sespie }
791c87b03e5Sespie 
792c87b03e5Sespie /* Return true if OP is a valid destination operand for an integer move
793c87b03e5Sespie    instruction.  */
794c87b03e5Sespie 
795c87b03e5Sespie int
general_operand_dst(op,mode)796c87b03e5Sespie general_operand_dst (op, mode)
797c87b03e5Sespie      rtx op;
798c87b03e5Sespie      enum machine_mode mode;
799c87b03e5Sespie {
800c87b03e5Sespie   if (GET_MODE (op) == mode
801c87b03e5Sespie       && GET_CODE (op) == MEM
802c87b03e5Sespie       && GET_CODE (XEXP (op, 0)) == PRE_DEC)
803c87b03e5Sespie     return 1;
804c87b03e5Sespie   return general_operand (op, mode);
805c87b03e5Sespie }
806c87b03e5Sespie 
807c87b03e5Sespie /* Return true if OP is a constant that contains only one 1 in its
808c87b03e5Sespie    binary representation.  */
809c87b03e5Sespie 
810c87b03e5Sespie int
single_one_operand(operand,mode)811c87b03e5Sespie single_one_operand (operand, mode)
812c87b03e5Sespie      rtx operand;
813c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
814c87b03e5Sespie {
815c87b03e5Sespie   if (GET_CODE (operand) == CONST_INT)
816c87b03e5Sespie     {
817c87b03e5Sespie       /* We really need to do this masking because 0x80 in QImode is
818c87b03e5Sespie 	 represented as -128 for example.  */
819c87b03e5Sespie       unsigned HOST_WIDE_INT mask =
820c87b03e5Sespie 	(GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
821c87b03e5Sespie 	? ((unsigned HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (mode)) - 1
822c87b03e5Sespie 	: ~(unsigned HOST_WIDE_INT) 0;
823c87b03e5Sespie       unsigned HOST_WIDE_INT value = INTVAL (operand);
824c87b03e5Sespie 
825c87b03e5Sespie       if (exact_log2 (value & mask) >= 0)
826c87b03e5Sespie 	return 1;
827c87b03e5Sespie     }
828c87b03e5Sespie 
829c87b03e5Sespie   return 0;
830c87b03e5Sespie }
831c87b03e5Sespie 
832c87b03e5Sespie /* Return true if OP is a constant that contains only one 0 in its
833c87b03e5Sespie    binary representation.  */
834c87b03e5Sespie 
835c87b03e5Sespie int
single_zero_operand(operand,mode)836c87b03e5Sespie single_zero_operand (operand, mode)
837c87b03e5Sespie      rtx operand;
838c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
839c87b03e5Sespie {
840c87b03e5Sespie   if (GET_CODE (operand) == CONST_INT)
841c87b03e5Sespie     {
842c87b03e5Sespie       /* We really need to do this masking because 0x80 in QImode is
843c87b03e5Sespie 	 represented as -128 for example.  */
844c87b03e5Sespie       unsigned HOST_WIDE_INT mask =
845c87b03e5Sespie 	(GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
846c87b03e5Sespie 	? ((unsigned HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (mode)) - 1
847c87b03e5Sespie 	: ~(unsigned HOST_WIDE_INT) 0;
848c87b03e5Sespie       unsigned HOST_WIDE_INT value = INTVAL (operand);
849c87b03e5Sespie 
850c87b03e5Sespie       if (exact_log2 (~value & mask) >= 0)
851c87b03e5Sespie 	return 1;
852c87b03e5Sespie     }
853c87b03e5Sespie 
854c87b03e5Sespie   return 0;
855c87b03e5Sespie }
856c87b03e5Sespie 
857c87b03e5Sespie /* Return true if OP is a valid call operand.  */
858c87b03e5Sespie 
859c87b03e5Sespie int
call_insn_operand(op,mode)860c87b03e5Sespie call_insn_operand (op, mode)
861c87b03e5Sespie      rtx op;
862c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
863c87b03e5Sespie {
864c87b03e5Sespie   if (GET_CODE (op) == MEM)
865c87b03e5Sespie     {
866c87b03e5Sespie       rtx inside = XEXP (op, 0);
867c87b03e5Sespie       if (register_operand (inside, Pmode))
868c87b03e5Sespie 	return 1;
869c87b03e5Sespie       if (CONSTANT_ADDRESS_P (inside))
870c87b03e5Sespie 	return 1;
871c87b03e5Sespie     }
872c87b03e5Sespie   return 0;
873c87b03e5Sespie }
874c87b03e5Sespie 
875c87b03e5Sespie /* Return 1 if an addition/subtraction of a constant integer can be
876c87b03e5Sespie    transformed into two consecutive adds/subs that are faster than the
877c87b03e5Sespie    straightforward way.  Otherwise, return 0.  */
878c87b03e5Sespie 
879c87b03e5Sespie int
two_insn_adds_subs_operand(op,mode)880c87b03e5Sespie two_insn_adds_subs_operand (op, mode)
881c87b03e5Sespie      rtx op;
882c87b03e5Sespie      enum machine_mode mode;
883c87b03e5Sespie {
884c87b03e5Sespie   if (GET_CODE (op) == CONST_INT)
885c87b03e5Sespie     {
886c87b03e5Sespie       HOST_WIDE_INT value = INTVAL (op);
887c87b03e5Sespie 
888c87b03e5Sespie       /* Force VALUE to be positive so that we do not have to consider
889c87b03e5Sespie          the negative case.  */
890c87b03e5Sespie       if (value < 0)
891c87b03e5Sespie 	value = -value;
892c87b03e5Sespie       if (TARGET_H8300H || TARGET_H8300S)
893c87b03e5Sespie 	{
894c87b03e5Sespie 	  /* A constant addition/subtraction takes 2 states in QImode,
895c87b03e5Sespie 	     4 states in HImode, and 6 states in SImode.  Thus, the
896c87b03e5Sespie 	     only case we can win is when SImode is used, in which
897c87b03e5Sespie 	     case, two adds/subs are used, taking 4 states.  */
898c87b03e5Sespie 	  if (mode == SImode
899c87b03e5Sespie 	      && (value == 2 + 1
900c87b03e5Sespie 		  || value == 4 + 1
901c87b03e5Sespie 		  || value == 4 + 2
902c87b03e5Sespie 		  || value == 4 + 4))
903c87b03e5Sespie 	    return 1;
904c87b03e5Sespie 	}
905c87b03e5Sespie       else
906c87b03e5Sespie 	{
907c87b03e5Sespie 	  /* We do not profit directly by splitting addition or
908c87b03e5Sespie 	     subtraction of 3 and 4.  However, since these are
909c87b03e5Sespie 	     implemented as a sequence of adds or subs, they do not
910c87b03e5Sespie 	     clobber (cc0) unlike a sequence of add.b and add.x.  */
911c87b03e5Sespie 	  if (mode == HImode
912c87b03e5Sespie 	      && (value == 2 + 1
913c87b03e5Sespie 		  || value == 2 + 2))
914c87b03e5Sespie 	    return 1;
915c87b03e5Sespie 	}
916c87b03e5Sespie     }
917c87b03e5Sespie 
918c87b03e5Sespie   return 0;
919c87b03e5Sespie }
920c87b03e5Sespie 
921c87b03e5Sespie /* Split an add of a small constant into two adds/subs insns.  */
922c87b03e5Sespie 
923c87b03e5Sespie void
split_adds_subs(mode,operands)924c87b03e5Sespie split_adds_subs (mode, operands)
925c87b03e5Sespie      enum machine_mode mode;
926c87b03e5Sespie      rtx *operands;
927c87b03e5Sespie {
928c87b03e5Sespie   HOST_WIDE_INT val = INTVAL (operands[1]);
929c87b03e5Sespie   rtx reg = operands[0];
930c87b03e5Sespie   HOST_WIDE_INT sign = 1;
931c87b03e5Sespie   HOST_WIDE_INT amount;
932c87b03e5Sespie 
933c87b03e5Sespie   /* Force VAL to be positive so that we do not have to consider the
934c87b03e5Sespie      sign.  */
935c87b03e5Sespie   if (val < 0)
936c87b03e5Sespie     {
937c87b03e5Sespie       val = -val;
938c87b03e5Sespie       sign = -1;
939c87b03e5Sespie     }
940c87b03e5Sespie 
941c87b03e5Sespie   /* Try different amounts in descending order.  */
942c87b03e5Sespie   for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
943c87b03e5Sespie        amount > 0;
944c87b03e5Sespie        amount /= 2)
945c87b03e5Sespie     {
946c87b03e5Sespie       for (; val >= amount; val -= amount)
947c87b03e5Sespie 	{
948c87b03e5Sespie 	  rtx tmp = gen_rtx_PLUS (mode, reg, GEN_INT (sign * amount));
949c87b03e5Sespie 	  emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
950c87b03e5Sespie 	}
951c87b03e5Sespie     }
952c87b03e5Sespie 
953c87b03e5Sespie   return;
954c87b03e5Sespie }
955c87b03e5Sespie 
956c87b03e5Sespie /* Return true if OP is a valid call operand, and OP represents
957c87b03e5Sespie    an operand for a small call (4 bytes instead of 6 bytes).  */
958c87b03e5Sespie 
959c87b03e5Sespie int
small_call_insn_operand(op,mode)960c87b03e5Sespie small_call_insn_operand (op, mode)
961c87b03e5Sespie      rtx op;
962c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
963c87b03e5Sespie {
964c87b03e5Sespie   if (GET_CODE (op) == MEM)
965c87b03e5Sespie     {
966c87b03e5Sespie       rtx inside = XEXP (op, 0);
967c87b03e5Sespie 
968c87b03e5Sespie       /* Register indirect is a small call.  */
969c87b03e5Sespie       if (register_operand (inside, Pmode))
970c87b03e5Sespie 	return 1;
971c87b03e5Sespie 
972c87b03e5Sespie       /* A call through the function vector is a small
973c87b03e5Sespie 	 call too.  */
974c87b03e5Sespie       if (GET_CODE (inside) == SYMBOL_REF
975c87b03e5Sespie 	  && SYMBOL_REF_FLAG (inside))
976c87b03e5Sespie 	return 1;
977c87b03e5Sespie     }
978c87b03e5Sespie   /* Otherwise it's a large call.  */
979c87b03e5Sespie   return 0;
980c87b03e5Sespie }
981c87b03e5Sespie 
982c87b03e5Sespie /* Return true if OP is a valid jump operand.  */
983c87b03e5Sespie 
984c87b03e5Sespie int
jump_address_operand(op,mode)985c87b03e5Sespie jump_address_operand (op, mode)
986c87b03e5Sespie      rtx op;
987c87b03e5Sespie      enum machine_mode mode;
988c87b03e5Sespie {
989c87b03e5Sespie   if (GET_CODE (op) == REG)
990c87b03e5Sespie     return mode == Pmode;
991c87b03e5Sespie 
992c87b03e5Sespie   if (GET_CODE (op) == MEM)
993c87b03e5Sespie     {
994c87b03e5Sespie       rtx inside = XEXP (op, 0);
995c87b03e5Sespie       if (register_operand (inside, Pmode))
996c87b03e5Sespie 	return 1;
997c87b03e5Sespie       if (CONSTANT_ADDRESS_P (inside))
998c87b03e5Sespie 	return 1;
999c87b03e5Sespie     }
1000c87b03e5Sespie   return 0;
1001c87b03e5Sespie }
1002c87b03e5Sespie 
1003c87b03e5Sespie /* Recognize valid operands for bit-field instructions.  */
1004c87b03e5Sespie 
1005c87b03e5Sespie extern int rtx_equal_function_value_matters;
1006c87b03e5Sespie 
1007c87b03e5Sespie int
bit_operand(op,mode)1008c87b03e5Sespie bit_operand (op, mode)
1009c87b03e5Sespie      rtx op;
1010c87b03e5Sespie      enum machine_mode mode;
1011c87b03e5Sespie {
1012c87b03e5Sespie   /* We can except any general operand, expept that MEM operands must
1013c87b03e5Sespie      be limited to those that use addresses valid for the 'U' constraint.  */
1014c87b03e5Sespie   if (!general_operand (op, mode))
1015c87b03e5Sespie     return 0;
1016c87b03e5Sespie 
1017c87b03e5Sespie   /* Accept any mem during RTL generation.  Otherwise, the code that does
1018c87b03e5Sespie      insv and extzv will think that we can not handle memory.  However,
1019c87b03e5Sespie      to avoid reload problems, we only accept 'U' MEM operands after RTL
1020c87b03e5Sespie      generation.  This means that any named pattern which uses this predicate
1021c87b03e5Sespie      must force its operands to match 'U' before emitting RTL.  */
1022c87b03e5Sespie 
1023c87b03e5Sespie   if (GET_CODE (op) == REG)
1024c87b03e5Sespie     return 1;
1025c87b03e5Sespie   if (GET_CODE (op) == SUBREG)
1026c87b03e5Sespie     return 1;
1027c87b03e5Sespie   if (!rtx_equal_function_value_matters)
1028c87b03e5Sespie     /* We're building rtl.  */
1029c87b03e5Sespie     return GET_CODE (op) == MEM;
1030c87b03e5Sespie   else
1031c87b03e5Sespie     return (GET_CODE (op) == MEM
1032c87b03e5Sespie 	    && EXTRA_CONSTRAINT (op, 'U'));
1033c87b03e5Sespie }
1034c87b03e5Sespie 
1035c87b03e5Sespie int
bit_memory_operand(op,mode)1036c87b03e5Sespie bit_memory_operand (op, mode)
1037c87b03e5Sespie      rtx op;
1038c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
1039c87b03e5Sespie {
1040c87b03e5Sespie   return (GET_CODE (op) == MEM
1041c87b03e5Sespie 	  && EXTRA_CONSTRAINT (op, 'U'));
1042c87b03e5Sespie }
1043c87b03e5Sespie 
1044c87b03e5Sespie /* Handle machine specific pragmas for compatibility with existing
1045c87b03e5Sespie    compilers for the H8/300.
1046c87b03e5Sespie 
1047c87b03e5Sespie    pragma saveall generates prolog/epilog code which saves and
1048c87b03e5Sespie    restores all the registers on function entry.
1049c87b03e5Sespie 
1050c87b03e5Sespie    pragma interrupt saves and restores all registers, and exits with
1051c87b03e5Sespie    an rte instruction rather than an rts.  A pointer to a function
1052c87b03e5Sespie    with this attribute may be safely used in an interrupt vector.  */
1053c87b03e5Sespie 
1054c87b03e5Sespie void
h8300_pr_interrupt(pfile)1055c87b03e5Sespie h8300_pr_interrupt (pfile)
1056c87b03e5Sespie      cpp_reader *pfile ATTRIBUTE_UNUSED;
1057c87b03e5Sespie {
1058c87b03e5Sespie   interrupt_handler = 1;
1059c87b03e5Sespie }
1060c87b03e5Sespie 
1061c87b03e5Sespie void
h8300_pr_saveall(pfile)1062c87b03e5Sespie h8300_pr_saveall (pfile)
1063c87b03e5Sespie      cpp_reader *pfile ATTRIBUTE_UNUSED;
1064c87b03e5Sespie {
1065c87b03e5Sespie   pragma_saveall = 1;
1066c87b03e5Sespie }
1067c87b03e5Sespie 
1068c87b03e5Sespie /* If the next function argument with MODE and TYPE is to be passed in
1069c87b03e5Sespie    a register, return a reg RTX for the hard register in which to pass
1070c87b03e5Sespie    the argument.  CUM represents the state after the last argument.
1071c87b03e5Sespie    If the argument is to be pushed, NULL_RTX is returned.  */
1072c87b03e5Sespie 
1073c87b03e5Sespie rtx
function_arg(cum,mode,type,named)1074c87b03e5Sespie function_arg (cum, mode, type, named)
1075c87b03e5Sespie      CUMULATIVE_ARGS *cum;
1076c87b03e5Sespie      enum machine_mode mode;
1077c87b03e5Sespie      tree type;
1078c87b03e5Sespie      int named;
1079c87b03e5Sespie {
1080c87b03e5Sespie   static const char *const hand_list[] = {
1081c87b03e5Sespie     "__main",
1082c87b03e5Sespie     "__cmpsi2",
1083c87b03e5Sespie     "__divhi3",
1084c87b03e5Sespie     "__modhi3",
1085c87b03e5Sespie     "__udivhi3",
1086c87b03e5Sespie     "__umodhi3",
1087c87b03e5Sespie     "__divsi3",
1088c87b03e5Sespie     "__modsi3",
1089c87b03e5Sespie     "__udivsi3",
1090c87b03e5Sespie     "__umodsi3",
1091c87b03e5Sespie     "__mulhi3",
1092c87b03e5Sespie     "__mulsi3",
1093c87b03e5Sespie     "__reg_memcpy",
1094c87b03e5Sespie     "__reg_memset",
1095c87b03e5Sespie     "__ucmpsi2",
1096c87b03e5Sespie     0,
1097c87b03e5Sespie   };
1098c87b03e5Sespie 
1099c87b03e5Sespie   rtx result = NULL_RTX;
1100c87b03e5Sespie   const char *fname;
1101c87b03e5Sespie   int regpass = 0;
1102c87b03e5Sespie 
1103c87b03e5Sespie   /* Never pass unnamed arguments in registers.  */
1104c87b03e5Sespie   if (!named)
1105c87b03e5Sespie     return NULL_RTX;
1106c87b03e5Sespie 
1107c87b03e5Sespie   /* Pass 3 regs worth of data in regs when user asked on the command line.  */
1108c87b03e5Sespie   if (TARGET_QUICKCALL)
1109c87b03e5Sespie     regpass = 3;
1110c87b03e5Sespie 
1111c87b03e5Sespie   /* If calling hand written assembler, use 4 regs of args.  */
1112c87b03e5Sespie   if (cum->libcall)
1113c87b03e5Sespie     {
1114c87b03e5Sespie       const char * const *p;
1115c87b03e5Sespie 
1116c87b03e5Sespie       fname = XSTR (cum->libcall, 0);
1117c87b03e5Sespie 
1118c87b03e5Sespie       /* See if this libcall is one of the hand coded ones.  */
1119c87b03e5Sespie       for (p = hand_list; *p && strcmp (*p, fname) != 0; p++)
1120c87b03e5Sespie 	;
1121c87b03e5Sespie 
1122c87b03e5Sespie       if (*p)
1123c87b03e5Sespie 	regpass = 4;
1124c87b03e5Sespie     }
1125c87b03e5Sespie 
1126c87b03e5Sespie   if (regpass)
1127c87b03e5Sespie     {
1128c87b03e5Sespie       int size;
1129c87b03e5Sespie 
1130c87b03e5Sespie       if (mode == BLKmode)
1131c87b03e5Sespie 	size = int_size_in_bytes (type);
1132c87b03e5Sespie       else
1133c87b03e5Sespie 	size = GET_MODE_SIZE (mode);
1134c87b03e5Sespie 
1135c87b03e5Sespie       if (size + cum->nbytes <= regpass * UNITS_PER_WORD
1136c87b03e5Sespie 	  && cum->nbytes / UNITS_PER_WORD <= 3)
1137c87b03e5Sespie 	result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
1138c87b03e5Sespie     }
1139c87b03e5Sespie 
1140c87b03e5Sespie   return result;
1141c87b03e5Sespie }
1142c87b03e5Sespie 
1143c87b03e5Sespie /* Return the cost of the rtx R with code CODE.  */
1144c87b03e5Sespie 
1145c87b03e5Sespie int
const_costs(r,c,outer_code)1146c87b03e5Sespie const_costs (r, c, outer_code)
1147c87b03e5Sespie      rtx r;
1148c87b03e5Sespie      enum rtx_code c;
1149c87b03e5Sespie      enum rtx_code outer_code;
1150c87b03e5Sespie {
1151c87b03e5Sespie   switch (c)
1152c87b03e5Sespie     {
1153c87b03e5Sespie     case CONST_INT:
1154c87b03e5Sespie       switch (INTVAL (r))
1155c87b03e5Sespie 	{
1156c87b03e5Sespie 	case 0:
1157c87b03e5Sespie 	  return 0;
1158c87b03e5Sespie 	case 1:
1159c87b03e5Sespie 	case 2:
1160c87b03e5Sespie 	case -1:
1161c87b03e5Sespie 	case -2:
1162c87b03e5Sespie 	  return 0 + (outer_code == SET);
1163c87b03e5Sespie 	case 4:
1164c87b03e5Sespie 	case -4:
1165c87b03e5Sespie 	  if (TARGET_H8300H || TARGET_H8300S)
1166c87b03e5Sespie 	    return 0 + (outer_code == SET);
1167c87b03e5Sespie 	  else
1168c87b03e5Sespie 	    return 1;
1169c87b03e5Sespie 	default:
1170c87b03e5Sespie 	  return 1;
1171c87b03e5Sespie 	}
1172c87b03e5Sespie 
1173c87b03e5Sespie     case CONST:
1174c87b03e5Sespie     case LABEL_REF:
1175c87b03e5Sespie     case SYMBOL_REF:
1176c87b03e5Sespie       return 3;
1177c87b03e5Sespie 
1178c87b03e5Sespie     case CONST_DOUBLE:
1179c87b03e5Sespie       return 20;
1180c87b03e5Sespie 
1181c87b03e5Sespie     default:
1182c87b03e5Sespie       return 4;
1183c87b03e5Sespie     }
1184c87b03e5Sespie }
1185c87b03e5Sespie 
1186c87b03e5Sespie int
h8300_and_costs(x)1187c87b03e5Sespie h8300_and_costs (x)
1188c87b03e5Sespie      rtx x;
1189c87b03e5Sespie {
1190c87b03e5Sespie   rtx operands[4];
1191c87b03e5Sespie 
1192c87b03e5Sespie   if (GET_MODE (x) == QImode)
1193c87b03e5Sespie     return 1;
1194c87b03e5Sespie 
1195c87b03e5Sespie   if (GET_MODE (x) != HImode
1196c87b03e5Sespie       && GET_MODE (x) != SImode)
1197c87b03e5Sespie     return 100;
1198c87b03e5Sespie 
1199c87b03e5Sespie   operands[0] = NULL;
1200c87b03e5Sespie   operands[1] = NULL;
1201c87b03e5Sespie   operands[2] = XEXP (x, 1);
1202c87b03e5Sespie   operands[3] = x;
1203c87b03e5Sespie   return compute_logical_op_length (GET_MODE (x), operands);
1204c87b03e5Sespie }
1205c87b03e5Sespie 
1206c87b03e5Sespie int
h8300_shift_costs(x)1207c87b03e5Sespie h8300_shift_costs (x)
1208c87b03e5Sespie      rtx x;
1209c87b03e5Sespie {
1210c87b03e5Sespie   rtx operands[4];
1211c87b03e5Sespie 
1212c87b03e5Sespie   if (GET_MODE (x) != QImode
1213c87b03e5Sespie       && GET_MODE (x) != HImode
1214c87b03e5Sespie       && GET_MODE (x) != SImode)
1215c87b03e5Sespie     return 100;
1216c87b03e5Sespie 
1217c87b03e5Sespie   operands[0] = NULL;
1218c87b03e5Sespie   operands[1] = NULL;
1219c87b03e5Sespie   operands[2] = XEXP (x, 1);
1220c87b03e5Sespie   operands[3] = x;
1221c87b03e5Sespie   return compute_a_shift_length (NULL, operands);
1222c87b03e5Sespie }
1223c87b03e5Sespie 
1224c87b03e5Sespie /* Documentation for the machine specific operand escapes:
1225c87b03e5Sespie 
1226c87b03e5Sespie    'E' like s but negative.
1227c87b03e5Sespie    'F' like t but negative.
1228c87b03e5Sespie    'G' constant just the negative
1229c87b03e5Sespie    'R' print operand as a byte:8 address if appropriate, else fall back to
1230c87b03e5Sespie        'X' handling.
1231c87b03e5Sespie    'S' print operand as a long word
1232c87b03e5Sespie    'T' print operand as a word
1233c87b03e5Sespie    'V' find the set bit, and print its number.
1234c87b03e5Sespie    'W' find the clear bit, and print its number.
1235c87b03e5Sespie    'X' print operand as a byte
1236c87b03e5Sespie    'Y' print either l or h depending on whether last 'Z' operand < 8 or >= 8.
1237c87b03e5Sespie        If this operand isn't a register, fall back to 'R' handling.
1238c87b03e5Sespie    'Z' print int & 7.
1239c87b03e5Sespie    'b' print the bit opcode
1240c87b03e5Sespie    'e' first word of 32 bit value - if reg, then least reg. if mem
1241c87b03e5Sespie        then least. if const then most sig word
1242c87b03e5Sespie    'f' second word of 32 bit value - if reg, then biggest reg. if mem
1243c87b03e5Sespie        then +2. if const then least sig word
1244c87b03e5Sespie    'j' print operand as condition code.
1245c87b03e5Sespie    'k' print operand as reverse condition code.
1246c87b03e5Sespie    's' print as low byte of 16 bit value
1247c87b03e5Sespie    't' print as high byte of 16 bit value
1248c87b03e5Sespie    'w' print as low byte of 32 bit value
1249c87b03e5Sespie    'x' print as 2nd byte of 32 bit value
1250c87b03e5Sespie    'y' print as 3rd byte of 32 bit value
1251c87b03e5Sespie    'z' print as msb of 32 bit value
1252c87b03e5Sespie */
1253c87b03e5Sespie 
1254c87b03e5Sespie /* Return assembly language string which identifies a comparison type.  */
1255c87b03e5Sespie 
1256c87b03e5Sespie static const char *
cond_string(code)1257c87b03e5Sespie cond_string (code)
1258c87b03e5Sespie      enum rtx_code code;
1259c87b03e5Sespie {
1260c87b03e5Sespie   switch (code)
1261c87b03e5Sespie     {
1262c87b03e5Sespie     case NE:
1263c87b03e5Sespie       return "ne";
1264c87b03e5Sespie     case EQ:
1265c87b03e5Sespie       return "eq";
1266c87b03e5Sespie     case GE:
1267c87b03e5Sespie       return "ge";
1268c87b03e5Sespie     case GT:
1269c87b03e5Sespie       return "gt";
1270c87b03e5Sespie     case LE:
1271c87b03e5Sespie       return "le";
1272c87b03e5Sespie     case LT:
1273c87b03e5Sespie       return "lt";
1274c87b03e5Sespie     case GEU:
1275c87b03e5Sespie       return "hs";
1276c87b03e5Sespie     case GTU:
1277c87b03e5Sespie       return "hi";
1278c87b03e5Sespie     case LEU:
1279c87b03e5Sespie       return "ls";
1280c87b03e5Sespie     case LTU:
1281c87b03e5Sespie       return "lo";
1282c87b03e5Sespie     default:
1283c87b03e5Sespie       abort ();
1284c87b03e5Sespie     }
1285c87b03e5Sespie }
1286c87b03e5Sespie 
1287c87b03e5Sespie /* Print operand X using operand code CODE to assembly language output file
1288c87b03e5Sespie    FILE.  */
1289c87b03e5Sespie 
1290c87b03e5Sespie void
print_operand(file,x,code)1291c87b03e5Sespie print_operand (file, x, code)
1292c87b03e5Sespie      FILE *file;
1293c87b03e5Sespie      rtx x;
1294c87b03e5Sespie      int code;
1295c87b03e5Sespie {
1296c87b03e5Sespie   /* This is used for communication between codes V,W,Z and Y.  */
1297c87b03e5Sespie   static int bitint;
1298c87b03e5Sespie 
1299c87b03e5Sespie   switch (code)
1300c87b03e5Sespie     {
1301c87b03e5Sespie     case 'E':
1302c87b03e5Sespie       switch (GET_CODE (x))
1303c87b03e5Sespie 	{
1304c87b03e5Sespie 	case REG:
1305c87b03e5Sespie 	  fprintf (file, "%sl", names_big[REGNO (x)]);
1306c87b03e5Sespie 	  break;
1307c87b03e5Sespie 	case CONST_INT:
1308c87b03e5Sespie 	  fprintf (file, "#%d", (-INTVAL (x)) & 0xff);
1309c87b03e5Sespie 	  break;
1310c87b03e5Sespie 	default:
1311c87b03e5Sespie 	  abort ();
1312c87b03e5Sespie 	}
1313c87b03e5Sespie       break;
1314c87b03e5Sespie     case 'F':
1315c87b03e5Sespie       switch (GET_CODE (x))
1316c87b03e5Sespie 	{
1317c87b03e5Sespie 	case REG:
1318c87b03e5Sespie 	  fprintf (file, "%sh", names_big[REGNO (x)]);
1319c87b03e5Sespie 	  break;
1320c87b03e5Sespie 	case CONST_INT:
1321c87b03e5Sespie 	  fprintf (file, "#%d", ((-INTVAL (x)) & 0xff00) >> 8);
1322c87b03e5Sespie 	  break;
1323c87b03e5Sespie 	default:
1324c87b03e5Sespie 	  abort ();
1325c87b03e5Sespie 	}
1326c87b03e5Sespie       break;
1327c87b03e5Sespie     case 'G':
1328c87b03e5Sespie       if (GET_CODE (x) != CONST_INT)
1329c87b03e5Sespie 	abort ();
1330c87b03e5Sespie       fprintf (file, "#%d", 0xff & (-INTVAL (x)));
1331c87b03e5Sespie       break;
1332c87b03e5Sespie     case 'S':
1333c87b03e5Sespie       if (GET_CODE (x) == REG)
1334c87b03e5Sespie 	fprintf (file, "%s", names_extended[REGNO (x)]);
1335c87b03e5Sespie       else
1336c87b03e5Sespie 	goto def;
1337c87b03e5Sespie       break;
1338c87b03e5Sespie     case 'T':
1339c87b03e5Sespie       if (GET_CODE (x) == REG)
1340c87b03e5Sespie 	fprintf (file, "%s", names_big[REGNO (x)]);
1341c87b03e5Sespie       else
1342c87b03e5Sespie 	goto def;
1343c87b03e5Sespie       break;
1344c87b03e5Sespie     case 'V':
1345c87b03e5Sespie       bitint = exact_log2 (INTVAL (x) & 0xff);
1346c87b03e5Sespie       if (bitint == -1)
1347c87b03e5Sespie 	abort ();
1348c87b03e5Sespie       fprintf (file, "#%d", bitint);
1349c87b03e5Sespie       break;
1350c87b03e5Sespie     case 'W':
1351c87b03e5Sespie       bitint = exact_log2 ((~INTVAL (x)) & 0xff);
1352c87b03e5Sespie       if (bitint == -1)
1353c87b03e5Sespie 	abort ();
1354c87b03e5Sespie       fprintf (file, "#%d", bitint);
1355c87b03e5Sespie       break;
1356c87b03e5Sespie     case 'R':
1357c87b03e5Sespie     case 'X':
1358c87b03e5Sespie       if (GET_CODE (x) == REG)
1359c87b03e5Sespie 	fprintf (file, "%s", byte_reg (x, 0));
1360c87b03e5Sespie       else
1361c87b03e5Sespie 	goto def;
1362c87b03e5Sespie       break;
1363c87b03e5Sespie     case 'Y':
1364c87b03e5Sespie       if (bitint == -1)
1365c87b03e5Sespie 	abort ();
1366c87b03e5Sespie       if (GET_CODE (x) == REG)
1367c87b03e5Sespie 	fprintf (file, "%s%c", names_big[REGNO (x)], bitint > 7 ? 'h' : 'l');
1368c87b03e5Sespie       else
1369c87b03e5Sespie 	print_operand (file, x, 'R');
1370c87b03e5Sespie       bitint = -1;
1371c87b03e5Sespie       break;
1372c87b03e5Sespie     case 'Z':
1373c87b03e5Sespie       bitint = INTVAL (x);
1374c87b03e5Sespie       fprintf (file, "#%d", bitint & 7);
1375c87b03e5Sespie       break;
1376c87b03e5Sespie     case 'b':
1377c87b03e5Sespie       switch (GET_CODE (x))
1378c87b03e5Sespie 	{
1379c87b03e5Sespie 	case IOR:
1380c87b03e5Sespie 	  fprintf (file, "bor");
1381c87b03e5Sespie 	  break;
1382c87b03e5Sespie 	case XOR:
1383c87b03e5Sespie 	  fprintf (file, "bxor");
1384c87b03e5Sespie 	  break;
1385c87b03e5Sespie 	case AND:
1386c87b03e5Sespie 	  fprintf (file, "band");
1387c87b03e5Sespie 	  break;
1388c87b03e5Sespie 	default:
1389c87b03e5Sespie 	  break;
1390c87b03e5Sespie 	}
1391c87b03e5Sespie       break;
1392c87b03e5Sespie     case 'e':
1393c87b03e5Sespie       switch (GET_CODE (x))
1394c87b03e5Sespie 	{
1395c87b03e5Sespie 	case REG:
1396c87b03e5Sespie 	  if (TARGET_H8300)
1397c87b03e5Sespie 	    fprintf (file, "%s", names_big[REGNO (x)]);
1398c87b03e5Sespie 	  else
1399c87b03e5Sespie 	    fprintf (file, "%s", names_upper_extended[REGNO (x)]);
1400c87b03e5Sespie 	  break;
1401c87b03e5Sespie 	case MEM:
1402c87b03e5Sespie 	  print_operand (file, x, 0);
1403c87b03e5Sespie 	  break;
1404c87b03e5Sespie 	case CONST_INT:
1405c87b03e5Sespie 	  fprintf (file, "#%d", ((INTVAL (x) >> 16) & 0xffff));
1406c87b03e5Sespie 	  break;
1407c87b03e5Sespie 	case CONST_DOUBLE:
1408c87b03e5Sespie 	  {
1409c87b03e5Sespie 	    long val;
1410c87b03e5Sespie 	    REAL_VALUE_TYPE rv;
1411c87b03e5Sespie 	    REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1412c87b03e5Sespie 	    REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1413c87b03e5Sespie 	    fprintf (file, "#%ld", ((val >> 16) & 0xffff));
1414c87b03e5Sespie 	    break;
1415c87b03e5Sespie 	  }
1416c87b03e5Sespie 	default:
1417c87b03e5Sespie 	  abort ();
1418c87b03e5Sespie 	  break;
1419c87b03e5Sespie 	}
1420c87b03e5Sespie       break;
1421c87b03e5Sespie     case 'f':
1422c87b03e5Sespie       switch (GET_CODE (x))
1423c87b03e5Sespie 	{
1424c87b03e5Sespie 	case REG:
1425c87b03e5Sespie 	  if (TARGET_H8300)
1426c87b03e5Sespie 	    fprintf (file, "%s", names_big[REGNO (x) + 1]);
1427c87b03e5Sespie 	  else
1428c87b03e5Sespie 	    fprintf (file, "%s", names_big[REGNO (x)]);
1429c87b03e5Sespie 	  break;
1430c87b03e5Sespie 	case MEM:
1431c87b03e5Sespie 	  x = adjust_address (x, HImode, 2);
1432c87b03e5Sespie 	  print_operand (file, x, 0);
1433c87b03e5Sespie 	  break;
1434c87b03e5Sespie 	case CONST_INT:
1435c87b03e5Sespie 	  fprintf (file, "#%d", INTVAL (x) & 0xffff);
1436c87b03e5Sespie 	  break;
1437c87b03e5Sespie 	case CONST_DOUBLE:
1438c87b03e5Sespie 	  {
1439c87b03e5Sespie 	    long val;
1440c87b03e5Sespie 	    REAL_VALUE_TYPE rv;
1441c87b03e5Sespie 	    REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1442c87b03e5Sespie 	    REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1443c87b03e5Sespie 	    fprintf (file, "#%ld", (val & 0xffff));
1444c87b03e5Sespie 	    break;
1445c87b03e5Sespie 	  }
1446c87b03e5Sespie 	default:
1447c87b03e5Sespie 	  abort ();
1448c87b03e5Sespie 	}
1449c87b03e5Sespie       break;
1450c87b03e5Sespie     case 'j':
1451c87b03e5Sespie       fputs (cond_string (GET_CODE (x)), file);
1452c87b03e5Sespie       break;
1453c87b03e5Sespie     case 'k':
1454c87b03e5Sespie       fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1455c87b03e5Sespie       break;
1456c87b03e5Sespie     case 's':
1457c87b03e5Sespie       if (GET_CODE (x) == CONST_INT)
1458c87b03e5Sespie 	fprintf (file, "#%d", (INTVAL (x)) & 0xff);
1459c87b03e5Sespie       else
1460c87b03e5Sespie 	fprintf (file, "%s", byte_reg (x, 0));
1461c87b03e5Sespie       break;
1462c87b03e5Sespie     case 't':
1463c87b03e5Sespie       if (GET_CODE (x) == CONST_INT)
1464c87b03e5Sespie 	fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
1465c87b03e5Sespie       else
1466c87b03e5Sespie 	fprintf (file, "%s", byte_reg (x, 1));
1467c87b03e5Sespie       break;
1468c87b03e5Sespie     case 'u':
1469c87b03e5Sespie       if (GET_CODE (x) != CONST_INT)
1470c87b03e5Sespie 	abort ();
1471c87b03e5Sespie       fprintf (file, "%d", INTVAL (x));
1472c87b03e5Sespie       break;
1473c87b03e5Sespie     case 'w':
1474c87b03e5Sespie       if (GET_CODE (x) == CONST_INT)
1475c87b03e5Sespie 	fprintf (file, "#%d", INTVAL (x) & 0xff);
1476c87b03e5Sespie       else
1477c87b03e5Sespie 	fprintf (file, "%s",
1478c87b03e5Sespie 		 byte_reg (x, TARGET_H8300 ? 2 : 0));
1479c87b03e5Sespie       break;
1480c87b03e5Sespie     case 'x':
1481c87b03e5Sespie       if (GET_CODE (x) == CONST_INT)
1482c87b03e5Sespie 	fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
1483c87b03e5Sespie       else
1484c87b03e5Sespie 	fprintf (file, "%s",
1485c87b03e5Sespie 		 byte_reg (x, TARGET_H8300 ? 3 : 1));
1486c87b03e5Sespie       break;
1487c87b03e5Sespie     case 'y':
1488c87b03e5Sespie       if (GET_CODE (x) == CONST_INT)
1489c87b03e5Sespie 	fprintf (file, "#%d", (INTVAL (x) >> 16) & 0xff);
1490c87b03e5Sespie       else
1491c87b03e5Sespie 	fprintf (file, "%s", byte_reg (x, 0));
1492c87b03e5Sespie       break;
1493c87b03e5Sespie     case 'z':
1494c87b03e5Sespie       if (GET_CODE (x) == CONST_INT)
1495c87b03e5Sespie 	fprintf (file, "#%d", (INTVAL (x) >> 24) & 0xff);
1496c87b03e5Sespie       else
1497c87b03e5Sespie 	fprintf (file, "%s", byte_reg (x, 1));
1498c87b03e5Sespie       break;
1499c87b03e5Sespie 
1500c87b03e5Sespie     default:
1501c87b03e5Sespie     def:
1502c87b03e5Sespie       switch (GET_CODE (x))
1503c87b03e5Sespie 	{
1504c87b03e5Sespie 	case REG:
1505c87b03e5Sespie 	  switch (GET_MODE (x))
1506c87b03e5Sespie 	    {
1507c87b03e5Sespie 	    case QImode:
1508c87b03e5Sespie #if 0 /* Is it asm ("mov.b %0,r2l", ...) */
1509c87b03e5Sespie 	      fprintf (file, "%s", byte_reg (x, 0));
1510c87b03e5Sespie #else /* ... or is it asm ("mov.b %0l,r2l", ...) */
1511c87b03e5Sespie 	      fprintf (file, "%s", names_big[REGNO (x)]);
1512c87b03e5Sespie #endif
1513c87b03e5Sespie 	      break;
1514c87b03e5Sespie 	    case HImode:
1515c87b03e5Sespie 	      fprintf (file, "%s", names_big[REGNO (x)]);
1516c87b03e5Sespie 	      break;
1517c87b03e5Sespie 	    case SImode:
1518c87b03e5Sespie 	    case SFmode:
1519c87b03e5Sespie 	      fprintf (file, "%s", names_extended[REGNO (x)]);
1520c87b03e5Sespie 	      break;
1521c87b03e5Sespie 	    default:
1522c87b03e5Sespie 	      abort ();
1523c87b03e5Sespie 	    }
1524c87b03e5Sespie 	  break;
1525c87b03e5Sespie 
1526c87b03e5Sespie 	case MEM:
1527c87b03e5Sespie 	  {
1528c87b03e5Sespie 	    rtx addr = XEXP (x, 0);
1529c87b03e5Sespie 
1530c87b03e5Sespie 	    fprintf (file, "@");
1531c87b03e5Sespie 	    output_address (addr);
1532c87b03e5Sespie 
1533c87b03e5Sespie 	    /* We fall back from smaller addressing to larger
1534c87b03e5Sespie 	       addressing in various ways depending on CODE.  */
1535c87b03e5Sespie 	    switch (code)
1536c87b03e5Sespie 	      {
1537c87b03e5Sespie 	      case 'R':
1538c87b03e5Sespie 		/* Used for mov.b and bit operations.  */
1539c87b03e5Sespie 		if (h8300_eightbit_constant_address_p (addr))
1540c87b03e5Sespie 		  {
1541c87b03e5Sespie 		    fprintf (file, ":8");
1542c87b03e5Sespie 		    break;
1543c87b03e5Sespie 		  }
1544c87b03e5Sespie 
1545c87b03e5Sespie 		/* Fall through.  We should not get here if we are
1546c87b03e5Sespie 		   processing bit operations on H8/300 or H8/300H
1547c87b03e5Sespie 		   because 'U' constraint does not allow bit
1548c87b03e5Sespie 		   operations on the tiny area on these machines.  */
1549c87b03e5Sespie 
1550c87b03e5Sespie 	      case 'T':
1551c87b03e5Sespie 	      case 'S':
1552c87b03e5Sespie 		/* Used for mov.w and mov.l.  */
1553c87b03e5Sespie 		if (h8300_tiny_constant_address_p (addr))
1554c87b03e5Sespie 		  fprintf (file, ":16");
1555c87b03e5Sespie 		break;
1556c87b03e5Sespie 	      default:
1557c87b03e5Sespie 		break;
1558c87b03e5Sespie 	      }
1559c87b03e5Sespie 	  }
1560c87b03e5Sespie 	  break;
1561c87b03e5Sespie 
1562c87b03e5Sespie 	case CONST_INT:
1563c87b03e5Sespie 	case SYMBOL_REF:
1564c87b03e5Sespie 	case CONST:
1565c87b03e5Sespie 	case LABEL_REF:
1566c87b03e5Sespie 	  fprintf (file, "#");
1567c87b03e5Sespie 	  print_operand_address (file, x);
1568c87b03e5Sespie 	  break;
1569c87b03e5Sespie 	case CONST_DOUBLE:
1570c87b03e5Sespie 	  {
1571c87b03e5Sespie 	    long val;
1572c87b03e5Sespie 	    REAL_VALUE_TYPE rv;
1573c87b03e5Sespie 	    REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1574c87b03e5Sespie 	    REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1575c87b03e5Sespie 	    fprintf (file, "#%ld", val);
1576c87b03e5Sespie 	    break;
1577c87b03e5Sespie 	  }
1578c87b03e5Sespie 	default:
1579c87b03e5Sespie 	  break;
1580c87b03e5Sespie 	}
1581c87b03e5Sespie     }
1582c87b03e5Sespie }
1583c87b03e5Sespie 
1584c87b03e5Sespie /* Output assembly language output for the address ADDR to FILE.  */
1585c87b03e5Sespie 
1586c87b03e5Sespie void
print_operand_address(file,addr)1587c87b03e5Sespie print_operand_address (file, addr)
1588c87b03e5Sespie      FILE *file;
1589c87b03e5Sespie      rtx addr;
1590c87b03e5Sespie {
1591c87b03e5Sespie   switch (GET_CODE (addr))
1592c87b03e5Sespie     {
1593c87b03e5Sespie     case REG:
1594c87b03e5Sespie       fprintf (file, "%s", h8_reg_names[REGNO (addr)]);
1595c87b03e5Sespie       break;
1596c87b03e5Sespie 
1597c87b03e5Sespie     case PRE_DEC:
1598c87b03e5Sespie       fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]);
1599c87b03e5Sespie       break;
1600c87b03e5Sespie 
1601c87b03e5Sespie     case POST_INC:
1602c87b03e5Sespie       fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]);
1603c87b03e5Sespie       break;
1604c87b03e5Sespie 
1605c87b03e5Sespie     case PLUS:
1606c87b03e5Sespie       fprintf (file, "(");
1607c87b03e5Sespie       if (GET_CODE (XEXP (addr, 0)) == REG)
1608c87b03e5Sespie 	{
1609c87b03e5Sespie 	  /* reg,foo */
1610c87b03e5Sespie 	  print_operand_address (file, XEXP (addr, 1));
1611c87b03e5Sespie 	  fprintf (file, ",");
1612c87b03e5Sespie 	  print_operand_address (file, XEXP (addr, 0));
1613c87b03e5Sespie 	}
1614c87b03e5Sespie       else
1615c87b03e5Sespie 	{
1616c87b03e5Sespie 	  /* foo+k */
1617c87b03e5Sespie 	  print_operand_address (file, XEXP (addr, 0));
1618c87b03e5Sespie 	  fprintf (file, "+");
1619c87b03e5Sespie 	  print_operand_address (file, XEXP (addr, 1));
1620c87b03e5Sespie 	}
1621c87b03e5Sespie       fprintf (file, ")");
1622c87b03e5Sespie       break;
1623c87b03e5Sespie 
1624c87b03e5Sespie     case CONST_INT:
1625c87b03e5Sespie       {
1626c87b03e5Sespie 	/* Since the H8/300 only has 16 bit pointers, negative values are also
1627c87b03e5Sespie 	   those >= 32768.  This happens for example with pointer minus a
1628c87b03e5Sespie 	   constant.  We don't want to turn (char *p - 2) into
1629c87b03e5Sespie 	   (char *p + 65534) because loop unrolling can build upon this
1630c87b03e5Sespie 	   (IE: char *p + 131068).  */
1631c87b03e5Sespie 	int n = INTVAL (addr);
1632c87b03e5Sespie 	if (TARGET_H8300)
1633c87b03e5Sespie 	  n = (int) (short) n;
1634c87b03e5Sespie 	if (n < 0)
1635c87b03e5Sespie 	  /* ??? Why the special case for -ve values?  */
1636c87b03e5Sespie 	  fprintf (file, "-%d", -n);
1637c87b03e5Sespie 	else
1638c87b03e5Sespie 	  fprintf (file, "%d", n);
1639c87b03e5Sespie 	break;
1640c87b03e5Sespie       }
1641c87b03e5Sespie 
1642c87b03e5Sespie     default:
1643c87b03e5Sespie       output_addr_const (file, addr);
1644c87b03e5Sespie       break;
1645c87b03e5Sespie     }
1646c87b03e5Sespie }
1647c87b03e5Sespie 
1648c87b03e5Sespie /* Output all insn addresses and their sizes into the assembly language
1649c87b03e5Sespie    output file.  This is helpful for debugging whether the length attributes
1650c87b03e5Sespie    in the md file are correct.  This is not meant to be a user selectable
1651c87b03e5Sespie    option.  */
1652c87b03e5Sespie 
1653c87b03e5Sespie void
final_prescan_insn(insn,operand,num_operands)1654c87b03e5Sespie final_prescan_insn (insn, operand, num_operands)
1655c87b03e5Sespie      rtx insn, *operand ATTRIBUTE_UNUSED;
1656c87b03e5Sespie      int num_operands ATTRIBUTE_UNUSED;
1657c87b03e5Sespie {
1658c87b03e5Sespie   /* This holds the last insn address.  */
1659c87b03e5Sespie   static int last_insn_address = 0;
1660c87b03e5Sespie 
1661c87b03e5Sespie   int uid = INSN_UID (insn);
1662c87b03e5Sespie 
1663c87b03e5Sespie   if (TARGET_RTL_DUMP)
1664c87b03e5Sespie     {
1665c87b03e5Sespie       fprintf (asm_out_file, "\n****************");
1666c87b03e5Sespie       print_rtl (asm_out_file, PATTERN (insn));
1667c87b03e5Sespie       fprintf (asm_out_file, "\n");
1668c87b03e5Sespie     }
1669c87b03e5Sespie 
1670c87b03e5Sespie   if (TARGET_ADDRESSES)
1671c87b03e5Sespie     {
1672c87b03e5Sespie       fprintf (asm_out_file, "; 0x%x %d\n", INSN_ADDRESSES (uid),
1673c87b03e5Sespie 	       INSN_ADDRESSES (uid) - last_insn_address);
1674c87b03e5Sespie       last_insn_address = INSN_ADDRESSES (uid);
1675c87b03e5Sespie     }
1676c87b03e5Sespie }
1677c87b03e5Sespie 
1678c87b03e5Sespie /* Prepare for an SI sized move.  */
1679c87b03e5Sespie 
1680c87b03e5Sespie int
do_movsi(operands)1681c87b03e5Sespie do_movsi (operands)
1682c87b03e5Sespie      rtx operands[];
1683c87b03e5Sespie {
1684c87b03e5Sespie   rtx src = operands[1];
1685c87b03e5Sespie   rtx dst = operands[0];
1686c87b03e5Sespie   if (!reload_in_progress && !reload_completed)
1687c87b03e5Sespie     {
1688c87b03e5Sespie       if (!register_operand (dst, GET_MODE (dst)))
1689c87b03e5Sespie 	{
1690c87b03e5Sespie 	  rtx tmp = gen_reg_rtx (GET_MODE (dst));
1691c87b03e5Sespie 	  emit_move_insn (tmp, src);
1692c87b03e5Sespie 	  operands[1] = tmp;
1693c87b03e5Sespie 	}
1694c87b03e5Sespie     }
1695c87b03e5Sespie   return 0;
1696c87b03e5Sespie }
1697c87b03e5Sespie 
1698c87b03e5Sespie /* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).
1699c87b03e5Sespie    Define the offset between two registers, one to be eliminated, and
1700c87b03e5Sespie    the other its replacement, at the start of a routine.  */
1701c87b03e5Sespie 
1702c87b03e5Sespie int
h8300_initial_elimination_offset(from,to)1703c87b03e5Sespie h8300_initial_elimination_offset (from, to)
1704c87b03e5Sespie      int from, to;
1705c87b03e5Sespie {
1706c87b03e5Sespie   int offset = 0;
1707c87b03e5Sespie   /* The number of bytes that the return address takes on the stack.  */
1708c87b03e5Sespie   int pc_size = POINTER_SIZE / BITS_PER_UNIT;
1709c87b03e5Sespie 
1710c87b03e5Sespie   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
1711c87b03e5Sespie     offset = pc_size + frame_pointer_needed * UNITS_PER_WORD;
1712c87b03e5Sespie   else if (from == RETURN_ADDRESS_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
1713c87b03e5Sespie     offset = frame_pointer_needed * UNITS_PER_WORD;
1714c87b03e5Sespie   else
1715c87b03e5Sespie     {
1716c87b03e5Sespie       int regno;
1717c87b03e5Sespie 
1718c87b03e5Sespie       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1719c87b03e5Sespie 	if (WORD_REG_USED (regno))
1720c87b03e5Sespie 	  offset += UNITS_PER_WORD;
1721c87b03e5Sespie 
1722c87b03e5Sespie       /* See the comments for get_frame_size.  We need to round it up to
1723c87b03e5Sespie 	 STACK_BOUNDARY.  */
1724c87b03e5Sespie 
1725c87b03e5Sespie       offset += round_frame_size (get_frame_size ());
1726c87b03e5Sespie 
1727c87b03e5Sespie       if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1728c87b03e5Sespie 	/* Skip saved PC.  */
1729c87b03e5Sespie 	offset += pc_size;
1730c87b03e5Sespie     }
1731c87b03e5Sespie 
1732c87b03e5Sespie   return offset;
1733c87b03e5Sespie }
1734c87b03e5Sespie 
1735c87b03e5Sespie rtx
h8300_return_addr_rtx(count,frame)1736c87b03e5Sespie h8300_return_addr_rtx (count, frame)
1737c87b03e5Sespie      int count;
1738c87b03e5Sespie      rtx frame;
1739c87b03e5Sespie {
1740c87b03e5Sespie   rtx ret;
1741c87b03e5Sespie 
1742c87b03e5Sespie   if (count == 0)
1743c87b03e5Sespie     ret = gen_rtx_MEM (Pmode,
1744c87b03e5Sespie 		       gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM));
1745c87b03e5Sespie   else if (flag_omit_frame_pointer)
1746c87b03e5Sespie     return (rtx) 0;
1747c87b03e5Sespie   else
1748c87b03e5Sespie     ret = gen_rtx_MEM (Pmode,
1749c87b03e5Sespie 		       memory_address (Pmode,
1750c87b03e5Sespie 				       plus_constant (frame, UNITS_PER_WORD)));
1751c87b03e5Sespie   set_mem_alias_set (ret, get_frame_alias_set ());
1752c87b03e5Sespie   return ret;
1753c87b03e5Sespie }
1754c87b03e5Sespie 
1755c87b03e5Sespie /* Update the condition code from the insn.  */
1756c87b03e5Sespie 
1757c87b03e5Sespie void
notice_update_cc(body,insn)1758c87b03e5Sespie notice_update_cc (body, insn)
1759c87b03e5Sespie      rtx body;
1760c87b03e5Sespie      rtx insn;
1761c87b03e5Sespie {
1762c87b03e5Sespie   rtx set;
1763c87b03e5Sespie 
1764c87b03e5Sespie   switch (get_attr_cc (insn))
1765c87b03e5Sespie     {
1766c87b03e5Sespie     case CC_NONE:
1767c87b03e5Sespie       /* Insn does not affect CC at all.  */
1768c87b03e5Sespie       break;
1769c87b03e5Sespie 
1770c87b03e5Sespie     case CC_NONE_0HIT:
1771c87b03e5Sespie       /* Insn does not change CC, but the 0'th operand has been changed.  */
1772c87b03e5Sespie       if (cc_status.value1 != 0
1773c87b03e5Sespie 	  && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
1774c87b03e5Sespie 	cc_status.value1 = 0;
1775c87b03e5Sespie       if (cc_status.value2 != 0
1776c87b03e5Sespie 	  && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))
1777c87b03e5Sespie 	cc_status.value2 = 0;
1778c87b03e5Sespie       break;
1779c87b03e5Sespie 
1780c87b03e5Sespie     case CC_SET_ZN:
1781c87b03e5Sespie       /* Insn sets the Z,N flags of CC to recog_data.operand[0].
1782c87b03e5Sespie 	 The V flag is unusable.  The C flag may or may not be known but
1783c87b03e5Sespie 	 that's ok because alter_cond will change tests to use EQ/NE.  */
1784c87b03e5Sespie       CC_STATUS_INIT;
1785c87b03e5Sespie       cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
1786c87b03e5Sespie       set = single_set (insn);
1787c87b03e5Sespie       cc_status.value1 = SET_SRC (set);
1788c87b03e5Sespie       if (SET_DEST (set) != cc0_rtx)
1789c87b03e5Sespie 	cc_status.value2 = SET_DEST (set);
1790c87b03e5Sespie       break;
1791c87b03e5Sespie 
1792c87b03e5Sespie     case CC_SET_ZNV:
1793c87b03e5Sespie       /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].
1794c87b03e5Sespie 	 The C flag may or may not be known but that's ok because
1795c87b03e5Sespie 	 alter_cond will change tests to use EQ/NE.  */
1796c87b03e5Sespie       CC_STATUS_INIT;
1797c87b03e5Sespie       cc_status.flags |= CC_NO_CARRY;
1798c87b03e5Sespie       set = single_set (insn);
1799c87b03e5Sespie       cc_status.value1 = SET_SRC (set);
1800c87b03e5Sespie       if (SET_DEST (set) != cc0_rtx)
1801c87b03e5Sespie 	cc_status.value2 = SET_DEST (set);
1802c87b03e5Sespie       break;
1803c87b03e5Sespie 
1804c87b03e5Sespie     case CC_COMPARE:
1805c87b03e5Sespie       /* The insn is a compare instruction.  */
1806c87b03e5Sespie       CC_STATUS_INIT;
1807c87b03e5Sespie       cc_status.value1 = SET_SRC (body);
1808c87b03e5Sespie       break;
1809c87b03e5Sespie 
1810c87b03e5Sespie     case CC_CLOBBER:
1811c87b03e5Sespie       /* Insn doesn't leave CC in a usable state.  */
1812c87b03e5Sespie       CC_STATUS_INIT;
1813c87b03e5Sespie       break;
1814c87b03e5Sespie     }
1815c87b03e5Sespie }
1816c87b03e5Sespie 
1817c87b03e5Sespie /* Return nonzero if X is a stack pointer.  */
1818c87b03e5Sespie 
1819c87b03e5Sespie int
stack_pointer_operand(x,mode)1820c87b03e5Sespie stack_pointer_operand (x, mode)
1821c87b03e5Sespie      rtx x;
1822c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
1823c87b03e5Sespie {
1824c87b03e5Sespie   return x == stack_pointer_rtx;
1825c87b03e5Sespie }
1826c87b03e5Sespie 
1827c87b03e5Sespie /* Return nonzero if X is a constant whose absolute value is greater
1828c87b03e5Sespie    than 2.  */
1829c87b03e5Sespie 
1830c87b03e5Sespie int
const_int_gt_2_operand(x,mode)1831c87b03e5Sespie const_int_gt_2_operand (x, mode)
1832c87b03e5Sespie      rtx x;
1833c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
1834c87b03e5Sespie {
1835c87b03e5Sespie   return (GET_CODE (x) == CONST_INT
1836c87b03e5Sespie 	  && abs (INTVAL (x)) > 2);
1837c87b03e5Sespie }
1838c87b03e5Sespie 
1839c87b03e5Sespie /* Return nonzero if X is a constant whose absolute value is no
1840c87b03e5Sespie    smaller than 8.  */
1841c87b03e5Sespie 
1842c87b03e5Sespie int
const_int_ge_8_operand(x,mode)1843c87b03e5Sespie const_int_ge_8_operand (x, mode)
1844c87b03e5Sespie      rtx x;
1845c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
1846c87b03e5Sespie {
1847c87b03e5Sespie   return (GET_CODE (x) == CONST_INT
1848c87b03e5Sespie 	  && abs (INTVAL (x)) >= 8);
1849c87b03e5Sespie }
1850c87b03e5Sespie 
1851c87b03e5Sespie /* Recognize valid operators for bit instructions.  */
1852c87b03e5Sespie 
1853c87b03e5Sespie int
bit_operator(x,mode)1854c87b03e5Sespie bit_operator (x, mode)
1855c87b03e5Sespie      rtx x;
1856c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
1857c87b03e5Sespie {
1858c87b03e5Sespie   enum rtx_code code = GET_CODE (x);
1859c87b03e5Sespie 
1860c87b03e5Sespie   return (code == XOR
1861c87b03e5Sespie 	  || code == AND
1862c87b03e5Sespie 	  || code == IOR);
1863c87b03e5Sespie }
1864c87b03e5Sespie 
1865c87b03e5Sespie const char *
output_logical_op(mode,operands)1866c87b03e5Sespie output_logical_op (mode, operands)
1867c87b03e5Sespie      enum machine_mode mode;
1868c87b03e5Sespie      rtx *operands;
1869c87b03e5Sespie {
1870c87b03e5Sespie   /* Figure out the logical op that we need to perform.  */
1871c87b03e5Sespie   enum rtx_code code = GET_CODE (operands[3]);
1872c87b03e5Sespie   /* Pretend that every byte is affected if both operands are registers.  */
1873c87b03e5Sespie   unsigned HOST_WIDE_INT intval =
1874c87b03e5Sespie     (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
1875c87b03e5Sespie 			      ? INTVAL (operands[2]) : 0x55555555);
1876c87b03e5Sespie   /* The determinant of the algorithm.  If we perform an AND, 0
1877c87b03e5Sespie      affects a bit.  Otherwise, 1 affects a bit.  */
1878c87b03e5Sespie   unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
1879c87b03e5Sespie   /* The name of an insn.  */
1880c87b03e5Sespie   const char *opname;
1881c87b03e5Sespie   char insn_buf[100];
1882c87b03e5Sespie 
1883c87b03e5Sespie   switch (code)
1884c87b03e5Sespie     {
1885c87b03e5Sespie     case AND:
1886c87b03e5Sespie       opname = "and";
1887c87b03e5Sespie       break;
1888c87b03e5Sespie     case IOR:
1889c87b03e5Sespie       opname = "or";
1890c87b03e5Sespie       break;
1891c87b03e5Sespie     case XOR:
1892c87b03e5Sespie       opname = "xor";
1893c87b03e5Sespie       break;
1894c87b03e5Sespie     default:
1895c87b03e5Sespie       abort ();
1896c87b03e5Sespie     }
1897c87b03e5Sespie 
1898c87b03e5Sespie   switch (mode)
1899c87b03e5Sespie     {
1900c87b03e5Sespie     case HImode:
1901c87b03e5Sespie       /* First, see if we can finish with one insn.  */
1902c87b03e5Sespie       if ((TARGET_H8300H || TARGET_H8300S)
1903c87b03e5Sespie 	  && ((det & 0x00ff) != 0)
1904c87b03e5Sespie 	  && ((det & 0xff00) != 0))
1905c87b03e5Sespie 	{
1906c87b03e5Sespie 	  sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname);
1907c87b03e5Sespie 	  output_asm_insn (insn_buf, operands);
1908c87b03e5Sespie 	}
1909c87b03e5Sespie       else
1910c87b03e5Sespie 	{
1911c87b03e5Sespie 	  /* Take care of the lower byte.  */
1912c87b03e5Sespie 	  if ((det & 0x00ff) != 0)
1913c87b03e5Sespie 	    {
1914c87b03e5Sespie 	      sprintf (insn_buf, "%s\t%%s2,%%s0", opname);
1915c87b03e5Sespie 	      output_asm_insn (insn_buf, operands);
1916c87b03e5Sespie 	    }
1917c87b03e5Sespie 	  /* Take care of the upper byte.  */
1918c87b03e5Sespie 	  if ((det & 0xff00) != 0)
1919c87b03e5Sespie 	    {
1920c87b03e5Sespie 	      sprintf (insn_buf, "%s\t%%t2,%%t0", opname);
1921c87b03e5Sespie 	      output_asm_insn (insn_buf, operands);
1922c87b03e5Sespie 	    }
1923c87b03e5Sespie 	}
1924c87b03e5Sespie       break;
1925c87b03e5Sespie     case SImode:
1926c87b03e5Sespie       /* First, see if we can finish with one insn.
1927c87b03e5Sespie 
1928c87b03e5Sespie 	 If code is either AND or XOR, we exclude two special cases,
1929c87b03e5Sespie 	 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w
1930c87b03e5Sespie 	 can do a better job.  */
1931c87b03e5Sespie       if ((TARGET_H8300H || TARGET_H8300S)
1932c87b03e5Sespie 	  && ((det & 0x0000ffff) != 0)
1933c87b03e5Sespie 	  && ((det & 0xffff0000) != 0)
1934c87b03e5Sespie 	  && (code == IOR || det != 0xffffff00)
1935c87b03e5Sespie 	  && (code == IOR || det != 0xffff00ff))
1936c87b03e5Sespie 	{
1937c87b03e5Sespie 	  sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname);
1938c87b03e5Sespie 	  output_asm_insn (insn_buf, operands);
1939c87b03e5Sespie 	}
1940c87b03e5Sespie       else
1941c87b03e5Sespie 	{
1942c87b03e5Sespie 	  /* Take care of the lower and upper words individually.  For
1943c87b03e5Sespie 	     each word, we try different methods in the order of
1944c87b03e5Sespie 
1945c87b03e5Sespie 	     1) the special insn (in case of AND or XOR),
1946c87b03e5Sespie 	     2) the word-wise insn, and
1947c87b03e5Sespie 	     3) The byte-wise insn.  */
1948c87b03e5Sespie 	  if ((det & 0x0000ffff) == 0x0000ffff
1949c87b03e5Sespie 	      && (TARGET_H8300 ? (code == AND) : (code != IOR)))
1950c87b03e5Sespie 	    output_asm_insn ((code == AND)
1951c87b03e5Sespie 			     ? "sub.w\t%f0,%f0" : "not.w\t%f0",
1952c87b03e5Sespie 			     operands);
1953c87b03e5Sespie 	  else if ((TARGET_H8300H || TARGET_H8300S)
1954c87b03e5Sespie 		   && ((det & 0x000000ff) != 0)
1955c87b03e5Sespie 		   && ((det & 0x0000ff00) != 0))
1956c87b03e5Sespie 	    {
1957c87b03e5Sespie 	      sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname);
1958c87b03e5Sespie 	      output_asm_insn (insn_buf, operands);
1959c87b03e5Sespie 	    }
1960c87b03e5Sespie 	  else
1961c87b03e5Sespie 	    {
1962c87b03e5Sespie 	      if ((det & 0x000000ff) != 0)
1963c87b03e5Sespie 		{
1964c87b03e5Sespie 		  sprintf (insn_buf, "%s\t%%w2,%%w0", opname);
1965c87b03e5Sespie 		  output_asm_insn (insn_buf, operands);
1966c87b03e5Sespie 		}
1967c87b03e5Sespie 	      if ((det & 0x0000ff00) != 0)
1968c87b03e5Sespie 		{
1969c87b03e5Sespie 		  sprintf (insn_buf, "%s\t%%x2,%%x0", opname);
1970c87b03e5Sespie 		  output_asm_insn (insn_buf, operands);
1971c87b03e5Sespie 		}
1972c87b03e5Sespie 	    }
1973c87b03e5Sespie 
1974c87b03e5Sespie 	  if ((det & 0xffff0000) == 0xffff0000
1975c87b03e5Sespie 	      && (TARGET_H8300 ? (code == AND) : (code != IOR)))
1976c87b03e5Sespie 	    output_asm_insn ((code == AND)
1977c87b03e5Sespie 			     ? "sub.w\t%e0,%e0" : "not.w\t%e0",
1978c87b03e5Sespie 			     operands);
1979c87b03e5Sespie 	  else if (TARGET_H8300H || TARGET_H8300S)
1980c87b03e5Sespie 	    {
1981c87b03e5Sespie 	      if ((det & 0xffff0000) != 0)
1982c87b03e5Sespie 		{
1983c87b03e5Sespie 		  sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname);
1984c87b03e5Sespie 		  output_asm_insn (insn_buf, operands);
1985c87b03e5Sespie 		}
1986c87b03e5Sespie 	    }
1987c87b03e5Sespie 	  else
1988c87b03e5Sespie 	    {
1989c87b03e5Sespie 	      if ((det & 0x00ff0000) != 0)
1990c87b03e5Sespie 		{
1991c87b03e5Sespie 		  sprintf (insn_buf, "%s\t%%y2,%%y0", opname);
1992c87b03e5Sespie 		  output_asm_insn (insn_buf, operands);
1993c87b03e5Sespie 		}
1994c87b03e5Sespie 	      if ((det & 0xff000000) != 0)
1995c87b03e5Sespie 		{
1996c87b03e5Sespie 		  sprintf (insn_buf, "%s\t%%z2,%%z0", opname);
1997c87b03e5Sespie 		  output_asm_insn (insn_buf, operands);
1998c87b03e5Sespie 		}
1999c87b03e5Sespie 	    }
2000c87b03e5Sespie 	}
2001c87b03e5Sespie       break;
2002c87b03e5Sespie     default:
2003c87b03e5Sespie       abort ();
2004c87b03e5Sespie     }
2005c87b03e5Sespie   return "";
2006c87b03e5Sespie }
2007c87b03e5Sespie 
2008c87b03e5Sespie unsigned int
compute_logical_op_length(mode,operands)2009c87b03e5Sespie compute_logical_op_length (mode, operands)
2010c87b03e5Sespie      enum machine_mode mode;
2011c87b03e5Sespie      rtx *operands;
2012c87b03e5Sespie {
2013c87b03e5Sespie   /* Figure out the logical op that we need to perform.  */
2014c87b03e5Sespie   enum rtx_code code = GET_CODE (operands[3]);
2015c87b03e5Sespie   /* Pretend that every byte is affected if both operands are registers.  */
2016c87b03e5Sespie   unsigned HOST_WIDE_INT intval =
2017c87b03e5Sespie     (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
2018c87b03e5Sespie 			      ? INTVAL (operands[2]) : 0x55555555);
2019c87b03e5Sespie   /* The determinant of the algorithm.  If we perform an AND, 0
2020c87b03e5Sespie      affects a bit.  Otherwise, 1 affects a bit.  */
2021c87b03e5Sespie   unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
2022c87b03e5Sespie   /* Insn length.  */
2023c87b03e5Sespie   unsigned int length = 0;
2024c87b03e5Sespie 
2025c87b03e5Sespie   switch (mode)
2026c87b03e5Sespie     {
2027c87b03e5Sespie     case HImode:
2028c87b03e5Sespie       /* First, see if we can finish with one insn.  */
2029c87b03e5Sespie       if ((TARGET_H8300H || TARGET_H8300S)
2030c87b03e5Sespie 	  && ((det & 0x00ff) != 0)
2031c87b03e5Sespie 	  && ((det & 0xff00) != 0))
2032c87b03e5Sespie 	{
2033c87b03e5Sespie 	  if (REG_P (operands[2]))
2034c87b03e5Sespie 	    length += 2;
2035c87b03e5Sespie 	  else
2036c87b03e5Sespie 	    length += 4;
2037c87b03e5Sespie 	}
2038c87b03e5Sespie       else
2039c87b03e5Sespie 	{
2040c87b03e5Sespie 	  /* Take care of the lower byte.  */
2041c87b03e5Sespie 	  if ((det & 0x00ff) != 0)
2042c87b03e5Sespie 	    length += 2;
2043c87b03e5Sespie 
2044c87b03e5Sespie 	  /* Take care of the upper byte.  */
2045c87b03e5Sespie 	  if ((det & 0xff00) != 0)
2046c87b03e5Sespie 	    length += 2;
2047c87b03e5Sespie 	}
2048c87b03e5Sespie       break;
2049c87b03e5Sespie     case SImode:
2050c87b03e5Sespie       /* First, see if we can finish with one insn.
2051c87b03e5Sespie 
2052c87b03e5Sespie 	 If code is either AND or XOR, we exclude two special cases,
2053c87b03e5Sespie 	 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w
2054c87b03e5Sespie 	 can do a better job.  */
2055c87b03e5Sespie       if ((TARGET_H8300H || TARGET_H8300S)
2056c87b03e5Sespie 	  && ((det & 0x0000ffff) != 0)
2057c87b03e5Sespie 	  && ((det & 0xffff0000) != 0)
2058c87b03e5Sespie 	  && (code == IOR || det != 0xffffff00)
2059c87b03e5Sespie 	  && (code == IOR || det != 0xffff00ff))
2060c87b03e5Sespie 	{
2061c87b03e5Sespie 	  if (REG_P (operands[2]))
2062c87b03e5Sespie 	    length += 4;
2063c87b03e5Sespie 	  else
2064c87b03e5Sespie 	    length += 6;
2065c87b03e5Sespie 	}
2066c87b03e5Sespie       else
2067c87b03e5Sespie 	{
2068c87b03e5Sespie 	  /* Take care of the lower and upper words individually.  For
2069c87b03e5Sespie 	     each word, we try different methods in the order of
2070c87b03e5Sespie 
2071c87b03e5Sespie 	     1) the special insn (in case of AND or XOR),
2072c87b03e5Sespie 	     2) the word-wise insn, and
2073c87b03e5Sespie 	     3) The byte-wise insn.  */
2074c87b03e5Sespie 	  if ((det & 0x0000ffff) == 0x0000ffff
2075c87b03e5Sespie 	      && (TARGET_H8300 ? (code == AND) : (code != IOR)))
2076c87b03e5Sespie 	    {
2077c87b03e5Sespie 	      length += 2;
2078c87b03e5Sespie 	    }
2079c87b03e5Sespie 	  else if ((TARGET_H8300H || TARGET_H8300S)
2080c87b03e5Sespie 		   && ((det & 0x000000ff) != 0)
2081c87b03e5Sespie 		   && ((det & 0x0000ff00) != 0))
2082c87b03e5Sespie 	    {
2083c87b03e5Sespie 	      length += 4;
2084c87b03e5Sespie 	    }
2085c87b03e5Sespie 	  else
2086c87b03e5Sespie 	    {
2087c87b03e5Sespie 	      if ((det & 0x000000ff) != 0)
2088c87b03e5Sespie 		length += 2;
2089c87b03e5Sespie 
2090c87b03e5Sespie 	      if ((det & 0x0000ff00) != 0)
2091c87b03e5Sespie 		length += 2;
2092c87b03e5Sespie 	    }
2093c87b03e5Sespie 
2094c87b03e5Sespie 	  if ((det & 0xffff0000) == 0xffff0000
2095c87b03e5Sespie 	      && (TARGET_H8300 ? (code == AND) : (code != IOR)))
2096c87b03e5Sespie 	    {
2097c87b03e5Sespie 	      length += 2;
2098c87b03e5Sespie 	    }
2099c87b03e5Sespie 	  else if (TARGET_H8300H || TARGET_H8300S)
2100c87b03e5Sespie 	    {
2101c87b03e5Sespie 	      if ((det & 0xffff0000) != 0)
2102c87b03e5Sespie 		length += 4;
2103c87b03e5Sespie 	    }
2104c87b03e5Sespie 	  else
2105c87b03e5Sespie 	    {
2106c87b03e5Sespie 	      if ((det & 0x00ff0000) != 0)
2107c87b03e5Sespie 		length += 2;
2108c87b03e5Sespie 
2109c87b03e5Sespie 	      if ((det & 0xff000000) != 0)
2110c87b03e5Sespie 		length += 2;
2111c87b03e5Sespie 	    }
2112c87b03e5Sespie 	}
2113c87b03e5Sespie       break;
2114c87b03e5Sespie     default:
2115c87b03e5Sespie       abort ();
2116c87b03e5Sespie     }
2117c87b03e5Sespie   return length;
2118c87b03e5Sespie }
2119c87b03e5Sespie 
2120c87b03e5Sespie int
compute_logical_op_cc(mode,operands)2121c87b03e5Sespie compute_logical_op_cc (mode, operands)
2122c87b03e5Sespie      enum machine_mode mode;
2123c87b03e5Sespie      rtx *operands;
2124c87b03e5Sespie {
2125c87b03e5Sespie   /* Figure out the logical op that we need to perform.  */
2126c87b03e5Sespie   enum rtx_code code = GET_CODE (operands[3]);
2127c87b03e5Sespie   /* Pretend that every byte is affected if both operands are registers.  */
2128c87b03e5Sespie   unsigned HOST_WIDE_INT intval =
2129c87b03e5Sespie     (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
2130c87b03e5Sespie 			      ? INTVAL (operands[2]) : 0x55555555);
2131c87b03e5Sespie   /* The determinant of the algorithm.  If we perform an AND, 0
2132c87b03e5Sespie      affects a bit.  Otherwise, 1 affects a bit.  */
2133c87b03e5Sespie   unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
2134c87b03e5Sespie   /* Condition code.  */
2135c87b03e5Sespie   enum attr_cc cc = CC_CLOBBER;
2136c87b03e5Sespie 
2137c87b03e5Sespie   switch (mode)
2138c87b03e5Sespie     {
2139c87b03e5Sespie     case HImode:
2140c87b03e5Sespie       /* First, see if we can finish with one insn.  */
2141c87b03e5Sespie       if ((TARGET_H8300H || TARGET_H8300S)
2142c87b03e5Sespie 	  && ((det & 0x00ff) != 0)
2143c87b03e5Sespie 	  && ((det & 0xff00) != 0))
2144c87b03e5Sespie 	{
2145c87b03e5Sespie 	  cc = CC_SET_ZNV;
2146c87b03e5Sespie 	}
2147c87b03e5Sespie       break;
2148c87b03e5Sespie     case SImode:
2149c87b03e5Sespie       /* First, see if we can finish with one insn.
2150c87b03e5Sespie 
2151c87b03e5Sespie 	 If code is either AND or XOR, we exclude two special cases,
2152c87b03e5Sespie 	 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w
2153c87b03e5Sespie 	 can do a better job.  */
2154c87b03e5Sespie       if ((TARGET_H8300H || TARGET_H8300S)
2155c87b03e5Sespie 	  && ((det & 0x0000ffff) != 0)
2156c87b03e5Sespie 	  && ((det & 0xffff0000) != 0)
2157c87b03e5Sespie 	  && (code == IOR || det != 0xffffff00)
2158c87b03e5Sespie 	  && (code == IOR || det != 0xffff00ff))
2159c87b03e5Sespie 	{
2160c87b03e5Sespie 	  cc = CC_SET_ZNV;
2161c87b03e5Sespie 	}
2162c87b03e5Sespie       break;
2163c87b03e5Sespie     default:
2164c87b03e5Sespie       abort ();
2165c87b03e5Sespie     }
2166c87b03e5Sespie   return cc;
2167c87b03e5Sespie }
2168c87b03e5Sespie 
2169c87b03e5Sespie /* Shifts.
2170c87b03e5Sespie 
2171c87b03e5Sespie    We devote a fair bit of code to getting efficient shifts since we
2172c87b03e5Sespie    can only shift one bit at a time on the H8/300 and H8/300H and only
2173c87b03e5Sespie    one or two bits at a time on the H8S.
2174c87b03e5Sespie 
2175c87b03e5Sespie    All shift code falls into one of the following ways of
2176c87b03e5Sespie    implementation:
2177c87b03e5Sespie 
2178c87b03e5Sespie    o SHIFT_INLINE: Emit straight line code for the shift; this is used
2179c87b03e5Sespie      when a straight line shift is about the same size or smaller than
2180c87b03e5Sespie      a loop.
2181c87b03e5Sespie 
2182c87b03e5Sespie    o SHIFT_ROT_AND: Rotate the value the opposite direction, then mask
2183c87b03e5Sespie      off the bits we don't need.  This is used when only a few of the
2184c87b03e5Sespie      bits in the original value will survive in the shifted value.
2185c87b03e5Sespie 
2186c87b03e5Sespie    o SHIFT_SPECIAL: Often it's possible to move a byte or a word to
2187c87b03e5Sespie      simulate a shift by 8, 16, or 24 bits.  Once moved, a few inline
2188c87b03e5Sespie      shifts can be added if the shift count is slightly more than 8 or
2189c87b03e5Sespie      16.  This case also includes other oddballs that are not worth
2190c87b03e5Sespie      explaning here.
2191c87b03e5Sespie 
2192c87b03e5Sespie    o SHIFT_LOOP: Emit a loop using one (or two on H8S) bit shifts.
2193c87b03e5Sespie 
2194c87b03e5Sespie    For each shift count, we try to use code that has no trade-off
2195c87b03e5Sespie    between code size and speed whenever possible.
2196c87b03e5Sespie 
2197c87b03e5Sespie    If the trade-off is unavoidable, we try to be reasonable.
2198c87b03e5Sespie    Specifically, the fastest version is one instruction longer than
2199c87b03e5Sespie    the shortest version, we take the fastest version.  We also provide
2200c87b03e5Sespie    the use a way to switch back to the shortest version with -Os.
2201c87b03e5Sespie 
2202c87b03e5Sespie    For the details of the shift algorithms for various shift counts,
2203c87b03e5Sespie    refer to shift_alg_[qhs]i.  */
2204c87b03e5Sespie 
2205c87b03e5Sespie int
nshift_operator(x,mode)2206c87b03e5Sespie nshift_operator (x, mode)
2207c87b03e5Sespie      rtx x;
2208c87b03e5Sespie      enum machine_mode mode ATTRIBUTE_UNUSED;
2209c87b03e5Sespie {
2210c87b03e5Sespie   switch (GET_CODE (x))
2211c87b03e5Sespie     {
2212c87b03e5Sespie     case ASHIFTRT:
2213c87b03e5Sespie     case LSHIFTRT:
2214c87b03e5Sespie     case ASHIFT:
2215c87b03e5Sespie       return 1;
2216c87b03e5Sespie 
2217c87b03e5Sespie     default:
2218c87b03e5Sespie       return 0;
2219c87b03e5Sespie     }
2220c87b03e5Sespie }
2221c87b03e5Sespie 
2222c87b03e5Sespie /* Called from the .md file to emit code to do shifts.
2223c87b03e5Sespie    Return a boolean indicating success.
2224c87b03e5Sespie    (Currently this is always TRUE).  */
2225c87b03e5Sespie 
2226c87b03e5Sespie int
expand_a_shift(mode,code,operands)2227c87b03e5Sespie expand_a_shift (mode, code, operands)
2228c87b03e5Sespie      enum machine_mode mode;
2229c87b03e5Sespie      int code;
2230c87b03e5Sespie      rtx operands[];
2231c87b03e5Sespie {
2232c87b03e5Sespie   emit_move_insn (operands[0], operands[1]);
2233c87b03e5Sespie 
2234c87b03e5Sespie   /* Need a loop to get all the bits we want  - we generate the
2235c87b03e5Sespie      code at emit time, but need to allocate a scratch reg now.  */
2236c87b03e5Sespie 
2237c87b03e5Sespie   emit_insn (gen_rtx_PARALLEL
2238c87b03e5Sespie 	     (VOIDmode,
2239c87b03e5Sespie 	      gen_rtvec (2,
2240c87b03e5Sespie 			 gen_rtx_SET (VOIDmode, operands[0],
2241c87b03e5Sespie 				      gen_rtx (code, mode, operands[0],
2242c87b03e5Sespie 					       operands[2])),
2243c87b03e5Sespie 			 gen_rtx_CLOBBER (VOIDmode,
2244c87b03e5Sespie 					  gen_rtx_SCRATCH (QImode)))));
2245c87b03e5Sespie 
2246c87b03e5Sespie   return 1;
2247c87b03e5Sespie }
2248c87b03e5Sespie 
2249c87b03e5Sespie /* Symbols of the various modes which can be used as indices.  */
2250c87b03e5Sespie 
2251c87b03e5Sespie enum shift_mode
2252c87b03e5Sespie {
2253c87b03e5Sespie   QIshift, HIshift, SIshift
2254c87b03e5Sespie };
2255c87b03e5Sespie 
2256c87b03e5Sespie /* For single bit shift insns, record assembler and what bits of the
2257c87b03e5Sespie    condition code are valid afterwards (represented as various CC_FOO
2258c87b03e5Sespie    bits, 0 means CC isn't left in a usable state).  */
2259c87b03e5Sespie 
2260c87b03e5Sespie struct shift_insn
2261c87b03e5Sespie {
2262c87b03e5Sespie   const char *const assembler;
2263c87b03e5Sespie   const int cc_valid;
2264c87b03e5Sespie };
2265c87b03e5Sespie 
2266c87b03e5Sespie /* Assembler instruction shift table.
2267c87b03e5Sespie 
2268c87b03e5Sespie    These tables are used to look up the basic shifts.
2269c87b03e5Sespie    They are indexed by cpu, shift_type, and mode.  */
2270c87b03e5Sespie 
2271c87b03e5Sespie static const struct shift_insn shift_one[2][3][3] =
2272c87b03e5Sespie {
2273c87b03e5Sespie /* H8/300 */
2274c87b03e5Sespie   {
2275c87b03e5Sespie /* SHIFT_ASHIFT */
2276c87b03e5Sespie     {
2277c87b03e5Sespie       { "shll\t%X0", CC_NO_CARRY },
2278c87b03e5Sespie       { "add.w\t%T0,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
2279c87b03e5Sespie       { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", 0 }
2280c87b03e5Sespie     },
2281c87b03e5Sespie /* SHIFT_LSHIFTRT */
2282c87b03e5Sespie     {
2283c87b03e5Sespie       { "shlr\t%X0", CC_NO_CARRY },
2284c87b03e5Sespie       { "shlr\t%t0\n\trotxr\t%s0", 0 },
2285c87b03e5Sespie       { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 }
2286c87b03e5Sespie     },
2287c87b03e5Sespie /* SHIFT_ASHIFTRT */
2288c87b03e5Sespie     {
2289c87b03e5Sespie       { "shar\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
2290c87b03e5Sespie       { "shar\t%t0\n\trotxr\t%s0", 0 },
2291c87b03e5Sespie       { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 }
2292c87b03e5Sespie     }
2293c87b03e5Sespie   },
2294c87b03e5Sespie /* H8/300H */
2295c87b03e5Sespie   {
2296c87b03e5Sespie /* SHIFT_ASHIFT */
2297c87b03e5Sespie     {
2298c87b03e5Sespie       { "shll.b\t%X0", CC_NO_CARRY },
2299c87b03e5Sespie       { "shll.w\t%T0", CC_NO_CARRY },
2300c87b03e5Sespie       { "shll.l\t%S0", CC_NO_CARRY }
2301c87b03e5Sespie     },
2302c87b03e5Sespie /* SHIFT_LSHIFTRT */
2303c87b03e5Sespie     {
2304c87b03e5Sespie       { "shlr.b\t%X0", CC_NO_CARRY },
2305c87b03e5Sespie       { "shlr.w\t%T0", CC_NO_CARRY },
2306c87b03e5Sespie       { "shlr.l\t%S0", CC_NO_CARRY }
2307c87b03e5Sespie     },
2308c87b03e5Sespie /* SHIFT_ASHIFTRT */
2309c87b03e5Sespie     {
2310c87b03e5Sespie       { "shar.b\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
2311c87b03e5Sespie       { "shar.w\t%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
2312c87b03e5Sespie       { "shar.l\t%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }
2313c87b03e5Sespie     }
2314c87b03e5Sespie   }
2315c87b03e5Sespie };
2316c87b03e5Sespie 
2317c87b03e5Sespie static const struct shift_insn shift_two[3][3] =
2318c87b03e5Sespie {
2319c87b03e5Sespie /* SHIFT_ASHIFT */
2320c87b03e5Sespie     {
2321c87b03e5Sespie       { "shll.b\t#2,%X0", CC_NO_CARRY },
2322c87b03e5Sespie       { "shll.w\t#2,%T0", CC_NO_CARRY },
2323c87b03e5Sespie       { "shll.l\t#2,%S0", CC_NO_CARRY }
2324c87b03e5Sespie     },
2325c87b03e5Sespie /* SHIFT_LSHIFTRT */
2326c87b03e5Sespie     {
2327c87b03e5Sespie       { "shlr.b\t#2,%X0", CC_NO_CARRY },
2328c87b03e5Sespie       { "shlr.w\t#2,%T0", CC_NO_CARRY },
2329c87b03e5Sespie       { "shlr.l\t#2,%S0", CC_NO_CARRY }
2330c87b03e5Sespie     },
2331c87b03e5Sespie /* SHIFT_ASHIFTRT */
2332c87b03e5Sespie     {
2333c87b03e5Sespie       { "shar.b\t#2,%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
2334c87b03e5Sespie       { "shar.w\t#2,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
2335c87b03e5Sespie       { "shar.l\t#2,%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }
2336c87b03e5Sespie     }
2337c87b03e5Sespie };
2338c87b03e5Sespie 
2339c87b03e5Sespie /* Rotates are organized by which shift they'll be used in implementing.
2340c87b03e5Sespie    There's no need to record whether the cc is valid afterwards because
2341c87b03e5Sespie    it is the AND insn that will decide this.  */
2342c87b03e5Sespie 
2343c87b03e5Sespie static const char *const rotate_one[2][3][3] =
2344c87b03e5Sespie {
2345c87b03e5Sespie /* H8/300 */
2346c87b03e5Sespie   {
2347c87b03e5Sespie /* SHIFT_ASHIFT */
2348c87b03e5Sespie     {
2349c87b03e5Sespie       "rotr\t%X0",
2350c87b03e5Sespie       "shlr\t%t0\n\trotxr\t%s0\n\tbst\t#7,%t0",
2351c87b03e5Sespie       0
2352c87b03e5Sespie     },
2353c87b03e5Sespie /* SHIFT_LSHIFTRT */
2354c87b03e5Sespie     {
2355c87b03e5Sespie       "rotl\t%X0",
2356c87b03e5Sespie       "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
2357c87b03e5Sespie       0
2358c87b03e5Sespie     },
2359c87b03e5Sespie /* SHIFT_ASHIFTRT */
2360c87b03e5Sespie     {
2361c87b03e5Sespie       "rotl\t%X0",
2362c87b03e5Sespie       "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
2363c87b03e5Sespie       0
2364c87b03e5Sespie     }
2365c87b03e5Sespie   },
2366c87b03e5Sespie /* H8/300H */
2367c87b03e5Sespie   {
2368c87b03e5Sespie /* SHIFT_ASHIFT */
2369c87b03e5Sespie     {
2370c87b03e5Sespie       "rotr.b\t%X0",
2371c87b03e5Sespie       "rotr.w\t%T0",
2372c87b03e5Sespie       "rotr.l\t%S0"
2373c87b03e5Sespie     },
2374c87b03e5Sespie /* SHIFT_LSHIFTRT */
2375c87b03e5Sespie     {
2376c87b03e5Sespie       "rotl.b\t%X0",
2377c87b03e5Sespie       "rotl.w\t%T0",
2378c87b03e5Sespie       "rotl.l\t%S0"
2379c87b03e5Sespie     },
2380c87b03e5Sespie /* SHIFT_ASHIFTRT */
2381c87b03e5Sespie     {
2382c87b03e5Sespie       "rotl.b\t%X0",
2383c87b03e5Sespie       "rotl.w\t%T0",
2384c87b03e5Sespie       "rotl.l\t%S0"
2385c87b03e5Sespie     }
2386c87b03e5Sespie   }
2387c87b03e5Sespie };
2388c87b03e5Sespie 
2389c87b03e5Sespie static const char *const rotate_two[3][3] =
2390c87b03e5Sespie {
2391c87b03e5Sespie /* SHIFT_ASHIFT */
2392c87b03e5Sespie     {
2393c87b03e5Sespie       "rotr.b\t#2,%X0",
2394c87b03e5Sespie       "rotr.w\t#2,%T0",
2395c87b03e5Sespie       "rotr.l\t#2,%S0"
2396c87b03e5Sespie     },
2397c87b03e5Sespie /* SHIFT_LSHIFTRT */
2398c87b03e5Sespie     {
2399c87b03e5Sespie       "rotl.b\t#2,%X0",
2400c87b03e5Sespie       "rotl.w\t#2,%T0",
2401c87b03e5Sespie       "rotl.l\t#2,%S0"
2402c87b03e5Sespie     },
2403c87b03e5Sespie /* SHIFT_ASHIFTRT */
2404c87b03e5Sespie     {
2405c87b03e5Sespie       "rotl.b\t#2,%X0",
2406c87b03e5Sespie       "rotl.w\t#2,%T0",
2407c87b03e5Sespie       "rotl.l\t#2,%S0"
2408c87b03e5Sespie     }
2409c87b03e5Sespie };
2410c87b03e5Sespie 
2411c87b03e5Sespie struct shift_info {
2412c87b03e5Sespie   /* Shift algorithm.  */
2413c87b03e5Sespie   enum shift_alg alg;
2414c87b03e5Sespie 
2415c87b03e5Sespie   /* The number of bits to be shifted by shift1 and shift2.  Valid
2416c87b03e5Sespie      when ALG is SHIFT_SPECIAL.  */
2417c87b03e5Sespie   unsigned int remainder;
2418c87b03e5Sespie 
2419c87b03e5Sespie   /* Special insn for a shift.  Valid when ALG is SHIFT_SPECIAL.  */
2420c87b03e5Sespie   const char *special;
2421c87b03e5Sespie 
2422c87b03e5Sespie   /* Insn for a one-bit shift.  Valid when ALG is either SHIFT_INLINE
2423c87b03e5Sespie      or SHIFT_SPECIAL, and REMAINDER is nonzero.  */
2424c87b03e5Sespie   const char *shift1;
2425c87b03e5Sespie 
2426c87b03e5Sespie   /* Insn for a two-bit shift.  Valid when ALG is either SHIFT_INLINE
2427c87b03e5Sespie      or SHIFT_SPECIAL, and REMAINDER is nonzero.  */
2428c87b03e5Sespie   const char *shift2;
2429c87b03e5Sespie 
2430c87b03e5Sespie   /* Valid CC flags.  */
2431c87b03e5Sespie   int cc_valid_p;
2432c87b03e5Sespie };
2433c87b03e5Sespie 
2434c87b03e5Sespie static void get_shift_alg PARAMS ((enum shift_type,
2435c87b03e5Sespie 				   enum shift_mode, unsigned int,
2436c87b03e5Sespie 				   struct shift_info *));
2437c87b03e5Sespie 
2438c87b03e5Sespie /* Given SHIFT_TYPE, SHIFT_MODE, and shift count COUNT, determine the
2439c87b03e5Sespie    best algorithm for doing the shift.  The assembler code is stored
2440c87b03e5Sespie    in the pointers in INFO.  We achieve the maximum efficiency in most
2441c87b03e5Sespie    cases when !TARGET_H8300.  In case of TARGET_H8300, shifts in
2442c87b03e5Sespie    SImode in particular have a lot of room to optimize.
2443c87b03e5Sespie 
2444c87b03e5Sespie    We first determine the strategy of the shift algorithm by a table
2445c87b03e5Sespie    lookup.  If that tells us to use a hand crafted assembly code, we
2446c87b03e5Sespie    go into the big switch statement to find what that is.  Otherwise,
2447c87b03e5Sespie    we resort to a generic way, such as inlining.  In either case, the
2448c87b03e5Sespie    result is returned through INFO.  */
2449c87b03e5Sespie 
2450c87b03e5Sespie static void
get_shift_alg(shift_type,shift_mode,count,info)2451c87b03e5Sespie get_shift_alg (shift_type, shift_mode, count, info)
2452c87b03e5Sespie      enum shift_type shift_type;
2453c87b03e5Sespie      enum shift_mode shift_mode;
2454c87b03e5Sespie      unsigned int count;
2455c87b03e5Sespie      struct shift_info *info;
2456c87b03e5Sespie {
2457c87b03e5Sespie   enum h8_cpu cpu;
2458c87b03e5Sespie 
2459c87b03e5Sespie   /* Find the target CPU.  */
2460c87b03e5Sespie   if (TARGET_H8300)
2461c87b03e5Sespie     cpu = H8_300;
2462c87b03e5Sespie   else if (TARGET_H8300H)
2463c87b03e5Sespie     cpu = H8_300H;
2464c87b03e5Sespie   else
2465c87b03e5Sespie     cpu = H8_S;
2466c87b03e5Sespie 
2467c87b03e5Sespie   /* Find the shift algorithm.  */
2468c87b03e5Sespie   info->alg = SHIFT_LOOP;
2469c87b03e5Sespie   switch (shift_mode)
2470c87b03e5Sespie     {
2471c87b03e5Sespie     case QIshift:
2472c87b03e5Sespie       if (count < GET_MODE_BITSIZE (QImode))
2473c87b03e5Sespie 	info->alg = shift_alg_qi[cpu][shift_type][count];
2474c87b03e5Sespie       break;
2475c87b03e5Sespie 
2476c87b03e5Sespie     case HIshift:
2477c87b03e5Sespie       if (count < GET_MODE_BITSIZE (HImode))
2478c87b03e5Sespie 	info->alg = shift_alg_hi[cpu][shift_type][count];
2479c87b03e5Sespie       break;
2480c87b03e5Sespie 
2481c87b03e5Sespie     case SIshift:
2482c87b03e5Sespie       if (count < GET_MODE_BITSIZE (SImode))
2483c87b03e5Sespie 	info->alg = shift_alg_si[cpu][shift_type][count];
2484c87b03e5Sespie       break;
2485c87b03e5Sespie 
2486c87b03e5Sespie     default:
2487c87b03e5Sespie       abort ();
2488c87b03e5Sespie     }
2489c87b03e5Sespie 
2490c87b03e5Sespie   /* Fill in INFO.  Return unless we have SHIFT_SPECIAL.  */
2491c87b03e5Sespie   switch (info->alg)
2492c87b03e5Sespie     {
2493c87b03e5Sespie     case SHIFT_INLINE:
2494c87b03e5Sespie       info->remainder = count;
2495c87b03e5Sespie       /* Fall through.  */
2496c87b03e5Sespie 
2497c87b03e5Sespie     case SHIFT_LOOP:
2498c87b03e5Sespie       /* It is up to the caller to know that looping clobbers cc.  */
2499c87b03e5Sespie       info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
2500c87b03e5Sespie       info->shift2 = shift_two[shift_type][shift_mode].assembler;
2501c87b03e5Sespie       info->cc_valid_p = shift_one[cpu_type][shift_type][shift_mode].cc_valid;
2502c87b03e5Sespie       goto end;
2503c87b03e5Sespie 
2504c87b03e5Sespie     case SHIFT_ROT_AND:
2505c87b03e5Sespie       info->shift1 = rotate_one[cpu_type][shift_type][shift_mode];
2506c87b03e5Sespie       info->shift2 = rotate_two[shift_type][shift_mode];
2507c87b03e5Sespie       info->cc_valid_p = 0;
2508c87b03e5Sespie       goto end;
2509c87b03e5Sespie 
2510c87b03e5Sespie     case SHIFT_SPECIAL:
2511c87b03e5Sespie       /* REMAINDER is 0 for most cases, so initialize it to 0.  */
2512c87b03e5Sespie       info->remainder = 0;
2513c87b03e5Sespie       info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
2514c87b03e5Sespie       info->shift2 = shift_two[shift_type][shift_mode].assembler;
2515c87b03e5Sespie       info->cc_valid_p = 0;
2516c87b03e5Sespie       break;
2517c87b03e5Sespie     }
2518c87b03e5Sespie 
2519c87b03e5Sespie   /* Here we only deal with SHIFT_SPECIAL.  */
2520c87b03e5Sespie   switch (shift_mode)
2521c87b03e5Sespie     {
2522c87b03e5Sespie     case QIshift:
2523c87b03e5Sespie       /* For ASHIFTRT by 7 bits, the sign bit is simply replicated
2524c87b03e5Sespie 	 through the entire value.  */
2525c87b03e5Sespie       if (shift_type == SHIFT_ASHIFTRT && count == 7)
2526c87b03e5Sespie 	{
2527c87b03e5Sespie 	  info->special = "shll\t%X0\n\tsubx\t%X0,%X0";
2528c87b03e5Sespie 	  goto end;
2529c87b03e5Sespie 	}
2530c87b03e5Sespie       abort ();
2531c87b03e5Sespie 
2532c87b03e5Sespie     case HIshift:
2533c87b03e5Sespie       if (count == 7)
2534c87b03e5Sespie 	{
2535c87b03e5Sespie 	  switch (shift_type)
2536c87b03e5Sespie 	    {
2537c87b03e5Sespie 	    case SHIFT_ASHIFT:
2538c87b03e5Sespie 	      if (TARGET_H8300)
2539c87b03e5Sespie 		info->special = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.b\t%t0\n\trotr.b\t%s0\n\tand.b\t#0x80,%s0";
2540c87b03e5Sespie 	      else
2541c87b03e5Sespie 		info->special = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.w\t%T0\n\tand.b\t#0x80,%s0";
2542c87b03e5Sespie 	      goto end;
2543c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2544c87b03e5Sespie 	      if (TARGET_H8300)
2545c87b03e5Sespie 		info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\trotl.b\t%t0\n\tand.b\t#0x01,%t0";
2546c87b03e5Sespie 	      else
2547c87b03e5Sespie 		info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.w\t%T0\n\tand.b\t#0x01,%t0";
2548c87b03e5Sespie 	      goto end;
2549c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2550c87b03e5Sespie 	      info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\tsubx\t%t0,%t0";
2551c87b03e5Sespie 	      goto end;
2552c87b03e5Sespie 	    }
2553c87b03e5Sespie 	}
2554c87b03e5Sespie       else if (8 <= count && count <= 13)
2555c87b03e5Sespie 	{
2556c87b03e5Sespie 	  info->remainder = count - 8;
2557c87b03e5Sespie 
2558c87b03e5Sespie 	  switch (shift_type)
2559c87b03e5Sespie 	    {
2560c87b03e5Sespie 	    case SHIFT_ASHIFT:
2561c87b03e5Sespie 	      info->special = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0";
2562c87b03e5Sespie 	      info->shift1  = "shal.b\t%t0";
2563c87b03e5Sespie 	      info->shift2  = "shal.b\t#2,%t0";
2564c87b03e5Sespie 	      goto end;
2565c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2566c87b03e5Sespie 	      info->special = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0";
2567c87b03e5Sespie 	      info->shift1  = "shlr.b\t%s0";
2568c87b03e5Sespie 	      info->shift2  = "shlr.b\t#2,%s0";
2569c87b03e5Sespie 	      goto end;
2570c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2571c87b03e5Sespie 	      if (TARGET_H8300)
2572c87b03e5Sespie 		info->special = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0";
2573c87b03e5Sespie 	      else
2574c87b03e5Sespie 		info->special = "mov.b\t%t0,%s0\n\texts.w\t%T0";
2575c87b03e5Sespie 	      info->shift1 = "shar.b\t%s0";
2576c87b03e5Sespie 	      info->shift2 = "shar.b\t#2,%s0";
2577c87b03e5Sespie 	      goto end;
2578c87b03e5Sespie 	    }
2579c87b03e5Sespie 	}
2580c87b03e5Sespie       else if (count == 14)
2581c87b03e5Sespie 	{
2582c87b03e5Sespie 	  switch (shift_type)
2583c87b03e5Sespie 	    {
2584c87b03e5Sespie 	    case SHIFT_ASHIFT:
2585c87b03e5Sespie 	      if (TARGET_H8300)
2586c87b03e5Sespie 		info->special = "mov.b\t%s0,%t0\n\trotr.b\t%t0\n\trotr.b\t%t0\n\tand.b\t#0xC0,%t0\n\tsub.b\t%s0,%s0";
2587c87b03e5Sespie 	      goto end;
2588c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2589c87b03e5Sespie 	      if (TARGET_H8300)
2590c87b03e5Sespie 		info->special = "mov.b\t%t0,%s0\n\trotl.b\t%s0\n\trotl.b\t%s0\n\tand.b\t#3,%s0\n\tsub.b\t%t0,%t0";
2591c87b03e5Sespie 	      goto end;
2592c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2593c87b03e5Sespie 	      if (TARGET_H8300)
2594c87b03e5Sespie 		info->special = "mov.b\t%t0,%s0\n\tshll.b\t%s0\n\tsubx.b\t%t0,%t0\n\tshll.b\t%s0\n\tmov.b\t%t0,%s0\n\tbst.b\t#0,%s0";
2595c87b03e5Sespie 	      else if (TARGET_H8300H)
2596c87b03e5Sespie 		info->special = "shll.b\t%t0\n\tsubx.b\t%s0,%s0\n\tshll.b\t%t0\n\trotxl.b\t%s0\n\texts.w\t%T0";
2597c87b03e5Sespie 	      else /* TARGET_H8300S */
2598c87b03e5Sespie 		info->special = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.w\t#2,%T0\n\tshar.w\t#2,%T0\n\tshar.w\t#2,%T0";
2599c87b03e5Sespie 	      goto end;
2600c87b03e5Sespie 	    }
2601c87b03e5Sespie 	}
2602c87b03e5Sespie       else if (count == 15)
2603c87b03e5Sespie 	{
2604c87b03e5Sespie 	  switch (shift_type)
2605c87b03e5Sespie 	    {
2606c87b03e5Sespie 	    case SHIFT_ASHIFT:
2607c87b03e5Sespie 	      info->special = "bld\t#0,%s0\n\txor\t%s0,%s0\n\txor\t%t0,%t0\n\tbst\t#7,%t0";
2608c87b03e5Sespie 	      goto end;
2609c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2610c87b03e5Sespie 	      info->special = "bld\t#7,%t0\n\txor\t%s0,%s0\n\txor\t%t0,%t0\n\tbst\t#0,%s0";
2611c87b03e5Sespie 	      goto end;
2612c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2613c87b03e5Sespie 	      info->special = "shll\t%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0";
2614c87b03e5Sespie 	      goto end;
2615c87b03e5Sespie 	    }
2616c87b03e5Sespie 	}
2617c87b03e5Sespie       abort ();
2618c87b03e5Sespie 
2619c87b03e5Sespie     case SIshift:
2620c87b03e5Sespie       if (TARGET_H8300 && 8 <= count && count <= 9)
2621c87b03e5Sespie 	{
2622c87b03e5Sespie 	  info->remainder = count - 8;
2623c87b03e5Sespie 
2624c87b03e5Sespie 	  switch (shift_type)
2625c87b03e5Sespie 	    {
2626c87b03e5Sespie 	    case SHIFT_ASHIFT:
2627c87b03e5Sespie 	      info->special = "mov.b\t%y0,%z0\n\tmov.b\t%x0,%y0\n\tmov.b\t%w0,%x0\n\tsub.b\t%w0,%w0";
2628c87b03e5Sespie 	      goto end;
2629c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2630c87b03e5Sespie 	      info->special = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tsub.b\t%z0,%z0";
2631c87b03e5Sespie 	      info->shift1  = "shlr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0";
2632c87b03e5Sespie 	      goto end;
2633c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2634c87b03e5Sespie 	      info->special = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tshll\t%z0\n\tsubx\t%z0,%z0";
2635c87b03e5Sespie 	      goto end;
2636c87b03e5Sespie 	    }
2637c87b03e5Sespie 	}
2638c87b03e5Sespie       else if (count == 8 && !TARGET_H8300)
2639c87b03e5Sespie 	{
2640c87b03e5Sespie 	  switch (shift_type)
2641c87b03e5Sespie 	    {
2642c87b03e5Sespie 	    case SHIFT_ASHIFT:
2643c87b03e5Sespie 	      info->special = "mov.w\t%e0,%f4\n\tmov.b\t%s4,%t4\n\tmov.b\t%t0,%s4\n\tmov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f4,%e0";
2644c87b03e5Sespie 	      goto end;
2645c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2646c87b03e5Sespie 	      info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\textu.w\t%f4\n\tmov.w\t%f4,%e0";
2647c87b03e5Sespie 	      goto end;
2648c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2649c87b03e5Sespie 	      info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\texts.w\t%f4\n\tmov.w\t%f4,%e0";
2650c87b03e5Sespie 	      goto end;
2651c87b03e5Sespie 	    }
2652c87b03e5Sespie 	}
2653c87b03e5Sespie       else if (count == 15 && TARGET_H8300)
2654c87b03e5Sespie 	{
2655c87b03e5Sespie 	  switch (shift_type)
2656c87b03e5Sespie 	    {
2657c87b03e5Sespie 	    case SHIFT_ASHIFT:
2658c87b03e5Sespie 	      abort ();
2659c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2660c87b03e5Sespie 	      info->special = "bld\t#7,%z0\n\tmov.w\t%e0,%f0\n\txor\t%y0,%y0\n\txor\t%z0,%z0\n\trotxl\t%w0,%w0\n\trotxl\t%x0,%x0\n\trotxl\t%y0,%y0";
2661c87b03e5Sespie 	      goto end;
2662c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2663c87b03e5Sespie 	      info->special = "bld\t#7,%z0\n\tmov.w\t%e0,%f0\n\trotxl\t%w0,%w0\n\trotxl\t%x0,%x0\n\tsubx\t%y0,%y0\n\tsubx\t%z0,%z0";
2664c87b03e5Sespie 	      goto end;
2665c87b03e5Sespie 	    }
2666c87b03e5Sespie 	}
2667c87b03e5Sespie       else if (count == 15 && !TARGET_H8300)
2668c87b03e5Sespie 	{
2669c87b03e5Sespie 	  switch (shift_type)
2670c87b03e5Sespie 	    {
2671c87b03e5Sespie 	    case SHIFT_ASHIFT:
2672c87b03e5Sespie 	      info->special = "shlr.w\t%e0\n\tmov.w\t%f0,%e0\n\txor.w\t%f0,%f0\n\trotxr.l\t%S0";
2673c87b03e5Sespie 	      goto end;
2674c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2675c87b03e5Sespie 	      info->special = "shll.w\t%f0\n\tmov.w\t%e0,%f0\n\txor.w\t%e0,%e0\n\trotxl.l\t%S0";
2676c87b03e5Sespie 	      goto end;
2677c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2678c87b03e5Sespie 	      abort ();
2679c87b03e5Sespie 	    }
2680c87b03e5Sespie 	}
2681c87b03e5Sespie       else if ((TARGET_H8300 && 16 <= count && count <= 20)
2682c87b03e5Sespie 	       || (TARGET_H8300H && 16 <= count && count <= 19)
2683c87b03e5Sespie 	       || (TARGET_H8300S && 16 <= count && count <= 21))
2684c87b03e5Sespie 	{
2685c87b03e5Sespie 	  info->remainder = count - 16;
2686c87b03e5Sespie 
2687c87b03e5Sespie 	  switch (shift_type)
2688c87b03e5Sespie 	    {
2689c87b03e5Sespie 	    case SHIFT_ASHIFT:
2690c87b03e5Sespie 	      info->special = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0";
2691c87b03e5Sespie 	      if (TARGET_H8300)
2692c87b03e5Sespie 		{
2693c87b03e5Sespie 		  info->shift1 = "add.w\t%e0,%e0";
2694c87b03e5Sespie 		}
2695c87b03e5Sespie 	      else
2696c87b03e5Sespie 		{
2697c87b03e5Sespie 		  info->shift1 = "shll.l\t%S0";
2698c87b03e5Sespie 		  info->shift2 = "shll.l\t#2,%S0";
2699c87b03e5Sespie 		}
2700c87b03e5Sespie 	      goto end;
2701c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2702c87b03e5Sespie 	      info->special = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0";
2703c87b03e5Sespie 	      if (TARGET_H8300)
2704c87b03e5Sespie 		{
2705c87b03e5Sespie 		  info->shift1 = "shlr\t%x0\n\trotxr\t%w0";
2706c87b03e5Sespie 		}
2707c87b03e5Sespie 	      else
2708c87b03e5Sespie 		{
2709c87b03e5Sespie 		  info->shift1 = "shlr.l\t%S0";
2710c87b03e5Sespie 		  info->shift2 = "shlr.l\t#2,%S0";
2711c87b03e5Sespie 		}
2712c87b03e5Sespie 	      goto end;
2713c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2714c87b03e5Sespie 	      if (TARGET_H8300)
2715c87b03e5Sespie 		{
2716c87b03e5Sespie 		  info->special = "mov.w\t%e0,%f0\n\tshll\t%z0\n\tsubx\t%z0,%z0\n\tmov.b\t%z0,%y0";
2717c87b03e5Sespie 		  info->shift1  = "shar\t%x0\n\trotxr\t%w0";
2718c87b03e5Sespie 		}
2719c87b03e5Sespie 	      else
2720c87b03e5Sespie 		{
2721c87b03e5Sespie 		  info->special = "mov.w\t%e0,%f0\n\texts.l\t%S0";
2722c87b03e5Sespie 		  info->shift1  = "shar.l\t%S0";
2723c87b03e5Sespie 		  info->shift2  = "shar.l\t#2,%S0";
2724c87b03e5Sespie 		}
2725c87b03e5Sespie 	      goto end;
2726c87b03e5Sespie 	    }
2727c87b03e5Sespie 	}
2728c87b03e5Sespie       else if (TARGET_H8300 && 24 <= count && count <= 28)
2729c87b03e5Sespie 	{
2730c87b03e5Sespie 	  info->remainder = count - 24;
2731c87b03e5Sespie 
2732c87b03e5Sespie 	  switch (shift_type)
2733c87b03e5Sespie 	    {
2734c87b03e5Sespie 	    case SHIFT_ASHIFT:
2735c87b03e5Sespie 	      info->special = "mov.b\t%w0,%z0\n\tsub.b\t%y0,%y0\n\tsub.w\t%f0,%f0";
2736c87b03e5Sespie 	      info->shift1  = "shll.b\t%z0";
2737c87b03e5Sespie 	      goto end;
2738c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2739c87b03e5Sespie 	      info->special = "mov.b\t%z0,%w0\n\tsub.b\t%x0,%x0\n\tsub.w\t%e0,%e0";
2740c87b03e5Sespie 	      info->shift1  = "shlr.b\t%w0";
2741c87b03e5Sespie 	      goto end;
2742c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2743c87b03e5Sespie 	      info->special = "mov.b\t%z0,%w0\n\tbld\t#7,%w0\n\tsubx\t%x0,%x0\n\tsubx\t%x0,%x0\n\tsubx\t%x0,%x0";
2744c87b03e5Sespie 	      info->shift1  = "shar.b\t%w0";
2745c87b03e5Sespie 	      goto end;
2746c87b03e5Sespie 	    }
2747c87b03e5Sespie 	}
2748c87b03e5Sespie       else if ((TARGET_H8300H && count == 24)
2749c87b03e5Sespie 	       || (TARGET_H8300S && 24 <= count && count <= 25))
2750c87b03e5Sespie 	{
2751c87b03e5Sespie 	  info->remainder = count - 24;
2752c87b03e5Sespie 
2753c87b03e5Sespie 	  switch (shift_type)
2754c87b03e5Sespie 	    {
2755c87b03e5Sespie 	    case SHIFT_ASHIFT:
2756c87b03e5Sespie 	      info->special = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f0,%e0\n\tsub.w\t%f0,%f0";
2757c87b03e5Sespie 	      info->shift1  = "shll.l\t%S0";
2758c87b03e5Sespie 	      info->shift2  = "shll.l\t#2,%S0";
2759c87b03e5Sespie 	      goto end;
2760c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2761c87b03e5Sespie 	      info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\textu.w\t%f0\n\textu.l\t%S0";
2762c87b03e5Sespie 	      info->shift1  = "shlr.l\t%S0";
2763c87b03e5Sespie 	      info->shift2  = "shlr.l\t#2,%S0";
2764c87b03e5Sespie 	      goto end;
2765c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2766c87b03e5Sespie 	      info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\texts.w\t%f0\n\texts.l\t%S0";
2767c87b03e5Sespie 	      info->shift1  = "shar.l\t%S0";
2768c87b03e5Sespie 	      info->shift2  = "shar.l\t#2,%S0";
2769c87b03e5Sespie 	      goto end;
2770c87b03e5Sespie 	    }
2771c87b03e5Sespie 	}
2772c87b03e5Sespie       else if (!TARGET_H8300 && count == 28)
2773c87b03e5Sespie 	{
2774c87b03e5Sespie 	  switch (shift_type)
2775c87b03e5Sespie 	    {
2776c87b03e5Sespie 	    case SHIFT_ASHIFT:
2777c87b03e5Sespie 	      if (TARGET_H8300H)
2778c87b03e5Sespie 		info->special = "sub.w\t%e0,%e0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
2779c87b03e5Sespie 	      else
2780c87b03e5Sespie 		info->special = "sub.w\t%e0,%e0\n\trotr.l\t#2,%S0\n\trotr.l\t#2,%S0\n\tsub.w\t%f0,%f0";
2781c87b03e5Sespie 	      info->shift1  = "";
2782c87b03e5Sespie 	      info->shift2  = "";
2783c87b03e5Sespie 	      goto end;
2784c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2785c87b03e5Sespie 	      if (TARGET_H8300H)
2786c87b03e5Sespie 		info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\tsub.w\t%e0,%e0";
2787c87b03e5Sespie 	      else
2788c87b03e5Sespie 		info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\trotl.l\t#2,%S0\n\tsub.w\t%e0,%e0";
2789c87b03e5Sespie 	      info->shift1  = "";
2790c87b03e5Sespie 	      info->shift2  = "";
2791c87b03e5Sespie 	      goto end;
2792c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2793c87b03e5Sespie 	      abort ();
2794c87b03e5Sespie 	    }
2795c87b03e5Sespie 	}
2796c87b03e5Sespie       else if (!TARGET_H8300 && count == 29)
2797c87b03e5Sespie 	{
2798c87b03e5Sespie 	  switch (shift_type)
2799c87b03e5Sespie 	    {
2800c87b03e5Sespie 	    case SHIFT_ASHIFT:
2801c87b03e5Sespie 	      if (TARGET_H8300H)
2802c87b03e5Sespie 		info->special = "sub.w\t%e0,%e0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
2803c87b03e5Sespie 	      else
2804c87b03e5Sespie 		info->special = "sub.w\t%e0,%e0\n\trotr.l\t#2,%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
2805c87b03e5Sespie 	      info->shift1  = "";
2806c87b03e5Sespie 	      info->shift2  = "";
2807c87b03e5Sespie 	      goto end;
2808c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2809c87b03e5Sespie 	      if (TARGET_H8300H)
2810c87b03e5Sespie 		info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\tsub.w\t%e0,%e0";
2811c87b03e5Sespie 	      else
2812c87b03e5Sespie 		info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\trotl.l\t%S0\n\tsub.w\t%e0,%e0";
2813c87b03e5Sespie 	      info->shift1  = "";
2814c87b03e5Sespie 	      info->shift2  = "";
2815c87b03e5Sespie 	      goto end;
2816c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2817c87b03e5Sespie 	      abort ();
2818c87b03e5Sespie 	    }
2819c87b03e5Sespie 	}
2820c87b03e5Sespie       else if (!TARGET_H8300 && count == 30)
2821c87b03e5Sespie 	{
2822c87b03e5Sespie 	  switch (shift_type)
2823c87b03e5Sespie 	    {
2824c87b03e5Sespie 	    case SHIFT_ASHIFT:
2825c87b03e5Sespie 	      if (TARGET_H8300H)
2826c87b03e5Sespie 		info->special = "sub.w\t%e0,%e0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
2827c87b03e5Sespie 	      else
2828c87b03e5Sespie 		info->special = "sub.w\t%e0,%e0\n\trotr.l\t#2,%S0\n\tsub.w\t%f0,%f0";
2829c87b03e5Sespie 	      info->shift1  = "";
2830c87b03e5Sespie 	      info->shift2  = "";
2831c87b03e5Sespie 	      goto end;
2832c87b03e5Sespie 	    case SHIFT_LSHIFTRT:
2833c87b03e5Sespie 	      if (TARGET_H8300H)
2834c87b03e5Sespie 		info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\tsub.w\t%e0,%e0";
2835c87b03e5Sespie 	      else
2836c87b03e5Sespie 		info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\tsub.w\t%e0,%e0";
2837c87b03e5Sespie 	      info->shift1  = "";
2838c87b03e5Sespie 	      info->shift2  = "";
2839c87b03e5Sespie 	      goto end;
2840c87b03e5Sespie 	    case SHIFT_ASHIFTRT:
2841c87b03e5Sespie 	      abort ();
2842c87b03e5Sespie 	    }
2843c87b03e5Sespie 	}
2844c87b03e5Sespie       else if (count == 31)
2845c87b03e5Sespie 	{
2846c87b03e5Sespie 	  if (TARGET_H8300)
2847c87b03e5Sespie 	    {
2848c87b03e5Sespie 	      switch (shift_type)
2849c87b03e5Sespie 		{
2850c87b03e5Sespie 		case SHIFT_ASHIFT:
2851c87b03e5Sespie 		  info->special = "sub.w\t%e0,%e0\n\tshlr\t%w0\n\tmov.w\t%e0,%f0\n\trotxr\t%z0";
2852c87b03e5Sespie 		  goto end;
2853c87b03e5Sespie 		case SHIFT_LSHIFTRT:
2854c87b03e5Sespie 		  info->special = "sub.w\t%f0,%f0\n\tshll\t%z0\n\tmov.w\t%f0,%e0\n\trotxl\t%w0";
2855c87b03e5Sespie 		  goto end;
2856c87b03e5Sespie 		case SHIFT_ASHIFTRT:
2857c87b03e5Sespie 		  info->special = "shll\t%z0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
2858c87b03e5Sespie 		  goto end;
2859c87b03e5Sespie 		}
2860c87b03e5Sespie 	    }
2861c87b03e5Sespie 	  else
2862c87b03e5Sespie 	    {
2863c87b03e5Sespie 	      switch (shift_type)
2864c87b03e5Sespie 		{
2865c87b03e5Sespie 		case SHIFT_ASHIFT:
2866c87b03e5Sespie 		  info->special = "shlr.l\t%S0\n\txor.l\t%S0,%S0\n\trotxr.l\t%S0";
2867c87b03e5Sespie 		  goto end;
2868c87b03e5Sespie 		case SHIFT_LSHIFTRT:
2869c87b03e5Sespie 		  info->special = "shll.l\t%S0\n\txor.l\t%S0,%S0\n\trotxl.l\t%S0";
2870c87b03e5Sespie 		  goto end;
2871c87b03e5Sespie 		case SHIFT_ASHIFTRT:
2872c87b03e5Sespie 		  info->special = "shll\t%e0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
2873c87b03e5Sespie 		  goto end;
2874c87b03e5Sespie 		}
2875c87b03e5Sespie 	    }
2876c87b03e5Sespie 	}
2877c87b03e5Sespie       abort ();
2878c87b03e5Sespie 
2879c87b03e5Sespie     default:
2880c87b03e5Sespie       abort ();
2881c87b03e5Sespie     }
2882c87b03e5Sespie 
2883c87b03e5Sespie  end:
2884c87b03e5Sespie   if (!TARGET_H8300S)
2885c87b03e5Sespie     info->shift2 = NULL;
2886c87b03e5Sespie }
2887c87b03e5Sespie 
2888c87b03e5Sespie /* Given COUNT and MODE of a shift, return 1 if a scratch reg may be
2889c87b03e5Sespie    needed for some shift with COUNT and MODE.  Return 0 otherwise.  */
2890c87b03e5Sespie 
2891c87b03e5Sespie int
h8300_shift_needs_scratch_p(count,mode)2892c87b03e5Sespie h8300_shift_needs_scratch_p (count, mode)
2893c87b03e5Sespie      int count;
2894c87b03e5Sespie      enum machine_mode mode;
2895c87b03e5Sespie {
2896c87b03e5Sespie   enum h8_cpu cpu;
2897c87b03e5Sespie   int a, lr, ar;
2898c87b03e5Sespie 
2899c87b03e5Sespie   if (GET_MODE_BITSIZE (mode) <= count)
2900c87b03e5Sespie     return 1;
2901c87b03e5Sespie 
2902c87b03e5Sespie   /* Find out the target CPU.  */
2903c87b03e5Sespie   if (TARGET_H8300)
2904c87b03e5Sespie     cpu = H8_300;
2905c87b03e5Sespie   else if (TARGET_H8300H)
2906c87b03e5Sespie     cpu = H8_300H;
2907c87b03e5Sespie   else
2908c87b03e5Sespie     cpu = H8_S;
2909c87b03e5Sespie 
2910c87b03e5Sespie   /* Find the shift algorithm.  */
2911c87b03e5Sespie   switch (mode)
2912c87b03e5Sespie     {
2913c87b03e5Sespie     case QImode:
2914c87b03e5Sespie       a  = shift_alg_qi[cpu][SHIFT_ASHIFT][count];
2915c87b03e5Sespie       lr = shift_alg_qi[cpu][SHIFT_LSHIFTRT][count];
2916c87b03e5Sespie       ar = shift_alg_qi[cpu][SHIFT_ASHIFTRT][count];
2917c87b03e5Sespie       break;
2918c87b03e5Sespie 
2919c87b03e5Sespie     case HImode:
2920c87b03e5Sespie       a  = shift_alg_hi[cpu][SHIFT_ASHIFT][count];
2921c87b03e5Sespie       lr = shift_alg_hi[cpu][SHIFT_LSHIFTRT][count];
2922c87b03e5Sespie       ar = shift_alg_hi[cpu][SHIFT_ASHIFTRT][count];
2923c87b03e5Sespie       break;
2924c87b03e5Sespie 
2925c87b03e5Sespie     case SImode:
2926c87b03e5Sespie       a  = shift_alg_si[cpu][SHIFT_ASHIFT][count];
2927c87b03e5Sespie       lr = shift_alg_si[cpu][SHIFT_LSHIFTRT][count];
2928c87b03e5Sespie       ar = shift_alg_si[cpu][SHIFT_ASHIFTRT][count];
2929c87b03e5Sespie       break;
2930c87b03e5Sespie 
2931c87b03e5Sespie     default:
2932c87b03e5Sespie       abort ();
2933c87b03e5Sespie     }
2934c87b03e5Sespie 
2935c87b03e5Sespie   /* On H8/300H and H8S, count == 8 uses the scratch register.  */
2936c87b03e5Sespie   return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
2937c87b03e5Sespie 	  || (!TARGET_H8300 && mode == SImode && count == 8));
2938c87b03e5Sespie }
2939c87b03e5Sespie 
2940c87b03e5Sespie /* Emit the assembler code for doing shifts.  */
2941c87b03e5Sespie 
2942c87b03e5Sespie const char *
output_a_shift(operands)2943c87b03e5Sespie output_a_shift (operands)
2944c87b03e5Sespie      rtx *operands;
2945c87b03e5Sespie {
2946c87b03e5Sespie   static int loopend_lab;
2947c87b03e5Sespie   rtx shift = operands[3];
2948c87b03e5Sespie   enum machine_mode mode = GET_MODE (shift);
2949c87b03e5Sespie   enum rtx_code code = GET_CODE (shift);
2950c87b03e5Sespie   enum shift_type shift_type;
2951c87b03e5Sespie   enum shift_mode shift_mode;
2952c87b03e5Sespie   struct shift_info info;
2953c87b03e5Sespie 
2954c87b03e5Sespie   loopend_lab++;
2955c87b03e5Sespie 
2956c87b03e5Sespie   switch (mode)
2957c87b03e5Sespie     {
2958c87b03e5Sespie     case QImode:
2959c87b03e5Sespie       shift_mode = QIshift;
2960c87b03e5Sespie       break;
2961c87b03e5Sespie     case HImode:
2962c87b03e5Sespie       shift_mode = HIshift;
2963c87b03e5Sespie       break;
2964c87b03e5Sespie     case SImode:
2965c87b03e5Sespie       shift_mode = SIshift;
2966c87b03e5Sespie       break;
2967c87b03e5Sespie     default:
2968c87b03e5Sespie       abort ();
2969c87b03e5Sespie     }
2970c87b03e5Sespie 
2971c87b03e5Sespie   switch (code)
2972c87b03e5Sespie     {
2973c87b03e5Sespie     case ASHIFTRT:
2974c87b03e5Sespie       shift_type = SHIFT_ASHIFTRT;
2975c87b03e5Sespie       break;
2976c87b03e5Sespie     case LSHIFTRT:
2977c87b03e5Sespie       shift_type = SHIFT_LSHIFTRT;
2978c87b03e5Sespie       break;
2979c87b03e5Sespie     case ASHIFT:
2980c87b03e5Sespie       shift_type = SHIFT_ASHIFT;
2981c87b03e5Sespie       break;
2982c87b03e5Sespie     default:
2983c87b03e5Sespie       abort ();
2984c87b03e5Sespie     }
2985c87b03e5Sespie 
2986c87b03e5Sespie   if (GET_CODE (operands[2]) != CONST_INT)
2987c87b03e5Sespie     {
2988c87b03e5Sespie       /* Indexing by reg, so have to loop and test at top.  */
2989c87b03e5Sespie       output_asm_insn ("mov.b	%X2,%X4", operands);
2990c87b03e5Sespie       fprintf (asm_out_file, "\tble	.Lle%d\n", loopend_lab);
2991c87b03e5Sespie 
2992c87b03e5Sespie       /* Get the assembler code to do one shift.  */
2993c87b03e5Sespie       get_shift_alg (shift_type, shift_mode, 1, &info);
2994c87b03e5Sespie 
2995c87b03e5Sespie       fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
2996c87b03e5Sespie       output_asm_insn (info.shift1, operands);
2997c87b03e5Sespie       output_asm_insn ("add	#0xff,%X4", operands);
2998c87b03e5Sespie       fprintf (asm_out_file, "\tbne	.Llt%d\n", loopend_lab);
2999c87b03e5Sespie       fprintf (asm_out_file, ".Lle%d:\n", loopend_lab);
3000c87b03e5Sespie 
3001c87b03e5Sespie       return "";
3002c87b03e5Sespie     }
3003c87b03e5Sespie   else
3004c87b03e5Sespie     {
3005c87b03e5Sespie       int n = INTVAL (operands[2]);
3006c87b03e5Sespie 
3007c87b03e5Sespie       /* If the count is negative, make it 0.  */
3008c87b03e5Sespie       if (n < 0)
3009c87b03e5Sespie 	n = 0;
3010c87b03e5Sespie       /* If the count is too big, truncate it.
3011c87b03e5Sespie          ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
3012c87b03e5Sespie 	 do the intuitive thing.  */
3013c87b03e5Sespie       else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
3014c87b03e5Sespie 	n = GET_MODE_BITSIZE (mode);
3015c87b03e5Sespie 
3016c87b03e5Sespie       get_shift_alg (shift_type, shift_mode, n, &info);
3017c87b03e5Sespie 
3018c87b03e5Sespie       switch (info.alg)
3019c87b03e5Sespie 	{
3020c87b03e5Sespie 	case SHIFT_SPECIAL:
3021c87b03e5Sespie 	  output_asm_insn (info.special, operands);
3022c87b03e5Sespie 	  /* Fall through.  */
3023c87b03e5Sespie 
3024c87b03e5Sespie 	case SHIFT_INLINE:
3025c87b03e5Sespie 	  n = info.remainder;
3026c87b03e5Sespie 
3027c87b03e5Sespie 	  /* Emit two bit shifts first.  */
3028c87b03e5Sespie 	  if (info.shift2 != NULL)
3029c87b03e5Sespie 	    {
3030c87b03e5Sespie 	      for (; n > 1; n -= 2)
3031c87b03e5Sespie 		output_asm_insn (info.shift2, operands);
3032c87b03e5Sespie 	    }
3033c87b03e5Sespie 
3034c87b03e5Sespie 	  /* Now emit one bit shifts for any residual.  */
3035c87b03e5Sespie 	  for (; n > 0; n--)
3036c87b03e5Sespie 	    output_asm_insn (info.shift1, operands);
3037c87b03e5Sespie 
3038c87b03e5Sespie 	  /* Keep track of CC.  */
3039c87b03e5Sespie 	  if (info.cc_valid_p)
3040c87b03e5Sespie 	    {
3041c87b03e5Sespie 	      cc_status.value1 = operands[0];
3042c87b03e5Sespie 	      cc_status.flags |= info.cc_valid_p;
3043c87b03e5Sespie 	    }
3044c87b03e5Sespie 	  return "";
3045c87b03e5Sespie 
3046c87b03e5Sespie 	case SHIFT_ROT_AND:
3047c87b03e5Sespie 	  {
3048c87b03e5Sespie 	    int m = GET_MODE_BITSIZE (mode) - n;
3049c87b03e5Sespie 	    int mask = (shift_type == SHIFT_ASHIFT
3050c87b03e5Sespie 			? ((1 << m) - 1) << n
3051c87b03e5Sespie 			: (1 << m) - 1);
3052c87b03e5Sespie 	    char insn_buf[200];
3053c87b03e5Sespie 
3054c87b03e5Sespie 	    /* Not all possibilities of rotate are supported.  They shouldn't
3055c87b03e5Sespie 	       be generated, but let's watch for 'em.  */
3056c87b03e5Sespie 	    if (info.shift1 == 0)
3057c87b03e5Sespie 	      abort ();
3058c87b03e5Sespie 
3059c87b03e5Sespie 	    /* Emit two bit rotates first.  */
3060c87b03e5Sespie 	    if (info.shift2 != NULL)
3061c87b03e5Sespie 	      {
3062c87b03e5Sespie 		for (; m > 1; m -= 2)
3063c87b03e5Sespie 		  output_asm_insn (info.shift2, operands);
3064c87b03e5Sespie 	      }
3065c87b03e5Sespie 
3066c87b03e5Sespie 	    /* Now single bit rotates for any residual.  */
3067c87b03e5Sespie 	    for (; m > 0; m--)
3068c87b03e5Sespie 	      output_asm_insn (info.shift1, operands);
3069c87b03e5Sespie 
3070c87b03e5Sespie 	    /* Now mask off the high bits.  */
3071c87b03e5Sespie 	    if (TARGET_H8300)
3072c87b03e5Sespie 	      {
3073c87b03e5Sespie 		switch (mode)
3074c87b03e5Sespie 		  {
3075c87b03e5Sespie 		  case QImode:
3076c87b03e5Sespie 		    sprintf (insn_buf, "and\t#%d,%%X0", mask);
3077c87b03e5Sespie 		    cc_status.value1 = operands[0];
3078c87b03e5Sespie 		    cc_status.flags |= CC_NO_CARRY;
3079c87b03e5Sespie 		    break;
3080c87b03e5Sespie 		  case HImode:
3081c87b03e5Sespie 		    sprintf (insn_buf, "and\t#%d,%%s0\n\tand\t#%d,%%t0",
3082c87b03e5Sespie 			     mask & 255, mask >> 8);
3083c87b03e5Sespie 		    break;
3084c87b03e5Sespie 		  default:
3085c87b03e5Sespie 		    abort ();
3086c87b03e5Sespie 		  }
3087c87b03e5Sespie 	      }
3088c87b03e5Sespie 	    else
3089c87b03e5Sespie 	      {
3090c87b03e5Sespie 		sprintf (insn_buf, "and.%c\t#%d,%%%c0",
3091c87b03e5Sespie 			 "bwl"[shift_mode], mask,
3092c87b03e5Sespie 			 mode == QImode ? 'X' : mode == HImode ? 'T' : 'S');
3093c87b03e5Sespie 		cc_status.value1 = operands[0];
3094c87b03e5Sespie 		cc_status.flags |= CC_NO_CARRY;
3095c87b03e5Sespie 	      }
3096c87b03e5Sespie 	    output_asm_insn (insn_buf, operands);
3097c87b03e5Sespie 	    return "";
3098c87b03e5Sespie 	  }
3099c87b03e5Sespie 
3100c87b03e5Sespie 	case SHIFT_LOOP:
3101c87b03e5Sespie 	  /* A loop to shift by a "large" constant value.
3102c87b03e5Sespie 	     If we have shift-by-2 insns, use them.  */
3103c87b03e5Sespie 	  if (info.shift2 != NULL)
3104c87b03e5Sespie 	    {
3105c87b03e5Sespie 	      fprintf (asm_out_file, "\tmov.b	#%d,%sl\n", n / 2,
3106c87b03e5Sespie 		       names_big[REGNO (operands[4])]);
3107c87b03e5Sespie 	      fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
3108c87b03e5Sespie 	      output_asm_insn (info.shift2, operands);
3109c87b03e5Sespie 	      output_asm_insn ("add	#0xff,%X4", operands);
3110c87b03e5Sespie 	      fprintf (asm_out_file, "\tbne	.Llt%d\n", loopend_lab);
3111c87b03e5Sespie 	      if (n % 2)
3112c87b03e5Sespie 		output_asm_insn (info.shift1, operands);
3113c87b03e5Sespie 	    }
3114c87b03e5Sespie 	  else
3115c87b03e5Sespie 	    {
3116c87b03e5Sespie 	      fprintf (asm_out_file, "\tmov.b	#%d,%sl\n", n,
3117c87b03e5Sespie 		       names_big[REGNO (operands[4])]);
3118c87b03e5Sespie 	      fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
3119c87b03e5Sespie 	      output_asm_insn (info.shift1, operands);
3120c87b03e5Sespie 	      output_asm_insn ("add	#0xff,%X4", operands);
3121c87b03e5Sespie 	      fprintf (asm_out_file, "\tbne	.Llt%d\n", loopend_lab);
3122c87b03e5Sespie 	    }
3123c87b03e5Sespie 	  return "";
3124c87b03e5Sespie 
3125c87b03e5Sespie 	default:
3126c87b03e5Sespie 	  abort ();
3127c87b03e5Sespie 	}
3128c87b03e5Sespie     }
3129c87b03e5Sespie }
3130c87b03e5Sespie 
3131c87b03e5Sespie static unsigned int
h8300_asm_insn_count(template)3132c87b03e5Sespie h8300_asm_insn_count (template)
3133c87b03e5Sespie      const char *template;
3134c87b03e5Sespie {
3135c87b03e5Sespie   unsigned int count = 1;
3136c87b03e5Sespie 
3137c87b03e5Sespie   for (; *template; template++)
3138c87b03e5Sespie     if (*template == '\n')
3139c87b03e5Sespie       count++;
3140c87b03e5Sespie 
3141c87b03e5Sespie   return count;
3142c87b03e5Sespie }
3143c87b03e5Sespie 
3144c87b03e5Sespie unsigned int
compute_a_shift_length(insn,operands)3145c87b03e5Sespie compute_a_shift_length (insn, operands)
3146c87b03e5Sespie      rtx insn ATTRIBUTE_UNUSED;
3147c87b03e5Sespie      rtx *operands;
3148c87b03e5Sespie {
3149c87b03e5Sespie   rtx shift = operands[3];
3150c87b03e5Sespie   enum machine_mode mode = GET_MODE (shift);
3151c87b03e5Sespie   enum rtx_code code = GET_CODE (shift);
3152c87b03e5Sespie   enum shift_type shift_type;
3153c87b03e5Sespie   enum shift_mode shift_mode;
3154c87b03e5Sespie   struct shift_info info;
3155c87b03e5Sespie   unsigned int wlength = 0;
3156c87b03e5Sespie 
3157c87b03e5Sespie   switch (mode)
3158c87b03e5Sespie     {
3159c87b03e5Sespie     case QImode:
3160c87b03e5Sespie       shift_mode = QIshift;
3161c87b03e5Sespie       break;
3162c87b03e5Sespie     case HImode:
3163c87b03e5Sespie       shift_mode = HIshift;
3164c87b03e5Sespie       break;
3165c87b03e5Sespie     case SImode:
3166c87b03e5Sespie       shift_mode = SIshift;
3167c87b03e5Sespie       break;
3168c87b03e5Sespie     default:
3169c87b03e5Sespie       abort ();
3170c87b03e5Sespie     }
3171c87b03e5Sespie 
3172c87b03e5Sespie   switch (code)
3173c87b03e5Sespie     {
3174c87b03e5Sespie     case ASHIFTRT:
3175c87b03e5Sespie       shift_type = SHIFT_ASHIFTRT;
3176c87b03e5Sespie       break;
3177c87b03e5Sespie     case LSHIFTRT:
3178c87b03e5Sespie       shift_type = SHIFT_LSHIFTRT;
3179c87b03e5Sespie       break;
3180c87b03e5Sespie     case ASHIFT:
3181c87b03e5Sespie       shift_type = SHIFT_ASHIFT;
3182c87b03e5Sespie       break;
3183c87b03e5Sespie     default:
3184c87b03e5Sespie       abort ();
3185c87b03e5Sespie     }
3186c87b03e5Sespie 
3187c87b03e5Sespie   if (GET_CODE (operands[2]) != CONST_INT)
3188c87b03e5Sespie     {
3189c87b03e5Sespie       /* Get the assembler code to do one shift.  */
3190c87b03e5Sespie       get_shift_alg (shift_type, shift_mode, 1, &info);
3191c87b03e5Sespie 
3192c87b03e5Sespie       return (4 + h8300_asm_insn_count (info.shift1)) * 2;
3193c87b03e5Sespie     }
3194c87b03e5Sespie   else
3195c87b03e5Sespie     {
3196c87b03e5Sespie       int n = INTVAL (operands[2]);
3197c87b03e5Sespie 
3198c87b03e5Sespie       /* If the count is negative, make it 0.  */
3199c87b03e5Sespie       if (n < 0)
3200c87b03e5Sespie 	n = 0;
3201c87b03e5Sespie       /* If the count is too big, truncate it.
3202c87b03e5Sespie          ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
3203c87b03e5Sespie 	 do the intuitive thing.  */
3204c87b03e5Sespie       else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
3205c87b03e5Sespie 	n = GET_MODE_BITSIZE (mode);
3206c87b03e5Sespie 
3207c87b03e5Sespie       get_shift_alg (shift_type, shift_mode, n, &info);
3208c87b03e5Sespie 
3209c87b03e5Sespie       switch (info.alg)
3210c87b03e5Sespie 	{
3211c87b03e5Sespie 	case SHIFT_SPECIAL:
3212c87b03e5Sespie 	  wlength += h8300_asm_insn_count (info.special);
3213c87b03e5Sespie 
3214c87b03e5Sespie 	  /* Every assembly instruction used in SHIFT_SPECIAL case
3215c87b03e5Sespie 	     takes 2 bytes except xor.l, which takes 4 bytes, so if we
3216c87b03e5Sespie 	     see xor.l, we just pretend that xor.l counts as two insns
3217c87b03e5Sespie 	     so that the insn length will be computed correctly.  */
3218c87b03e5Sespie 	  if (strstr (info.special, "xor.l") != NULL)
3219c87b03e5Sespie 	    wlength++;
3220c87b03e5Sespie 
3221c87b03e5Sespie 	  /* Fall through.  */
3222c87b03e5Sespie 
3223c87b03e5Sespie 	case SHIFT_INLINE:
3224c87b03e5Sespie 	  n = info.remainder;
3225c87b03e5Sespie 
3226c87b03e5Sespie 	  if (info.shift2 != NULL)
3227c87b03e5Sespie 	    {
3228c87b03e5Sespie 	      wlength += h8300_asm_insn_count (info.shift2) * (n / 2);
3229c87b03e5Sespie 	      n = n % 2;
3230c87b03e5Sespie 	    }
3231c87b03e5Sespie 
3232c87b03e5Sespie 	  wlength += h8300_asm_insn_count (info.shift1) * n;
3233c87b03e5Sespie 
3234c87b03e5Sespie 	  return 2 * wlength;
3235c87b03e5Sespie 
3236c87b03e5Sespie 	case SHIFT_ROT_AND:
3237c87b03e5Sespie 	  {
3238c87b03e5Sespie 	    int m = GET_MODE_BITSIZE (mode) - n;
3239c87b03e5Sespie 
3240c87b03e5Sespie 	    /* Not all possibilities of rotate are supported.  They shouldn't
3241c87b03e5Sespie 	       be generated, but let's watch for 'em.  */
3242c87b03e5Sespie 	    if (info.shift1 == 0)
3243c87b03e5Sespie 	      abort ();
3244c87b03e5Sespie 
3245c87b03e5Sespie 	    if (info.shift2 != NULL)
3246c87b03e5Sespie 	      {
3247c87b03e5Sespie 		wlength += h8300_asm_insn_count (info.shift2) * (m / 2);
3248c87b03e5Sespie 		m = m % 2;
3249c87b03e5Sespie 	      }
3250c87b03e5Sespie 
3251c87b03e5Sespie 	    wlength += h8300_asm_insn_count (info.shift1) * m;
3252c87b03e5Sespie 
3253c87b03e5Sespie 	    /* Now mask off the high bits.  */
3254c87b03e5Sespie 	    switch (mode)
3255c87b03e5Sespie 	      {
3256c87b03e5Sespie 	      case QImode:
3257c87b03e5Sespie 		wlength += 1;
3258c87b03e5Sespie 		break;
3259c87b03e5Sespie 	      case HImode:
3260c87b03e5Sespie 		wlength += 2;
3261c87b03e5Sespie 		break;
3262c87b03e5Sespie 	      case SImode:
3263c87b03e5Sespie 		if (TARGET_H8300)
3264c87b03e5Sespie 		  abort ();
3265c87b03e5Sespie 		wlength += 3;
3266c87b03e5Sespie 		break;
3267c87b03e5Sespie 	      default:
3268c87b03e5Sespie 		abort ();
3269c87b03e5Sespie 	      }
3270c87b03e5Sespie 	    return 2 * wlength;
3271c87b03e5Sespie 	  }
3272c87b03e5Sespie 
3273c87b03e5Sespie 	case SHIFT_LOOP:
3274c87b03e5Sespie 	  /* A loop to shift by a "large" constant value.
3275c87b03e5Sespie 	     If we have shift-by-2 insns, use them.  */
3276c87b03e5Sespie 	  if (info.shift2 != NULL)
3277c87b03e5Sespie 	    {
3278c87b03e5Sespie 	      wlength += 3 + h8300_asm_insn_count (info.shift2);
3279c87b03e5Sespie 	      if (n % 2)
3280c87b03e5Sespie 		wlength += h8300_asm_insn_count (info.shift1);
3281c87b03e5Sespie 	    }
3282c87b03e5Sespie 	  else
3283c87b03e5Sespie 	    {
3284c87b03e5Sespie 	      wlength += 3 + h8300_asm_insn_count (info.shift1);
3285c87b03e5Sespie 	    }
3286c87b03e5Sespie 	  return 2 * wlength;
3287c87b03e5Sespie 
3288c87b03e5Sespie 	default:
3289c87b03e5Sespie 	  abort ();
3290c87b03e5Sespie 	}
3291c87b03e5Sespie     }
3292c87b03e5Sespie }
3293c87b03e5Sespie 
3294c87b03e5Sespie /* A rotation by a non-constant will cause a loop to be generated, in
3295c87b03e5Sespie    which a rotation by one bit is used.  A rotation by a constant,
3296c87b03e5Sespie    including the one in the loop, will be taken care of by
3297c87b03e5Sespie    emit_a_rotate () at the insn emit time.  */
3298c87b03e5Sespie 
3299c87b03e5Sespie int
expand_a_rotate(code,operands)3300c87b03e5Sespie expand_a_rotate (code, operands)
3301c87b03e5Sespie      enum rtx_code code;
3302c87b03e5Sespie      rtx operands[];
3303c87b03e5Sespie {
3304c87b03e5Sespie   rtx dst = operands[0];
3305c87b03e5Sespie   rtx src = operands[1];
3306c87b03e5Sespie   rtx rotate_amount = operands[2];
3307c87b03e5Sespie   enum machine_mode mode = GET_MODE (dst);
3308c87b03e5Sespie   rtx tmp;
3309c87b03e5Sespie 
3310c87b03e5Sespie   /* We rotate in place.  */
3311c87b03e5Sespie   emit_move_insn (dst, src);
3312c87b03e5Sespie 
3313c87b03e5Sespie   if (GET_CODE (rotate_amount) != CONST_INT)
3314c87b03e5Sespie     {
3315c87b03e5Sespie       rtx counter = gen_reg_rtx (QImode);
3316c87b03e5Sespie       rtx start_label = gen_label_rtx ();
3317c87b03e5Sespie       rtx end_label = gen_label_rtx ();
3318c87b03e5Sespie 
3319c87b03e5Sespie       /* If the rotate amount is less than or equal to 0,
3320c87b03e5Sespie 	 we go out of the loop.  */
3321c87b03e5Sespie       emit_cmp_and_jump_insns (rotate_amount, GEN_INT (0), LE, NULL_RTX,
3322c87b03e5Sespie 			       QImode, 0, end_label);
3323c87b03e5Sespie 
3324c87b03e5Sespie       /* Initialize the loop counter.  */
3325c87b03e5Sespie       emit_move_insn (counter, rotate_amount);
3326c87b03e5Sespie 
3327c87b03e5Sespie       emit_label (start_label);
3328c87b03e5Sespie 
3329c87b03e5Sespie       /* Rotate by one bit.  */
3330c87b03e5Sespie       tmp = gen_rtx (code, mode, dst, GEN_INT (1));
3331c87b03e5Sespie       emit_insn (gen_rtx_SET (mode, dst, tmp));
3332c87b03e5Sespie 
3333c87b03e5Sespie       /* Decrement the counter by 1.  */
3334c87b03e5Sespie       tmp = gen_rtx_PLUS (QImode, counter, GEN_INT (-1));
3335c87b03e5Sespie       emit_insn (gen_rtx_SET (VOIDmode, counter, tmp));
3336c87b03e5Sespie 
3337c87b03e5Sespie       /* If the loop counter is nonzero, we go back to the beginning
3338c87b03e5Sespie 	 of the loop.  */
3339c87b03e5Sespie       emit_cmp_and_jump_insns (counter, GEN_INT (0), NE, NULL_RTX, QImode, 1,
3340c87b03e5Sespie 			       start_label);
3341c87b03e5Sespie 
3342c87b03e5Sespie       emit_label (end_label);
3343c87b03e5Sespie     }
3344c87b03e5Sespie   else
3345c87b03e5Sespie     {
3346c87b03e5Sespie       /* Rotate by AMOUNT bits.  */
3347c87b03e5Sespie       tmp = gen_rtx (code, mode, dst, rotate_amount);
3348c87b03e5Sespie       emit_insn (gen_rtx_SET (mode, dst, tmp));
3349c87b03e5Sespie     }
3350c87b03e5Sespie 
3351c87b03e5Sespie   return 1;
3352c87b03e5Sespie }
3353c87b03e5Sespie 
3354c87b03e5Sespie /* Emit rotate insns.  */
3355c87b03e5Sespie 
3356c87b03e5Sespie const char *
emit_a_rotate(code,operands)3357c87b03e5Sespie emit_a_rotate (code, operands)
3358c87b03e5Sespie      enum rtx_code code;
3359c87b03e5Sespie      rtx *operands;
3360c87b03e5Sespie {
3361c87b03e5Sespie   rtx dst = operands[0];
3362c87b03e5Sespie   rtx rotate_amount = operands[2];
3363c87b03e5Sespie   enum shift_mode rotate_mode;
3364c87b03e5Sespie   enum shift_type rotate_type;
3365c87b03e5Sespie   const char *insn_buf;
3366c87b03e5Sespie   int bits;
3367c87b03e5Sespie   int amount;
3368c87b03e5Sespie   enum machine_mode mode = GET_MODE (dst);
3369c87b03e5Sespie 
3370c87b03e5Sespie   if (GET_CODE (rotate_amount) != CONST_INT)
3371c87b03e5Sespie     abort ();
3372c87b03e5Sespie 
3373c87b03e5Sespie   switch (mode)
3374c87b03e5Sespie     {
3375c87b03e5Sespie     case QImode:
3376c87b03e5Sespie       rotate_mode = QIshift;
3377c87b03e5Sespie       break;
3378c87b03e5Sespie     case HImode:
3379c87b03e5Sespie       rotate_mode = HIshift;
3380c87b03e5Sespie       break;
3381c87b03e5Sespie     case SImode:
3382c87b03e5Sespie       rotate_mode = SIshift;
3383c87b03e5Sespie       break;
3384c87b03e5Sespie     default:
3385c87b03e5Sespie       abort ();
3386c87b03e5Sespie     }
3387c87b03e5Sespie 
3388c87b03e5Sespie   switch (code)
3389c87b03e5Sespie     {
3390c87b03e5Sespie     case ROTATERT:
3391c87b03e5Sespie       rotate_type = SHIFT_ASHIFT;
3392c87b03e5Sespie       break;
3393c87b03e5Sespie     case ROTATE:
3394c87b03e5Sespie       rotate_type = SHIFT_LSHIFTRT;
3395c87b03e5Sespie       break;
3396c87b03e5Sespie     default:
3397c87b03e5Sespie       abort ();
3398c87b03e5Sespie     }
3399c87b03e5Sespie 
3400c87b03e5Sespie   amount = INTVAL (rotate_amount);
3401c87b03e5Sespie 
3402c87b03e5Sespie   /* Clean up AMOUNT.  */
3403c87b03e5Sespie   if (amount < 0)
3404c87b03e5Sespie     amount = 0;
3405c87b03e5Sespie   if ((unsigned int) amount > GET_MODE_BITSIZE (mode))
3406c87b03e5Sespie     amount = GET_MODE_BITSIZE (mode);
3407c87b03e5Sespie 
3408c87b03e5Sespie   /* Determine the faster direction.  After this phase, amount will be
3409c87b03e5Sespie      at most a half of GET_MODE_BITSIZE (mode).  */
3410c87b03e5Sespie   if ((unsigned int) amount > GET_MODE_BITSIZE (mode) / (unsigned) 2)
3411c87b03e5Sespie     {
3412c87b03e5Sespie       /* Flip the direction.  */
3413c87b03e5Sespie       amount = GET_MODE_BITSIZE (mode) - amount;
3414c87b03e5Sespie       rotate_type =
3415c87b03e5Sespie 	(rotate_type == SHIFT_ASHIFT) ? SHIFT_LSHIFTRT : SHIFT_ASHIFT;
3416c87b03e5Sespie     }
3417c87b03e5Sespie 
3418c87b03e5Sespie   /* See if a byte swap (in HImode) or a word swap (in SImode) can
3419c87b03e5Sespie      boost up the rotation.  */
3420c87b03e5Sespie   if ((mode == HImode && TARGET_H8300 && amount >= 5)
3421c87b03e5Sespie       || (mode == HImode && TARGET_H8300H && amount >= 6)
3422c87b03e5Sespie       || (mode == HImode && TARGET_H8300S && amount == 8)
3423c87b03e5Sespie       || (mode == SImode && TARGET_H8300H && amount >= 10)
3424c87b03e5Sespie       || (mode == SImode && TARGET_H8300S && amount >= 13))
3425c87b03e5Sespie     {
3426c87b03e5Sespie       switch (mode)
3427c87b03e5Sespie 	{
3428c87b03e5Sespie 	case HImode:
3429c87b03e5Sespie 	  /* This code works on any family.  */
3430c87b03e5Sespie 	  insn_buf = "xor.b\t%s0,%t0\n\txor.b\t%t0,%s0\n\txor.b\t%s0,%t0";
3431c87b03e5Sespie 	  output_asm_insn (insn_buf, operands);
3432c87b03e5Sespie 	  break;
3433c87b03e5Sespie 
3434c87b03e5Sespie 	case SImode:
3435c87b03e5Sespie 	  /* This code works on the H8/300H and H8S.  */
3436c87b03e5Sespie 	  insn_buf = "xor.w\t%e0,%f0\n\txor.w\t%f0,%e0\n\txor.w\t%e0,%f0";
3437c87b03e5Sespie 	  output_asm_insn (insn_buf, operands);
3438c87b03e5Sespie 	  break;
3439c87b03e5Sespie 
3440c87b03e5Sespie 	default:
3441c87b03e5Sespie 	  abort ();
3442c87b03e5Sespie 	}
3443c87b03e5Sespie 
3444c87b03e5Sespie       /* Adjust AMOUNT and flip the direction.  */
3445c87b03e5Sespie       amount = GET_MODE_BITSIZE (mode) / 2 - amount;
3446c87b03e5Sespie       rotate_type =
3447c87b03e5Sespie 	(rotate_type == SHIFT_ASHIFT) ? SHIFT_LSHIFTRT : SHIFT_ASHIFT;
3448c87b03e5Sespie     }
3449c87b03e5Sespie 
3450c87b03e5Sespie   /* Emit rotate insns.  */
3451c87b03e5Sespie   for (bits = TARGET_H8300S ? 2 : 1; bits > 0; bits /= 2)
3452c87b03e5Sespie     {
3453c87b03e5Sespie       if (bits == 2)
3454c87b03e5Sespie 	insn_buf = rotate_two[rotate_type][rotate_mode];
3455c87b03e5Sespie       else
3456c87b03e5Sespie 	insn_buf = rotate_one[cpu_type][rotate_type][rotate_mode];
3457c87b03e5Sespie 
3458c87b03e5Sespie       for (; amount >= bits; amount -= bits)
3459c87b03e5Sespie 	output_asm_insn (insn_buf, operands);
3460c87b03e5Sespie     }
3461c87b03e5Sespie 
3462c87b03e5Sespie   return "";
3463c87b03e5Sespie }
3464c87b03e5Sespie 
3465c87b03e5Sespie /* Fix the operands of a gen_xxx so that it could become a bit
3466c87b03e5Sespie    operating insn.  */
3467c87b03e5Sespie 
3468c87b03e5Sespie int
fix_bit_operand(operands,what,type)3469c87b03e5Sespie fix_bit_operand (operands, what, type)
3470c87b03e5Sespie      rtx *operands;
3471c87b03e5Sespie      int what;
3472c87b03e5Sespie      enum rtx_code type;
3473c87b03e5Sespie {
3474c87b03e5Sespie   /* The bit_operand predicate accepts any memory during RTL generation, but
3475c87b03e5Sespie      only 'U' memory afterwards, so if this is a MEM operand, we must force
3476c87b03e5Sespie      it to be valid for 'U' by reloading the address.  */
3477c87b03e5Sespie 
3478c87b03e5Sespie   if ((what == 0 && single_zero_operand (operands[2], QImode))
3479c87b03e5Sespie       || (what == 1 && single_one_operand (operands[2], QImode)))
3480c87b03e5Sespie     {
3481c87b03e5Sespie       /* OK to have a memory dest.  */
3482c87b03e5Sespie       if (GET_CODE (operands[0]) == MEM
3483c87b03e5Sespie 	  && !EXTRA_CONSTRAINT (operands[0], 'U'))
3484c87b03e5Sespie 	{
3485c87b03e5Sespie 	  rtx mem = gen_rtx_MEM (GET_MODE (operands[0]),
3486c87b03e5Sespie 				 copy_to_mode_reg (Pmode,
3487c87b03e5Sespie 						   XEXP (operands[0], 0)));
3488c87b03e5Sespie 	  MEM_COPY_ATTRIBUTES (mem, operands[0]);
3489c87b03e5Sespie 	  operands[0] = mem;
3490c87b03e5Sespie 	}
3491c87b03e5Sespie 
3492c87b03e5Sespie       if (GET_CODE (operands[1]) == MEM
3493c87b03e5Sespie 	  && !EXTRA_CONSTRAINT (operands[1], 'U'))
3494c87b03e5Sespie 	{
3495c87b03e5Sespie 	  rtx mem = gen_rtx_MEM (GET_MODE (operands[1]),
3496c87b03e5Sespie 				 copy_to_mode_reg (Pmode,
3497c87b03e5Sespie 						   XEXP (operands[1], 0)));
3498c87b03e5Sespie 	  MEM_COPY_ATTRIBUTES (mem, operands[0]);
3499c87b03e5Sespie 	  operands[1] = mem;
3500c87b03e5Sespie 	}
3501c87b03e5Sespie       return 0;
3502c87b03e5Sespie     }
3503c87b03e5Sespie 
3504c87b03e5Sespie   /* Dest and src op must be register.  */
3505c87b03e5Sespie 
3506c87b03e5Sespie   operands[1] = force_reg (QImode, operands[1]);
3507c87b03e5Sespie   {
3508c87b03e5Sespie     rtx res = gen_reg_rtx (QImode);
3509c87b03e5Sespie     emit_insn (gen_rtx_SET (VOIDmode, res,
3510c87b03e5Sespie 			    gen_rtx (type, QImode, operands[1], operands[2])));
3511c87b03e5Sespie     emit_insn (gen_rtx_SET (VOIDmode, operands[0], res));
3512c87b03e5Sespie   }
3513c87b03e5Sespie   return 1;
3514c87b03e5Sespie }
3515c87b03e5Sespie 
3516c87b03e5Sespie /* Return nonzero if FUNC is an interrupt function as specified
3517c87b03e5Sespie    by the "interrupt" attribute.  */
3518c87b03e5Sespie 
3519c87b03e5Sespie static int
h8300_interrupt_function_p(func)3520c87b03e5Sespie h8300_interrupt_function_p (func)
3521c87b03e5Sespie      tree func;
3522c87b03e5Sespie {
3523c87b03e5Sespie   tree a;
3524c87b03e5Sespie 
3525c87b03e5Sespie   if (TREE_CODE (func) != FUNCTION_DECL)
3526c87b03e5Sespie     return 0;
3527c87b03e5Sespie 
3528c87b03e5Sespie   a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
3529c87b03e5Sespie   return a != NULL_TREE;
3530c87b03e5Sespie }
3531c87b03e5Sespie 
3532c87b03e5Sespie /* Return nonzero if FUNC is an OS_Task function as specified
3533c87b03e5Sespie    by the "OS_Task" attribute.  */
3534c87b03e5Sespie 
3535c87b03e5Sespie static int
h8300_os_task_function_p(func)3536c87b03e5Sespie h8300_os_task_function_p (func)
3537c87b03e5Sespie      tree func;
3538c87b03e5Sespie {
3539c87b03e5Sespie   tree a;
3540c87b03e5Sespie 
3541c87b03e5Sespie   if (TREE_CODE (func) != FUNCTION_DECL)
3542c87b03e5Sespie     return 0;
3543c87b03e5Sespie 
3544c87b03e5Sespie   a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
3545c87b03e5Sespie   return a != NULL_TREE;
3546c87b03e5Sespie }
3547c87b03e5Sespie 
3548c87b03e5Sespie /* Return nonzero if FUNC is a monitor function as specified
3549c87b03e5Sespie    by the "monitor" attribute.  */
3550c87b03e5Sespie 
3551c87b03e5Sespie static int
h8300_monitor_function_p(func)3552c87b03e5Sespie h8300_monitor_function_p (func)
3553c87b03e5Sespie      tree func;
3554c87b03e5Sespie {
3555c87b03e5Sespie   tree a;
3556c87b03e5Sespie 
3557c87b03e5Sespie   if (TREE_CODE (func) != FUNCTION_DECL)
3558c87b03e5Sespie     return 0;
3559c87b03e5Sespie 
3560c87b03e5Sespie   a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
3561c87b03e5Sespie   return a != NULL_TREE;
3562c87b03e5Sespie }
3563c87b03e5Sespie 
3564c87b03e5Sespie /* Return nonzero if FUNC is a function that should be called
3565c87b03e5Sespie    through the function vector.  */
3566c87b03e5Sespie 
3567c87b03e5Sespie int
h8300_funcvec_function_p(func)3568c87b03e5Sespie h8300_funcvec_function_p (func)
3569c87b03e5Sespie      tree func;
3570c87b03e5Sespie {
3571c87b03e5Sespie   tree a;
3572c87b03e5Sespie 
3573c87b03e5Sespie   if (TREE_CODE (func) != FUNCTION_DECL)
3574c87b03e5Sespie     return 0;
3575c87b03e5Sespie 
3576c87b03e5Sespie   a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
3577c87b03e5Sespie   return a != NULL_TREE;
3578c87b03e5Sespie }
3579c87b03e5Sespie 
3580c87b03e5Sespie /* Return nonzero if DECL is a variable that's in the eight bit
3581c87b03e5Sespie    data area.  */
3582c87b03e5Sespie 
3583c87b03e5Sespie int
h8300_eightbit_data_p(decl)3584c87b03e5Sespie h8300_eightbit_data_p (decl)
3585c87b03e5Sespie      tree decl;
3586c87b03e5Sespie {
3587c87b03e5Sespie   tree a;
3588c87b03e5Sespie 
3589c87b03e5Sespie   if (TREE_CODE (decl) != VAR_DECL)
3590c87b03e5Sespie     return 0;
3591c87b03e5Sespie 
3592c87b03e5Sespie   a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
3593c87b03e5Sespie   return a != NULL_TREE;
3594c87b03e5Sespie }
3595c87b03e5Sespie 
3596c87b03e5Sespie /* Return nonzero if DECL is a variable that's in the tiny
3597c87b03e5Sespie    data area.  */
3598c87b03e5Sespie 
3599c87b03e5Sespie int
h8300_tiny_data_p(decl)3600c87b03e5Sespie h8300_tiny_data_p (decl)
3601c87b03e5Sespie      tree decl;
3602c87b03e5Sespie {
3603c87b03e5Sespie   tree a;
3604c87b03e5Sespie 
3605c87b03e5Sespie   if (TREE_CODE (decl) != VAR_DECL)
3606c87b03e5Sespie     return 0;
3607c87b03e5Sespie 
3608c87b03e5Sespie   a = lookup_attribute ("tiny_data", DECL_ATTRIBUTES (decl));
3609c87b03e5Sespie   return a != NULL_TREE;
3610c87b03e5Sespie }
3611c87b03e5Sespie 
3612c87b03e5Sespie /* Generate an 'interrupt_handler' attribute for decls.  */
3613c87b03e5Sespie 
3614c87b03e5Sespie static void
h8300_insert_attributes(node,attributes)3615c87b03e5Sespie h8300_insert_attributes (node, attributes)
3616c87b03e5Sespie      tree node;
3617c87b03e5Sespie      tree *attributes;
3618c87b03e5Sespie {
3619c87b03e5Sespie   if (!interrupt_handler
3620c87b03e5Sespie       || TREE_CODE (node) != FUNCTION_DECL)
3621c87b03e5Sespie     return;
3622c87b03e5Sespie 
3623c87b03e5Sespie   /* Add an 'interrupt_handler' attribute.  */
3624c87b03e5Sespie   *attributes = tree_cons (get_identifier ("interrupt_handler"),
3625c87b03e5Sespie 			   NULL, *attributes);
3626c87b03e5Sespie }
3627c87b03e5Sespie 
3628c87b03e5Sespie /* Supported attributes:
3629c87b03e5Sespie 
3630c87b03e5Sespie    interrupt_handler: output a prologue and epilogue suitable for an
3631c87b03e5Sespie    interrupt handler.
3632c87b03e5Sespie 
3633c87b03e5Sespie    function_vector: This function should be called through the
3634c87b03e5Sespie    function vector.
3635c87b03e5Sespie 
3636c87b03e5Sespie    eightbit_data: This variable lives in the 8-bit data area and can
3637c87b03e5Sespie    be referenced with 8-bit absolute memory addresses.
3638c87b03e5Sespie 
3639c87b03e5Sespie    tiny_data: This variable lives in the tiny data area and can be
3640c87b03e5Sespie    referenced with 16-bit absolute memory references.  */
3641c87b03e5Sespie 
3642c87b03e5Sespie const struct attribute_spec h8300_attribute_table[] =
3643c87b03e5Sespie {
3644c87b03e5Sespie   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3645c87b03e5Sespie   { "interrupt_handler", 0, 0, true,  false, false, h8300_handle_fndecl_attribute },
3646c87b03e5Sespie   { "OS_Task",           0, 0, true,  false, false, h8300_handle_fndecl_attribute },
3647c87b03e5Sespie   { "monitor",           0, 0, true,  false, false, h8300_handle_fndecl_attribute },
3648c87b03e5Sespie   { "function_vector",   0, 0, true,  false, false, h8300_handle_fndecl_attribute },
3649c87b03e5Sespie   { "eightbit_data",     0, 0, true,  false, false, h8300_handle_eightbit_data_attribute },
3650c87b03e5Sespie   { "tiny_data",         0, 0, true,  false, false, h8300_handle_tiny_data_attribute },
3651c87b03e5Sespie   { NULL,                0, 0, false, false, false, NULL }
3652c87b03e5Sespie };
3653c87b03e5Sespie 
3654c87b03e5Sespie 
3655c87b03e5Sespie /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3656c87b03e5Sespie    struct attribute_spec.handler.  */
3657c87b03e5Sespie static tree
h8300_handle_fndecl_attribute(node,name,args,flags,no_add_attrs)3658c87b03e5Sespie h8300_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
3659c87b03e5Sespie      tree *node;
3660c87b03e5Sespie      tree name;
3661c87b03e5Sespie      tree args ATTRIBUTE_UNUSED;
3662c87b03e5Sespie      int flags ATTRIBUTE_UNUSED;
3663c87b03e5Sespie      bool *no_add_attrs;
3664c87b03e5Sespie {
3665c87b03e5Sespie   if (TREE_CODE (*node) != FUNCTION_DECL)
3666c87b03e5Sespie     {
3667c87b03e5Sespie       warning ("`%s' attribute only applies to functions",
3668c87b03e5Sespie 	       IDENTIFIER_POINTER (name));
3669c87b03e5Sespie       *no_add_attrs = true;
3670c87b03e5Sespie     }
3671c87b03e5Sespie 
3672c87b03e5Sespie   return NULL_TREE;
3673c87b03e5Sespie }
3674c87b03e5Sespie 
3675c87b03e5Sespie /* Handle an "eightbit_data" attribute; arguments as in
3676c87b03e5Sespie    struct attribute_spec.handler.  */
3677c87b03e5Sespie static tree
h8300_handle_eightbit_data_attribute(node,name,args,flags,no_add_attrs)3678c87b03e5Sespie h8300_handle_eightbit_data_attribute (node, name, args, flags, no_add_attrs)
3679c87b03e5Sespie      tree *node;
3680c87b03e5Sespie      tree name;
3681c87b03e5Sespie      tree args ATTRIBUTE_UNUSED;
3682c87b03e5Sespie      int flags ATTRIBUTE_UNUSED;
3683c87b03e5Sespie      bool *no_add_attrs;
3684c87b03e5Sespie {
3685c87b03e5Sespie   tree decl = *node;
3686c87b03e5Sespie 
3687c87b03e5Sespie   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
3688c87b03e5Sespie     {
3689c87b03e5Sespie       DECL_SECTION_NAME (decl) = build_string (7, ".eight");
3690c87b03e5Sespie     }
3691c87b03e5Sespie   else
3692c87b03e5Sespie     {
3693c87b03e5Sespie       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
3694c87b03e5Sespie       *no_add_attrs = true;
3695c87b03e5Sespie     }
3696c87b03e5Sespie 
3697c87b03e5Sespie   return NULL_TREE;
3698c87b03e5Sespie }
3699c87b03e5Sespie 
3700c87b03e5Sespie /* Handle an "tiny_data" attribute; arguments as in
3701c87b03e5Sespie    struct attribute_spec.handler.  */
3702c87b03e5Sespie static tree
h8300_handle_tiny_data_attribute(node,name,args,flags,no_add_attrs)3703c87b03e5Sespie h8300_handle_tiny_data_attribute (node, name, args, flags, no_add_attrs)
3704c87b03e5Sespie      tree *node;
3705c87b03e5Sespie      tree name;
3706c87b03e5Sespie      tree args ATTRIBUTE_UNUSED;
3707c87b03e5Sespie      int flags ATTRIBUTE_UNUSED;
3708c87b03e5Sespie      bool *no_add_attrs;
3709c87b03e5Sespie {
3710c87b03e5Sespie   tree decl = *node;
3711c87b03e5Sespie 
3712c87b03e5Sespie   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
3713c87b03e5Sespie     {
3714c87b03e5Sespie       DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
3715c87b03e5Sespie     }
3716c87b03e5Sespie   else
3717c87b03e5Sespie     {
3718c87b03e5Sespie       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
3719c87b03e5Sespie       *no_add_attrs = true;
3720c87b03e5Sespie     }
3721c87b03e5Sespie 
3722c87b03e5Sespie   return NULL_TREE;
3723c87b03e5Sespie }
3724c87b03e5Sespie 
3725c87b03e5Sespie static void
h8300_encode_label(decl)3726c87b03e5Sespie h8300_encode_label (decl)
3727c87b03e5Sespie      tree decl;
3728c87b03e5Sespie {
3729c87b03e5Sespie   const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
3730c87b03e5Sespie   int len = strlen (str);
3731c87b03e5Sespie   char *newstr = alloca (len + 2);
3732c87b03e5Sespie 
3733c87b03e5Sespie   newstr[0] = '&';
3734c87b03e5Sespie   strcpy (&newstr[1], str);
3735c87b03e5Sespie 
3736c87b03e5Sespie   XSTR (XEXP (DECL_RTL (decl), 0), 0) =
3737c87b03e5Sespie     ggc_alloc_string (newstr, len + 1);
3738c87b03e5Sespie }
3739c87b03e5Sespie 
3740c87b03e5Sespie /* If we are referencing a function that is supposed to be called
3741c87b03e5Sespie    through the function vector, the SYMBOL_REF_FLAG in the rtl
3742c87b03e5Sespie    so the call patterns can generate the correct code.  */
3743c87b03e5Sespie 
3744c87b03e5Sespie static void
h8300_encode_section_info(decl,first)3745c87b03e5Sespie h8300_encode_section_info (decl, first)
3746c87b03e5Sespie      tree decl;
3747c87b03e5Sespie      int first;
3748c87b03e5Sespie {
3749c87b03e5Sespie   if (TREE_CODE (decl) == FUNCTION_DECL
3750c87b03e5Sespie       && h8300_funcvec_function_p (decl))
3751c87b03e5Sespie     SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
3752c87b03e5Sespie   else if (TREE_CODE (decl) == VAR_DECL
3753c87b03e5Sespie 	   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
3754c87b03e5Sespie     {
3755c87b03e5Sespie       if (h8300_eightbit_data_p (decl))
3756c87b03e5Sespie 	SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
3757c87b03e5Sespie       else if (first && h8300_tiny_data_p (decl))
3758c87b03e5Sespie 	h8300_encode_label (decl);
3759c87b03e5Sespie     }
3760c87b03e5Sespie }
3761c87b03e5Sespie 
3762c87b03e5Sespie /* Undo the effects of the above.  */
3763c87b03e5Sespie 
3764c87b03e5Sespie static const char *
h8300_strip_name_encoding(str)3765c87b03e5Sespie h8300_strip_name_encoding (str)
3766c87b03e5Sespie      const char *str;
3767c87b03e5Sespie {
3768c87b03e5Sespie   return str + (*str == '*' || *str == '@' || *str == '&');
3769c87b03e5Sespie }
3770c87b03e5Sespie 
3771c87b03e5Sespie const char *
output_simode_bld(bild,operands)3772c87b03e5Sespie output_simode_bld (bild, operands)
3773c87b03e5Sespie      int bild;
3774c87b03e5Sespie      rtx operands[];
3775c87b03e5Sespie {
3776c87b03e5Sespie   if (TARGET_H8300)
3777c87b03e5Sespie     {
3778c87b03e5Sespie       /* Clear the destination register.  */
3779c87b03e5Sespie       output_asm_insn ("sub.w\t%e0,%e0\n\tsub.w\t%f0,%f0", operands);
3780c87b03e5Sespie 
3781c87b03e5Sespie       /* Now output the bit load or bit inverse load, and store it in
3782c87b03e5Sespie 	 the destination.  */
3783c87b03e5Sespie       if (bild)
3784c87b03e5Sespie 	output_asm_insn ("bild\t%Z2,%Y1", operands);
3785c87b03e5Sespie       else
3786c87b03e5Sespie 	output_asm_insn ("bld\t%Z2,%Y1", operands);
3787c87b03e5Sespie 
3788c87b03e5Sespie       output_asm_insn ("bst\t#0,%w0", operands);
3789c87b03e5Sespie     }
3790c87b03e5Sespie   else
3791c87b03e5Sespie     {
3792c87b03e5Sespie       /* Output the bit load or bit inverse load.  */
3793c87b03e5Sespie       if (bild)
3794c87b03e5Sespie 	output_asm_insn ("bild\t%Z2,%Y1", operands);
3795c87b03e5Sespie       else
3796c87b03e5Sespie 	output_asm_insn ("bld\t%Z2,%Y1", operands);
3797c87b03e5Sespie 
3798c87b03e5Sespie       /* Clear the destination register and perform the bit store.  */
3799c87b03e5Sespie       output_asm_insn ("xor.l\t%S0,%S0\n\tbst\t#0,%w0", operands);
3800c87b03e5Sespie     }
3801c87b03e5Sespie 
3802c87b03e5Sespie   /* All done.  */
3803c87b03e5Sespie   return "";
3804c87b03e5Sespie }
3805c87b03e5Sespie 
3806c87b03e5Sespie /* Given INSN and its current length LENGTH, return the adjustment
3807c87b03e5Sespie    (in bytes) to correctly compute INSN's length.
3808c87b03e5Sespie 
3809c87b03e5Sespie    We use this to get the lengths of various memory references correct.  */
3810c87b03e5Sespie 
3811c87b03e5Sespie int
h8300_adjust_insn_length(insn,length)3812c87b03e5Sespie h8300_adjust_insn_length (insn, length)
3813c87b03e5Sespie      rtx insn;
3814c87b03e5Sespie      int length ATTRIBUTE_UNUSED;
3815c87b03e5Sespie {
3816c87b03e5Sespie   rtx pat = PATTERN (insn);
3817c87b03e5Sespie 
3818c87b03e5Sespie   /* We must filter these out before calling get_attr_adjust_length.  */
3819c87b03e5Sespie   if (GET_CODE (pat) == USE
3820c87b03e5Sespie       || GET_CODE (pat) == CLOBBER
3821c87b03e5Sespie       || GET_CODE (pat) == SEQUENCE
3822c87b03e5Sespie       || GET_CODE (pat) == ADDR_VEC
3823c87b03e5Sespie       || GET_CODE (pat) == ADDR_DIFF_VEC)
3824c87b03e5Sespie     return 0;
3825c87b03e5Sespie 
3826c87b03e5Sespie   if (get_attr_adjust_length (insn) == ADJUST_LENGTH_NO)
3827c87b03e5Sespie     return 0;
3828c87b03e5Sespie 
3829c87b03e5Sespie   /* Adjust length for reg->mem and mem->reg copies.  */
3830c87b03e5Sespie   if (GET_CODE (pat) == SET
3831c87b03e5Sespie       && (GET_CODE (SET_SRC (pat)) == MEM
3832c87b03e5Sespie 	  || GET_CODE (SET_DEST (pat)) == MEM))
3833c87b03e5Sespie     {
3834c87b03e5Sespie       /* This insn might need a length adjustment.  */
3835c87b03e5Sespie       rtx addr;
3836c87b03e5Sespie 
3837c87b03e5Sespie       if (GET_CODE (SET_SRC (pat)) == MEM)
3838c87b03e5Sespie 	addr = XEXP (SET_SRC (pat), 0);
3839c87b03e5Sespie       else
3840c87b03e5Sespie 	addr = XEXP (SET_DEST (pat), 0);
3841c87b03e5Sespie 
3842c87b03e5Sespie       if (TARGET_H8300)
3843c87b03e5Sespie 	{
3844c87b03e5Sespie 	  /* On the H8/300, we subtract the difference between the
3845c87b03e5Sespie              actual length and the longest one, which is @(d:16,ERs).  */
3846c87b03e5Sespie 
3847c87b03e5Sespie 	  /* @Rs is 2 bytes shorter than the longest.  */
3848c87b03e5Sespie 	  if (GET_CODE (addr) == REG)
3849c87b03e5Sespie 	    return -2;
3850c87b03e5Sespie 
3851c87b03e5Sespie 	  /* @aa:8 is 2 bytes shorter than the longest.  */
3852c87b03e5Sespie 	  if (GET_MODE (SET_SRC (pat)) == QImode
3853c87b03e5Sespie 	      && h8300_eightbit_constant_address_p (addr))
3854c87b03e5Sespie 	    return -2;
3855c87b03e5Sespie 	}
3856c87b03e5Sespie       else
3857c87b03e5Sespie 	{
3858c87b03e5Sespie 	  /* On the H8/300H and H8S, we subtract the difference
3859c87b03e5Sespie              between the actual length and the longest one, which is
3860c87b03e5Sespie              @(d:24,ERs).  */
3861c87b03e5Sespie 
3862c87b03e5Sespie 	  /* @ERs is 6 bytes shorter than the longest.  */
3863c87b03e5Sespie 	  if (GET_CODE (addr) == REG)
3864c87b03e5Sespie 	    return -6;
3865c87b03e5Sespie 
3866c87b03e5Sespie 	  /* @(d:16,ERs) is 6 bytes shorter than the longest.  */
3867c87b03e5Sespie 	  if (GET_CODE (addr) == PLUS
3868c87b03e5Sespie 	      && GET_CODE (XEXP (addr, 0)) == REG
3869c87b03e5Sespie 	      && GET_CODE (XEXP (addr, 1)) == CONST_INT
3870c87b03e5Sespie 	      && INTVAL (XEXP (addr, 1)) > -32768
3871c87b03e5Sespie 	      && INTVAL (XEXP (addr, 1)) < 32767)
3872c87b03e5Sespie 	    return -4;
3873c87b03e5Sespie 
3874c87b03e5Sespie 	  /* @aa:8 is 6 bytes shorter than the longest.  */
3875c87b03e5Sespie 	  if (GET_MODE (SET_SRC (pat)) == QImode
3876c87b03e5Sespie 	      && h8300_eightbit_constant_address_p (addr))
3877c87b03e5Sespie 	    return -6;
3878c87b03e5Sespie 
3879c87b03e5Sespie 	  /* @aa:16 is 4 bytes shorter than the longest.  */
3880c87b03e5Sespie 	  if (h8300_tiny_constant_address_p (addr))
3881c87b03e5Sespie 	    return -4;
3882c87b03e5Sespie 
3883c87b03e5Sespie 	  /* @aa:24 is 2 bytes shorter than the longest.  */
3884c87b03e5Sespie 	  if (GET_CODE (addr) == CONST_INT)
3885c87b03e5Sespie 	    return -2;
3886c87b03e5Sespie 	}
3887c87b03e5Sespie     }
3888c87b03e5Sespie 
3889c87b03e5Sespie   /* Loading some constants needs adjustment.  */
3890c87b03e5Sespie   if (GET_CODE (pat) == SET
3891c87b03e5Sespie       && GET_CODE (SET_SRC (pat)) == CONST_INT
3892c87b03e5Sespie       && GET_MODE (SET_DEST (pat)) == SImode
3893c87b03e5Sespie       && INTVAL (SET_SRC (pat)) != 0)
3894c87b03e5Sespie     {
3895c87b03e5Sespie       int val = INTVAL (SET_SRC (pat));
3896c87b03e5Sespie 
3897c87b03e5Sespie       if (TARGET_H8300
3898c87b03e5Sespie 	  && ((val & 0xffff) == 0
3899c87b03e5Sespie 	      || ((val >> 16) & 0xffff) == 0))
3900c87b03e5Sespie 	return -2;
3901c87b03e5Sespie 
3902c87b03e5Sespie       if (TARGET_H8300H || TARGET_H8300S)
3903c87b03e5Sespie 	{
3904c87b03e5Sespie 	  if (val == (val & 0xff)
3905c87b03e5Sespie 	      || val == (val & 0xff00))
3906c87b03e5Sespie 	    return 4 - 6;
3907c87b03e5Sespie 
3908c87b03e5Sespie 	  switch (val & 0xffffffff)
3909c87b03e5Sespie 	    {
3910c87b03e5Sespie 	    case 0xffffffff:
3911c87b03e5Sespie 	    case 0xfffffffe:
3912c87b03e5Sespie 	    case 0xfffffffc:
3913c87b03e5Sespie 	    case 0x0000ffff:
3914c87b03e5Sespie 	    case 0x0000fffe:
3915c87b03e5Sespie 	    case 0xffff0000:
3916c87b03e5Sespie 	    case 0xfffe0000:
3917c87b03e5Sespie 	    case 0x00010000:
3918c87b03e5Sespie 	    case 0x00020000:
3919c87b03e5Sespie 	      return 4 - 6;
3920c87b03e5Sespie 	    }
3921c87b03e5Sespie 	}
3922c87b03e5Sespie     }
3923c87b03e5Sespie 
3924c87b03e5Sespie   /* Rotations need various adjustments.  */
3925c87b03e5Sespie   if (GET_CODE (pat) == SET
3926c87b03e5Sespie       && (GET_CODE (SET_SRC (pat)) == ROTATE
3927c87b03e5Sespie 	  || GET_CODE (SET_SRC (pat)) == ROTATERT))
3928c87b03e5Sespie     {
3929c87b03e5Sespie       rtx src = SET_SRC (pat);
3930c87b03e5Sespie       enum machine_mode mode = GET_MODE (src);
3931c87b03e5Sespie       int amount;
3932c87b03e5Sespie       int states = 0;
3933c87b03e5Sespie 
3934c87b03e5Sespie       if (GET_CODE (XEXP (src, 1)) != CONST_INT)
3935c87b03e5Sespie 	return 0;
3936c87b03e5Sespie 
3937c87b03e5Sespie       amount = INTVAL (XEXP (src, 1));
3938c87b03e5Sespie 
3939c87b03e5Sespie       /* Clean up AMOUNT.  */
3940c87b03e5Sespie       if (amount < 0)
3941c87b03e5Sespie 	amount = 0;
3942c87b03e5Sespie       if ((unsigned int) amount > GET_MODE_BITSIZE (mode))
3943c87b03e5Sespie 	amount = GET_MODE_BITSIZE (mode);
3944c87b03e5Sespie 
3945c87b03e5Sespie       /* Determine the faster direction.  After this phase, amount
3946c87b03e5Sespie 	 will be at most a half of GET_MODE_BITSIZE (mode).  */
3947c87b03e5Sespie       if ((unsigned int) amount > GET_MODE_BITSIZE (mode) / (unsigned) 2)
3948c87b03e5Sespie 	/* Flip the direction.  */
3949c87b03e5Sespie 	amount = GET_MODE_BITSIZE (mode) - amount;
3950c87b03e5Sespie 
3951c87b03e5Sespie       /* See if a byte swap (in HImode) or a word swap (in SImode) can
3952c87b03e5Sespie 	 boost up the rotation.  */
3953c87b03e5Sespie       if ((mode == HImode && TARGET_H8300 && amount >= 5)
3954c87b03e5Sespie 	  || (mode == HImode && TARGET_H8300H && amount >= 6)
3955c87b03e5Sespie 	  || (mode == HImode && TARGET_H8300S && amount == 8)
3956c87b03e5Sespie 	  || (mode == SImode && TARGET_H8300H && amount >= 10)
3957c87b03e5Sespie 	  || (mode == SImode && TARGET_H8300S && amount >= 13))
3958c87b03e5Sespie 	{
3959c87b03e5Sespie 	  /* Adjust AMOUNT and flip the direction.  */
3960c87b03e5Sespie 	  amount = GET_MODE_BITSIZE (mode) / 2 - amount;
3961c87b03e5Sespie 	  states += 6;
3962c87b03e5Sespie 	}
3963c87b03e5Sespie 
3964c87b03e5Sespie       /* We use 2-bit rotatations on the H8S.  */
3965c87b03e5Sespie       if (TARGET_H8300S)
3966c87b03e5Sespie 	amount = amount / 2 + amount % 2;
3967c87b03e5Sespie 
3968c87b03e5Sespie       /* The H8/300 uses three insns to rotate one bit, taking 6
3969c87b03e5Sespie          states.  */
3970c87b03e5Sespie       states += amount * ((TARGET_H8300 && mode == HImode) ? 6 : 2);
3971c87b03e5Sespie 
3972c87b03e5Sespie       return -(20 - states);
3973c87b03e5Sespie     }
3974c87b03e5Sespie 
3975c87b03e5Sespie   return 0;
3976c87b03e5Sespie }
3977c87b03e5Sespie 
3978c87b03e5Sespie #ifndef OBJECT_FORMAT_ELF
3979c87b03e5Sespie static void
h8300_asm_named_section(name,flags)3980c87b03e5Sespie h8300_asm_named_section (name, flags)
3981c87b03e5Sespie      const char *name;
3982c87b03e5Sespie      unsigned int flags ATTRIBUTE_UNUSED;
3983c87b03e5Sespie {
3984c87b03e5Sespie   /* ??? Perhaps we should be using default_coff_asm_named_section.  */
3985c87b03e5Sespie   fprintf (asm_out_file, "\t.section %s\n", name);
3986c87b03e5Sespie }
3987c87b03e5Sespie #endif /* ! OBJECT_FORMAT_ELF */
3988c87b03e5Sespie 
3989c87b03e5Sespie /* Nonzero if X is a constant address suitable as an 8-bit absolute,
3990c87b03e5Sespie    which is a special case of the 'R' operand.  */
3991c87b03e5Sespie 
3992c87b03e5Sespie int
h8300_eightbit_constant_address_p(x)3993c87b03e5Sespie h8300_eightbit_constant_address_p (x)
3994c87b03e5Sespie      rtx x;
3995c87b03e5Sespie {
3996c87b03e5Sespie   /* The ranges of the 8-bit area. */
3997c87b03e5Sespie   const unsigned HOST_WIDE_INT n1 = trunc_int_for_mode (0xff00, HImode);
3998c87b03e5Sespie   const unsigned HOST_WIDE_INT n2 = trunc_int_for_mode (0xffff, HImode);
3999c87b03e5Sespie   const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode (0x00ffff00, SImode);
4000c87b03e5Sespie   const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode (0x00ffffff, SImode);
4001c87b03e5Sespie   const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode (0xffffff00, SImode);
4002c87b03e5Sespie   const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode (0xffffffff, SImode);
4003c87b03e5Sespie 
4004c87b03e5Sespie   unsigned HOST_WIDE_INT addr;
4005c87b03e5Sespie 
4006c87b03e5Sespie   /* We accept symbols declared with eightbit_data.  */
4007c87b03e5Sespie   if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))
4008c87b03e5Sespie     return 1;
4009c87b03e5Sespie 
4010c87b03e5Sespie   if (GET_CODE (x) != CONST_INT)
4011c87b03e5Sespie     return 0;
4012c87b03e5Sespie 
4013c87b03e5Sespie   addr = INTVAL (x);
4014c87b03e5Sespie 
4015c87b03e5Sespie   return (0
4016c87b03e5Sespie 	  || ((TARGET_H8300 || TARGET_NORMAL_MODE) && IN_RANGE (addr, n1, n2))
4017c87b03e5Sespie 	  || (TARGET_H8300H && IN_RANGE (addr, h1, h2))
4018c87b03e5Sespie 	  || (TARGET_H8300S && IN_RANGE (addr, s1, s2)));
4019c87b03e5Sespie }
4020c87b03e5Sespie 
4021c87b03e5Sespie /* Nonzero if X is a constant address suitable as an 16-bit absolute
4022c87b03e5Sespie    on H8/300H and H8S.  */
4023c87b03e5Sespie 
4024c87b03e5Sespie int
h8300_tiny_constant_address_p(x)4025c87b03e5Sespie h8300_tiny_constant_address_p (x)
4026c87b03e5Sespie      rtx x;
4027c87b03e5Sespie {
4028c87b03e5Sespie   /* The ranges of the 16-bit area.  */
4029c87b03e5Sespie   const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode (0x00000000, SImode);
4030c87b03e5Sespie   const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode (0x00007fff, SImode);
4031c87b03e5Sespie   const unsigned HOST_WIDE_INT h3 = trunc_int_for_mode (0x00ff8000, SImode);
4032c87b03e5Sespie   const unsigned HOST_WIDE_INT h4 = trunc_int_for_mode (0x00ffffff, SImode);
4033c87b03e5Sespie   const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode (0x00000000, SImode);
4034c87b03e5Sespie   const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode (0x00007fff, SImode);
4035c87b03e5Sespie   const unsigned HOST_WIDE_INT s3 = trunc_int_for_mode (0xffff8000, SImode);
4036c87b03e5Sespie   const unsigned HOST_WIDE_INT s4 = trunc_int_for_mode (0xffffffff, SImode);
4037c87b03e5Sespie 
4038c87b03e5Sespie   unsigned HOST_WIDE_INT addr;
4039c87b03e5Sespie 
4040c87b03e5Sespie   /* We accept symbols declared with tiny_data.  */
4041c87b03e5Sespie   if (GET_CODE (x) == SYMBOL_REF && TINY_DATA_NAME_P (XSTR (x, 0)))
4042c87b03e5Sespie     return 1;
4043c87b03e5Sespie 
4044c87b03e5Sespie   if (GET_CODE (x) != CONST_INT)
4045c87b03e5Sespie     return 0;
4046c87b03e5Sespie 
4047c87b03e5Sespie   addr = INTVAL (x);
4048c87b03e5Sespie 
4049c87b03e5Sespie   return (0
4050c87b03e5Sespie 	  || ((TARGET_H8300H && !TARGET_NORMAL_MODE)
4051c87b03e5Sespie 	      && (IN_RANGE (addr, h1, h2) || IN_RANGE (addr, h3, h4)))
4052c87b03e5Sespie 	  || ((TARGET_H8300S && !TARGET_NORMAL_MODE)
4053c87b03e5Sespie 	      && (IN_RANGE (addr, s1, s2) || IN_RANGE (addr, s3, s4))));
4054c87b03e5Sespie }
4055